diff --git a/lang/en/ratingallocate.php b/lang/en/ratingallocate.php index e49e6276..325b03e9 100644 --- a/lang/en/ratingallocate.php +++ b/lang/en/ratingallocate.php @@ -461,3 +461,7 @@ and ratable choices by groups that had the ability to access them. * Only groups used in the *use groups* option can be selected. * If *no group* is selected, users that are in none of the groups used by a choice are shown.'; + +// Language Strings for resetting. +$string['remove_ratings_and_allocations'] = 'Delete all ratings and allocations'; +$string['ratings_and_allocations_deleted'] = 'Ratings and allocations deleted'; diff --git a/lib.php b/lib.php index bb1ba248..71446a3d 100644 --- a/lib.php +++ b/lib.php @@ -663,3 +663,74 @@ function mod_ratingallocate_core_calendar_get_valid_event_timestart_range (\cale } return [$mindate, $maxdate]; } + +/** + * This function is used by the reset_course_userdata function in moodlelib. + * This function will remove all ratings and allocations + * and clean up any related data. + * + * @global object + * @global object + * @param $data stdClass the data submitted from the reset course. + * @return array status array + */ +function ratingallocate_reset_userdata($data) { + global $CFG, $DB; + + $componentstr = get_string('modulenameplural', RATINGALLOCATE_MOD_NAME); + $status = []; + + $params = array('courseid' => $data->courseid); + + if (!empty($data->reset_ratings_and_allocations)) { + + // Delete all ratings. + $ratingidssql = "SELECT r.id FROM {ratingallocate_ratings} r + INNER JOIN {ratingallocate_choices} c ON r.choiceid=c.id + INNER JOIN {ratingallocate} ra ON c.ratingallocateid=ra.id + WHERE ra.course= :courseid"; + $DB->delete_records_select('ratingallocate_ratings', "id IN ($ratingidssql)", $params); + + // Delete all allocations. + $allocationidssql = "SELECT a.id FROM {ratingallocate_allocations} a + INNER JOIN {ratingallocate} r ON a.ratingallocateid=r.id + WHERE r.course= :courseid"; + $DB->delete_records_select('ratingallocate_allocations', "id IN ($allocationidssql)", $params); + + $status[] = [ + 'component' => $componentstr, + 'item' => get_string('ratings_and_allocations_deleted', RATINGALLOCATE_MOD_NAME), + 'error' => false]; + } + + // Updating dates - shift may be negative too. + if ($data->timeshift) { + // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. + // See MDL-9367. + shift_course_mod_dates(RATINGALLOCATE_MOD_NAME, array('accesstimestart', 'accesstimestop'), $data->timeshift, $data->courseid); + $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); + } + + return $status; +} + +/** + * Called by course/reset.php. + * + * @param MoodleQuickForm $mform form passed by reference + */ +function ratingallocate_reset_course_form_definition($mform) { + + $mform->addElement('header', 'ratingallocateheader', get_string('modulenameplural', RATINGALLOCATE_MOD_NAME)); + $mform->addElement('advcheckbox', 'reset_ratings_and_allocations', + get_string('remove_ratings_and_allocations', RATINGALLOCATE_MOD_NAME)); + +} + +/** + * Course reset form defaults. + * @return array the defaults. + */ +function ratingallocate_reset_course_form_defaults($course) { + return ['reset_ratings_and_allocations' => 1]; +} diff --git a/locallib.php b/locallib.php index 37e3b6a7..e88685ab 100644 --- a/locallib.php +++ b/locallib.php @@ -1818,6 +1818,13 @@ public function get_choices() { ), this_db\ratingallocate_choices::TITLE); } + /** + * Returns the id of the ratingallocate instance. + */ + public function get_ratingallocateid() { + return $this->ratingallocateid; + } + /** * Returns an array of choices with the given ids * diff --git a/tests/locallib_test.php b/tests/locallib_test.php index dd3dc67c..789ec24c 100644 --- a/tests/locallib_test.php +++ b/tests/locallib_test.php @@ -231,4 +231,91 @@ public function test_get_option_titles_mixed() { $result = $ratingallocate->get_options_titles($ratings); $this->assertEquals($expectedresult, $result); } + + public function test_reset_userdata() { + global $DB; + + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $teacher = \mod_ratingallocate_generator::create_user_and_enrol($this, $course, true); + $student1 = \mod_ratingallocate_generator::create_user_and_enrol($this, $course); + $student2 = \mod_ratingallocate_generator::create_user_and_enrol($this, $course); + + $this->setUser($teacher); + + $choices = array( + array( + 'title' => 'C1', + 'maxsize' => '1', + 'active' => '1', + ), + array( + 'title' => 'C2', + 'maxsize' => '1', + 'active' => '1', + ) + ); + $ratings = array( + $student1->id => array( + array( + 'choice' => 'C1', + 'rating' => 1 + ), + array( + 'choice' => 'C2', + 'rating' => 0 + ) + ), + $student2->id => array( + array( + 'choice' => 'C1', + 'rating' => 0 + ), + array( + 'choice' => 'C2', + 'rating' => 1 + ) + ) + ); + + // Create ratingallocate instance. + $ratingallocate = \mod_ratingallocate_generator::get_closed_ratingallocate_for_teacher($this, $choices, + $course, $ratings); + + // Simulate Allocation. + $ratingallocate->distrubute_choices(); + + // There should be two ratings in the course. + $this->assertEquals(2, count($ratingallocate->get_users_with_ratings())); + $this->assertEquals(2, count($ratingallocate->get_allocations())); + + // Keep dates for comparison. + $accesstimestart = $DB->get_record('ratingallocate', ['id' => $ratingallocate->get_ratingallocateid()], 'accesstimestart')->accesstimestart; + $accesstimestop = $DB->get_record('ratingallocate', ['id' => $ratingallocate->get_ratingallocateid()], 'accesstimestop')->accesstimestop; + + // Now try and reset. + $data = new \stdClass(); + $data->reset_ratings_and_allocations = 1; + $data->courseid = $course->id; + $data->timeshift = (2 * DAYSECS); + $this->setUser($teacher); + $status = ratingallocate_reset_userdata($data); + + // Reload the instance data. + $ra = $DB->get_record('ratingallocate', array('id' => $ratingallocate->get_ratingallocateid())); + $ratingallocate = \mod_ratingallocate_generator::get_ratingallocate($ra); + + // There should be no ratings and allocations anymore. + $this->assertEquals(0, count($ratingallocate->get_allocations())); + $this->assertEquals(0, count($ratingallocate->get_ratings_for_rateable_choices())); + if (isset($status['error'])) { + $this->assertEquals(false, $status['error']); + } + + // Check if the timeshift happened successfully. + $this->assertEquals($accesstimestart + (2 * DAYSECS), $ra->accesstimestart); + $this->assertEquals($accesstimestop + (2 * DAYSECS), $ra->accesstimestop); + } + }