From e3658a6a9c8052bdbfc76133c54bda3589445372 Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Tue, 4 Jul 2017 14:43:25 +0800 Subject: [PATCH] MDL-59287 course_module: Create calendar event update function. --- course/lib.php | 74 ++++++++++++++++++++ course/tests/courselib_test.php | 118 ++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) diff --git a/course/lib.php b/course/lib.php index bc444f81e1d..74652defc26 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1386,6 +1386,80 @@ function delete_mod_from_section($modid, $sectionid) { return false; } +/** + * This function updates the calendar events from the information stored in the module table and the course + * module table. + * + * @param string $modulename Module name + * @param stdClass $instance Module object. Either the $instance or the $cm must be supplied. + * @param stdClass $cm Course module object. Either the $instance or the $cm must be supplied. + * @return bool Returns true if calendar events are updated. + * @since Moodle 3.3.4 + */ +function course_module_update_calendar_events($modulename, $instance = null, $cm = null) { + global $DB; + + if (isset($instance) || isset($cm)) { + + if (!isset($instance)) { + $instance = $DB->get_record($modulename, array('id' => $cm->instance), '*', MUST_EXIST); + } + if (!isset($cm)) { + $cm = get_coursemodule_from_instance($modulename, $instance->id, $instance->course); + } + course_module_calendar_event_update_process($instance, $cm); + return true; + } + return false; +} + +/** + * Update all instances through out the site or in a course. + * + * @param string $modulename Module type to update. + * @param integer $courseid Course id to update events. 0 for the whole site. + * @return bool Returns True if the update was successful. + * @since Moodle 3.3.4 + */ +function course_module_bulk_update_calendar_events($modulename, $courseid = 0) { + global $DB; + + $instances = null; + if ($courseid) { + if (!$instances = $DB->get_records($modulename, array('course' => $courseid))) { + return false; + } + } else { + if (!$instances = $DB->get_records($modulename)) { + return false; + } + } + + foreach ($instances as $instance) { + $cm = get_coursemodule_from_instance($modulename, $instance->id, $instance->course); + course_module_calendar_event_update_process($instance, $cm); + } + return true; +} + +/** + * Calendar events for a module instance are updated. + * + * @param stdClass $instance Module instance object. + * @param stdClass $cm Course Module object. + * @since Moodle 3.3.4 + */ +function course_module_calendar_event_update_process($instance, $cm) { + // We need to call *_refresh_events() first because some modules delete 'old' events at the end of the code which + // will remove the completion events. + $refresheventsfunction = $cm->modname . '_refresh_events'; + if (function_exists($refresheventsfunction)) { + call_user_func($refresheventsfunction, $cm->course, $instance, $cm); + } + $completionexpected = (!empty($cm->completionexpected)) ? $cm->completionexpected : null; + \core_completion\api::update_completion_date_event($cm->id, $cm->modname, $instance, $completionexpected); +} + /** * Moves a section within a course, from a position to another. * Be very careful: $section and $destination refer to section number, diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 5da897db9a3..c51f30cf788 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -3757,4 +3757,122 @@ class core_course_courselib_testcase extends advanced_testcase { $this->assertEquals(COURSE_TIMELINE_PAST, course_classify_for_timeline($completedcourse)); $this->assertEquals(COURSE_TIMELINE_INPROGRESS, course_classify_for_timeline($inprogresscourse)); } + + /** + * Test the main function for updating all calendar events for a module. + */ + public function test_course_module_calendar_event_update_process() { + global $DB; + + $this->resetAfterTest(); + $this->setAdminUser(); + + $completionexpected = time(); + $duedate = time(); + + $course = $this->getDataGenerator()->create_course(['enablecompletion' => COMPLETION_ENABLED]); + $assign = $this->getDataGenerator()->create_module('assign', [ + 'course' => $course, + 'completionexpected' => $completionexpected, + 'duedate' => $duedate + ]); + + $cm = get_coursemodule_from_instance('assign', $assign->id, $course->id); + $events = $DB->get_records('event', ['courseid' => $course->id, 'instance' => $assign->id]); + // Check that both events are using the expected dates. + foreach ($events as $event) { + if ($event->eventtype == \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED) { + $this->assertEquals($completionexpected, $event->timestart); + } + if ($event->eventtype == ASSIGN_EVENT_TYPE_DUE) { + $this->assertEquals($duedate, $event->timestart); + } + } + + // We have to manually update the module and the course module. + $newcompletionexpected = time() + DAYSECS * 60; + $newduedate = time() + DAYSECS * 45; + $newmodulename = 'Assign - new name'; + + $moduleobject = (object)array('id' => $assign->id, 'duedate' => $newduedate, 'name' => $newmodulename); + $DB->update_record('assign', $moduleobject); + $cmobject = (object)array('id' => $cm->id, 'completionexpected' => $newcompletionexpected); + $DB->update_record('course_modules', $cmobject); + + $assign = $DB->get_record('assign', ['id' => $assign->id]); + $cm = get_coursemodule_from_instance('assign', $assign->id, $course->id); + + course_module_calendar_event_update_process($assign, $cm); + + $events = $DB->get_records('event', ['courseid' => $course->id, 'instance' => $assign->id]); + // Now check that the details have been updated properly from the function. + foreach ($events as $event) { + if ($event->eventtype == \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED) { + $this->assertEquals($newcompletionexpected, $event->timestart); + $this->assertEquals(get_string('completionexpectedfor', 'completion', (object)['instancename' => $newmodulename]), + $event->name); + } + if ($event->eventtype == ASSIGN_EVENT_TYPE_DUE) { + $this->assertEquals($newduedate, $event->timestart); + $this->assertEquals($newmodulename, $event->name); + } + } + } + + /** + * Test the higher level checks for updating calendar events for an instance. + */ + public function test_course_module_update_calendar_events() { + $this->resetAfterTest(); + $this->setAdminUser(); + + $completionexpected = time(); + $duedate = time(); + + $course = $this->getDataGenerator()->create_course(['enablecompletion' => COMPLETION_ENABLED]); + $assign = $this->getDataGenerator()->create_module('assign', [ + 'course' => $course, + 'completionexpected' => $completionexpected, + 'duedate' => $duedate + ]); + + $cm = get_coursemodule_from_instance('assign', $assign->id, $course->id); + + // Both the instance and cm objects are missing. + $this->assertFalse(course_module_update_calendar_events('assign')); + // Just using the assign instance. + $this->assertTrue(course_module_update_calendar_events('assign', $assign)); + // Just using the course module object. + $this->assertTrue(course_module_update_calendar_events('assign', null, $cm)); + // Using both the assign instance and the course module object. + $this->assertTrue(course_module_update_calendar_events('assign', $assign, $cm)); + } + + /** + * Test the higher level checks for updating calendar events for a module. + */ + public function test_course_module_bulk_update_calendar_events() { + $this->resetAfterTest(); + $this->setAdminUser(); + + $completionexpected = time(); + $duedate = time(); + + $course = $this->getDataGenerator()->create_course(['enablecompletion' => COMPLETION_ENABLED]); + $course2 = $this->getDataGenerator()->create_course(['enablecompletion' => COMPLETION_ENABLED]); + $assign = $this->getDataGenerator()->create_module('assign', [ + 'course' => $course, + 'completionexpected' => $completionexpected, + 'duedate' => $duedate + ]); + + // No assign instances in this course. + $this->assertFalse(course_module_bulk_update_calendar_events('assign', $course2->id)); + // No book instances for the site. + $this->assertFalse(course_module_bulk_update_calendar_events('book')); + // Update all assign instances. + $this->assertTrue(course_module_bulk_update_calendar_events('assign')); + // Update the assign instances for this course. + $this->assertTrue(course_module_bulk_update_calendar_events('assign', $course->id)); + } }