diff --git a/backup/moodle2/backup_questionnaire_stepslib.php b/backup/moodle2/backup_questionnaire_stepslib.php
index 747b304b..430fe151 100644
--- a/backup/moodle2/backup_questionnaire_stepslib.php
+++ b/backup/moodle2/backup_questionnaire_stepslib.php
@@ -39,7 +39,7 @@ protected function define_structure() {
$questionnaire = new backup_nested_element('questionnaire', array('id'), array(
'course', 'name', 'intro', 'introformat', 'qtype',
'respondenttype', 'resp_eligible', 'resp_view', 'notifications', 'opendate',
- 'closedate', 'resume', 'navigate', 'grade', 'sid', 'timemodified', 'completionsubmit', 'autonum'));
+ 'closedate', 'resume', 'navigate', 'grade', 'sid', 'timemodified', 'completionsubmit', 'autonum', 'removeafter'));
$surveys = new backup_nested_element('surveys');
diff --git a/classes/task/cleanup.php b/classes/task/cleanup.php
index 7cd40678..d11b95c8 100644
--- a/classes/task/cleanup.php
+++ b/classes/task/cleanup.php
@@ -43,5 +43,6 @@ public function execute() {
require_once($CFG->dirroot . '/mod/questionnaire/locallib.php');
questionnaire_cleanup();
+ questionnaire_delete_old_responses();
}
}
diff --git a/db/install.xml b/db/install.xml
index a1b7af0b..e5892b26 100644
--- a/db/install.xml
+++ b/db/install.xml
@@ -26,6 +26,7 @@
+
diff --git a/db/upgrade.php b/db/upgrade.php
index dd5fd989..ce1ecd26 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -1002,6 +1002,20 @@ function xmldb_questionnaire_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2022121600.02, 'questionnaire');
}
+ if ($oldversion < 2024060400.00) {
+ // Add removeafter fields.
+ $table = new xmldb_table('questionnaire');
+ $field = new xmldb_field('removeafter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0, 'progressbar');
+
+ // Conditionally launch add field.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Questionnaire savepoint reached.
+ upgrade_mod_savepoint(true, 2024060400.00, 'questionnaire');
+ }
+
return true;
}
diff --git a/lang/en/questionnaire.php b/lang/en/questionnaire.php
index 7de8d9f7..51e9e6f1 100644
--- a/lang/en/questionnaire.php
+++ b/lang/en/questionnaire.php
@@ -118,6 +118,7 @@
$string['createcontent_help'] = 'Select one of the radio button options. \'Create new\' is the default.';
$string['createcontent_link'] = 'mod/questionnaire/mod#Content_Options';
$string['createnew'] = 'Create new';
+$string['configremoveoldresponses'] = 'Setting which will be used as default on all new questionares.';
$string['centerlabel'] = 'Centre label';
$string['date'] = 'Date';
$string['date_help'] = 'Use this question type if you expect the response to be a correctly formatted date.';
@@ -403,6 +404,7 @@
$string['overviewnumrespvw'] = 'responses';
$string['overviewnumrespvw1'] = 'response';
$string['owner'] = 'Owner';
+$string['onemonth'] = '1 month';
$string['page'] = 'Page';
$string['pageof'] = 'Page {$a->page} of {$a->totpages}';
$string['parent'] = 'Parent';
@@ -566,6 +568,10 @@
$string['resume_link'] = 'mod/questionnaire/mod#Save/Resume_answers';
$string['resumesurvey'] = 'Resume questionnaire';
$string['return'] = 'Return';
+$string['removeoldresponsesdefault'] = 'Never remove';
+$string['removeoldresponses'] = 'Manage old responses';
+$string['removeoldresponsesafter'] = 'Manage old responses after';
+$string['removeoldresponses_help'] = 'The system can automatically remove responses after a certain length of time.';
$string['rightlabel'] = 'Right label';
$string['rightpart'] = ' and {$a->max} is {$a->rightlabel}';
$string['rightpartdefault'] = ' and {$a->max} is maximum slider range';
diff --git a/locallib.php b/locallib.php
index 4fce8590..830dfa5f 100644
--- a/locallib.php
+++ b/locallib.php
@@ -949,3 +949,63 @@ function questionnaire_get_standard_page_items($id = null, $a = null) {
return (array($cm, $course, $questionnaire));
}
+
+
+/**
+ * Create options for remove old responses in the questionare.
+ *
+ * @return array
+ */
+function questionnaire_create_remove_options() {
+ $options = [];
+ $options[0] = get_string('removeoldresponsesdefault', 'questionnaire');
+ for ($i = 1; $i <= 36; $i++) {
+ $options[$i * 2592000] = $i > 1 ? get_string('nummonths', 'moodle', $i) : get_string('onemonth', 'questionnaire');
+ }
+ return $options;
+}
+
+/**
+ * Delete all the old responses when we have setting the questionnaire.
+ *
+ * @throws coding_exception
+ * @throws dml_exception
+ */
+function questionnaire_delete_old_responses() {
+ global $DB;
+ $currenttime = time();
+
+ $sql = "SELECT qr.id
+ FROM {questionnaire} q
+ JOIN {questionnaire_response} qr ON qr.questionnaireid = q.id AND qr.complete = 'y'
+ WHERE q.removeafter <> 0 AND (q.removeafter < :currettime - qr.submitted)";
+ // Get all old response from questionnaires.
+ $oldresponsesid = $DB->get_records_sql($sql, ['currettime' => $currenttime]);
+ if (!empty($oldresponsesid)) {
+ try {
+ $oldresponsesid = array_keys($oldresponsesid);
+ $count = count($oldresponsesid);
+ if (!PHPUNIT_TEST) {
+ mtrace("\nBeginning deleting $count old responses requests");
+ }
+ // Delete all of the response data for a response.
+ $responsetables = [
+ 'questionnaire_response_bool', 'questionnaire_response_date', 'questionnaire_resp_multiple',
+ 'questionnaire_response_other', 'questionnaire_response_rank', 'questionnaire_resp_single',
+ 'questionnaire_response_text'];
+ list ($sqlparam, $params) = $DB->get_in_or_equal($oldresponsesid, SQL_PARAMS_QM);
+ foreach ($responsetables as $tablename) {
+ $sql = "DELETE FROM {{$tablename}} WHERE response_id $sqlparam";
+ $DB->execute($sql, $params);
+ }
+ // Delete the response from the main table.
+ $sql = "DELETE FROM {questionnaire_response} WHERE id $sqlparam";
+ $DB->execute($sql, $params);
+ if (!PHPUNIT_TEST) {
+ mtrace("\nCompleted deleting $count old responses requests");
+ }
+ } catch (\dml_exception $ex) {
+ debugging('Error: ' . $ex->getMessage(), DEBUG_DEVELOPER);
+ }
+ }
+}
diff --git a/mod_form.php b/mod_form.php
index 26fcd227..d4132dda 100644
--- a/mod_form.php
+++ b/mod_form.php
@@ -34,7 +34,7 @@ class mod_questionnaire_mod_form extends moodleform_mod {
* Form definition.
*/
protected function definition() {
- global $COURSE;
+ global $COURSE, $CFG;
global $questionnairetypes, $questionnairerespondents, $questionnaireresponseviewers, $autonumbering;
$questionnaire = new questionnaire($COURSE, $this->_cm, $this->_instance, null);
@@ -142,6 +142,17 @@ protected function definition() {
$mform->setDefault('create', 'new-0');
}
+ // Remove old responses.
+ $options = questionnaire_create_remove_options();
+ $mform->addElement('header', 'responsehdr', get_string('removeoldresponses', 'questionnaire'));
+ $mform->addElement('select', 'removeafter',
+ get_string('removeoldresponsesafter', 'questionnaire'), $options);
+ $mform->addHelpButton('removeafter', 'removeoldresponses', 'questionnaire');
+ // Just set default value when creating a new questionare.
+ if (empty($questionnaire->sid)) {
+ $defaultconfig = get_config('questionnaire', 'removeoldresponses');
+ $mform->setDefault('removeafter', $defaultconfig);
+ }
$this->standard_coursemodule_elements();
// Buttons.
@@ -223,4 +234,18 @@ public function completion_rule_enabled($data) {
return !empty($data['completionsubmit']);
}
+ /**
+ * Create options for remove old responses in the questionare.
+ *
+ * @return array
+ */
+ public function create_remove_options() {
+ $options = [];
+ $options[0] = get_string('removeoldresponsesdefault', 'questionnaire');
+ for ($i = 1; $i <= 36; $i++) {
+ $options[$i * 2592000] = $i > 1 ? get_string('nummonths', 'moodle', $i) : get_string('onemonth', 'questionnaire');
+ }
+ return $options;
+ }
+
}
diff --git a/settings.php b/settings.php
index 6a21c51d..c98fc35b 100644
--- a/settings.php
+++ b/settings.php
@@ -24,6 +24,7 @@
*/
defined('MOODLE_INTERNAL') || die;
+require_once($CFG->dirroot . '/mod/questionnaire/locallib.php');
if ($ADMIN->fulltree) {
$options = array(0 => get_string('no'), 1 => get_string('yes'));
@@ -52,4 +53,10 @@
$settings->add(new admin_setting_configcheckbox('questionnaire/allowemailreporting',
get_string('configemailreporting', 'questionnaire'), get_string('configemailreportinglong', 'questionnaire'), 0));
+
+ // Manage old responses after. The default value is 24 months.
+ $options = questionnaire_create_remove_options();
+ $settings->add(new admin_setting_configselect('questionnaire/removeoldresponses',
+ get_string('removeoldresponsesafter', 'questionnaire'),
+ get_string('configremoveoldresponses', 'questionnaire'), 0, $options));
}
diff --git a/tests/responsetypes_test.php b/tests/responsetypes_test.php
index e10db5ef..3d95409e 100644
--- a/tests/responsetypes_test.php
+++ b/tests/responsetypes_test.php
@@ -419,4 +419,55 @@ private function response_tests($questionnaireid, $responseid, $userid,
$this->assertArrayHasKey($responseid, $responses);
$this->assertEquals($responseid, $responses[$responseid]->id);
}
+
+ public function test_create_old_response_boolean() {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ // Some common variables used below.
+ $userid = 1;
+
+ // Set up a questinnaire with one boolean response question.
+ $course = $this->getDataGenerator()->create_course();
+ $generator = $this->getDataGenerator()->get_plugin_generator('mod_questionnaire');
+ // Add a questionnaire that will delete old responses after one month.
+ $questionnaire1 = $generator->create_test_questionnaire($course, QUESYESNO, ['content' => 'Enter yes or no']);
+ $question1 = reset($questionnaire1->questions);
+ $response1 = $generator->create_question_response($questionnaire1, $question1, 'y', $userid);
+
+ $questionnaire2 = $generator->create_test_questionnaire($course, QUESYESNO, ['content' => 'Enter yes or no']);
+ $question2 = reset($questionnaire2->questions);
+ $response2 = $generator->create_question_response($questionnaire2, $question2, 'y', $userid);
+
+ $this->response_tests($questionnaire1->id, $response1->id, $userid);
+ $this->response_tests($questionnaire2->id, $response2->id, $userid);
+
+ // Set the removeafterfield for questionnaires.
+ $newquestionairre1 = new \stdClass();
+ $newquestionairre1->id = $questionnaire1->id;
+ $newquestionairre1->removeafter = 2592000;
+ $newquestionairre2 = new \stdClass();
+ $newquestionairre2->id = $questionnaire2->id;
+ $newquestionairre2->removeafter = 2592000;
+ $DB->update_record('questionnaire', $newquestionairre1);
+ $DB->update_record('questionnaire', $newquestionairre2);
+ // Retrieve the specific boolean response.
+ $booleanresponses1 = $DB->get_record('questionnaire_response', ['id' => $response1->id]);
+ $booleanresponses2 = $DB->get_record('questionnaire_response', ['id' => $response2->id]);
+ // Set the submitted time to 31 day in the past.
+ $booleanresponses1->submitted = $booleanresponses1->submitted - 2592000 - 86400;
+ $booleanresponses2->submitted = $booleanresponses2->submitted - 2592000 - 86400;
+ $DB->update_record('questionnaire_response', $booleanresponses1);
+ $DB->update_record('questionnaire_response', $booleanresponses2);
+ questionnaire_delete_old_responses();
+ $responseresult1 = $DB->record_exists('questionnaire_response', ['id' => $response1->id]);
+ $responseresult2 = $DB->record_exists('questionnaire_response', ['id' => $response2->id]);
+ $this->assertEmpty($responseresult1);
+ $this->assertEmpty($responseresult2);
+ $boolresponseresult1 = $DB->record_exists('questionnaire_response_bool', ['response_id' => $response1->id]);
+ $boolresponseresult2 = $DB->record_exists('questionnaire_response_bool', ['response_id' => $response2->id]);
+ $this->assertEmpty($boolresponseresult1);
+ $this->assertEmpty($boolresponseresult2);
+ }
}
diff --git a/version.php b/version.php
index ac5eb9bf..1dbadc50 100644
--- a/version.php
+++ b/version.php
@@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2022121600.02; // The current module version (Date: YYYYMMDDXX).
+$plugin->version = 2024060400.00; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2022112800.00; // Moodle version (4.1.0).
$plugin->component = 'mod_questionnaire';