diff --git a/backup/moodle2/backup_questionnaire_stepslib.php b/backup/moodle2/backup_questionnaire_stepslib.php
index 0b0dafe9..db7bd5e5 100644
--- a/backup/moodle2/backup_questionnaire_stepslib.php
+++ b/backup/moodle2/backup_questionnaire_stepslib.php
@@ -41,7 +41,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 1dc8396e..029f5adf 100644
--- a/classes/task/cleanup.php
+++ b/classes/task/cleanup.php
@@ -41,5 +41,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 ca290ae7..b8796ef1 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -979,6 +979,20 @@ function xmldb_questionnaire_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2020062301, 'questionnaire');
}
+ if ($oldversion < 2021092800) {
+ // 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, 2021092800, 'questionnaire');
+ }
+
return $result;
}
diff --git a/lang/en/questionnaire.php b/lang/en/questionnaire.php
index 7ac3af8b..f1419033 100644
--- a/lang/en/questionnaire.php
+++ b/lang/en/questionnaire.php
@@ -117,6 +117,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['date'] = 'Date';
$string['date_help'] = 'Use this question type if you expect the response to be a correctly formatted date.';
$string['date_link'] = 'mod/questionnaire/questions#Date';
@@ -385,6 +386,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';
@@ -548,6 +550,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['save'] = 'Save';
$string['saveasnew'] = 'Save as New Question';
$string['savedbutnotsubmitted'] = 'This questionnaire has been saved but not yet submitted.';
diff --git a/locallib.php b/locallib.php
index 42879e67..bf0ae907 100644
--- a/locallib.php
+++ b/locallib.php
@@ -879,3 +879,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}} r WHERE r.response_id $sqlparam";
+ $DB->execute($sql, $params);
+ }
+ // Delete the response from the main table.
+ $sql = "DELETE FROM {questionnaire_response} r WHERE r.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 b7053639..77000ee4 100644
--- a/mod_form.php
+++ b/mod_form.php
@@ -31,7 +31,7 @@
class mod_questionnaire_mod_form extends moodleform_mod {
protected function definition() {
- global $COURSE;
+ global $COURSE, $CFG;
global $questionnairetypes, $questionnairerespondents, $questionnaireresponseviewers, $autonumbering;
$questionnaire = new questionnaire($this->_instance, null, $COURSE, $this->_cm);
@@ -139,6 +139,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.
@@ -198,4 +209,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 1b61f757..10e4a881 100644
--- a/settings.php
+++ b/settings.php
@@ -23,6 +23,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'));
@@ -50,4 +51,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 fb1c78e0..69ba11ed 100644
--- a/tests/responsetypes_test.php
+++ b/tests/responsetypes_test.php
@@ -316,4 +316,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 3b5a4b7c..dcb05d32 100644
--- a/version.php
+++ b/version.php
@@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2020111101; // The current module version (Date: YYYYMMDDXX).
+$plugin->version = 2021092800; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2020061500; // Moodle version (3.9).
$plugin->component = 'mod_questionnaire';