diff --git a/availability/condition/date/classes/condition.php b/availability/condition/date/classes/condition.php index bdedc31b434de..722b0247be2f6 100644 --- a/availability/condition/date/classes/condition.php +++ b/availability/condition/date/classes/condition.php @@ -234,4 +234,68 @@ public function update_after_restore( } return false; } + + /** + * Changes all date restrictions on a course by the specified shift amount. + * Used by the course reset feature. + * + * @param int $courseid Course id + * @param int $timeshift Offset in seconds + */ + public static function update_all_dates($courseid, $timeshift) { + global $DB; + + $modinfo = get_fast_modinfo($courseid); + $anychanged = false; + + // Adjust dates from all course modules. + foreach ($modinfo->cms as $cm) { + if (!$cm->availability) { + continue; + } + $info = new \core_availability\info_module($cm); + $tree = $info->get_availability_tree(); + $dates = $tree->get_all_children('availability_date\condition'); + $changed = false; + foreach ($dates as $date) { + $date->time += $timeshift; + $changed = true; + } + + // Save the updated course module. + if ($changed) { + $DB->set_field('course_modules', 'availability', json_encode($tree->save()), + array('id' => $cm->id)); + $anychanged = true; + } + } + + // Adjust dates from all course sections. + foreach ($modinfo->get_section_info_all() as $section) { + if (!$section->availability) { + continue; + } + + $info = new \core_availability\info_section($section); + $tree = $info->get_availability_tree(); + $dates = $tree->get_all_children('availability_date\condition'); + $changed = false; + foreach ($dates as $date) { + $date->time += $timeshift; + $changed = true; + } + + // Save the updated course module. + if ($changed) { + $DB->set_field('course_sections', 'availability', json_encode($tree->save()), + array('id' => $section->id)); + $anychanged = true; + } + } + + // Ensure course cache is cleared if required. + if ($anychanged) { + rebuild_course_cache($courseid, true); + } + } } diff --git a/availability/condition/date/tests/condition_test.php b/availability/condition/date/tests/condition_test.php index 425f1458d1c02..9d32b4374670e 100644 --- a/availability/condition/date/tests/condition_test.php +++ b/availability/condition/date/tests/condition_test.php @@ -25,6 +25,7 @@ defined('MOODLE_INTERNAL') || die(); use availability_date\condition; +use core_availability\tree; /** * Unit tests for the date condition. @@ -233,4 +234,53 @@ public function test_get_description() { $information = $date->get_standalone_description(true, true, $info); $this->assertRegExp('~from.*5 March 2014([^0-9]*)$~', $information); } + + /** + * Tests the update_all_dates function. + */ + public function test_update_all_dates() { + global $DB; + $this->resetAfterTest(); + + // Create a course with 3 pages. + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + $rec = array('course' => $course); + $page1 = $generator->get_plugin_generator('mod_page')->create_instance($rec); + $page2 = $generator->get_plugin_generator('mod_page')->create_instance($rec); + $page3 = $generator->get_plugin_generator('mod_page')->create_instance($rec); + + // Set the availability page 2 to a simple date condition. You can access + // it from 1337 onwards. + $simplecondition = tree::get_root_json(array( + condition::get_json(condition::DIRECTION_FROM, 1337))); + $DB->set_field('course_modules', 'availability', + json_encode($simplecondition), array('id' => $page2->cmid)); + + // Set page 3 to a complex set of conditions including a nested date condition. + // You can access it until 1459, *or* after 2810 if you belong to a group. + $complexcondition = tree::get_root_json(array( + condition::get_json(condition::DIRECTION_UNTIL, 1459), + tree::get_nested_json(array( + condition::get_json(condition::DIRECTION_FROM, 2810), + \availability_group\condition::get_json()))), + tree::OP_OR); + $DB->set_field('course_modules', 'availability', + json_encode($complexcondition), array('id' => $page3->cmid)); + + // Now use the update_all_dates function to move date forward 100000. + condition::update_all_dates($course->id, 100000); + + // Get the expected conditions after adjusting time, and compare to database. + $simplecondition->c[0]->t = 101337; + $complexcondition->c[0]->t = 101459; + $complexcondition->c[1]->c[0]->t = 102810; + $this->assertEquals($simplecondition, json_decode( + $DB->get_field('course_modules', 'availability', array('id' => $page2->cmid)))); + $this->assertEquals($complexcondition, json_decode( + $DB->get_field('course_modules', 'availability', array('id' => $page3->cmid)))); + + // The one without availability conditions should still be null. + $this->assertNull($DB->get_field('course_modules', 'availability', array('id' => $page1->cmid))); + } } diff --git a/availability/condition/group/classes/condition.php b/availability/condition/group/classes/condition.php index 2445cdc963f68..a27adaaf89524 100644 --- a/availability/condition/group/classes/condition.php +++ b/availability/condition/group/classes/condition.php @@ -229,7 +229,12 @@ public function filter_user_list(array $users, $not, \core_availability\info $in * @return stdClass Object representing condition */ public static function get_json($groupid = 0) { - return (object)array('type' => 'group', 'id' => (int)$groupid); + $result = (object)array('type' => 'group'); + // Id is only included if set. + if ($groupid) { + $result->id = (int)$groupid; + } + return $result; } public function get_user_list_sql($not, \core_availability\info $info, $onlyactive) { diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 770658b7478e3..d437e711bfed4 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -5410,6 +5410,11 @@ function reset_course_userdata($data) { WHERE courseid=? AND instance=0"; $DB->execute($updatesql, array($data->timeshift, $data->courseid)); + // Update any date activity restrictions. + if ($CFG->enableavailability) { + \availability_date\condition::update_all_dates($data->courseid, $data->timeshift); + } + $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); }