* @return array
*/
protected function get_module_timestamp_limits($event) {
+ global $DB;
+
$values = [];
$mapper = container::get_event_mapper();
$starttime = $event->get_times()->get_start_time();
+ $modname = $event->get_course_module()->get('modname');
+ $modid = $event->get_course_module()->get('instance');
+ $moduleinstance = $DB->get_record($modname, ['id' => $modid]);
list($min, $max) = component_callback(
- 'mod_' . $event->get_course_module()->get('modname'),
+ 'mod_' . $modname,
'core_calendar_get_valid_event_timestart_range',
- [$mapper->from_event_to_legacy_event($event)],
+ [$mapper->from_event_to_legacy_event($event), $moduleinstance],
[null, null]
);
event_interface $event,
\DateTimeInterface $startdate
) {
+ global $DB;
+
$mapper = container::get_event_mapper();
$legacyevent = $mapper->from_event_to_legacy_event($event);
$hascoursemodule = !empty($event->get_course_module());
+ $moduleinstance = null;
$starttime = $event->get_times()->get_start_time()->setDate(
$startdate->format('Y'),
$startdate->format('n'),
);
if ($hascoursemodule) {
+ $moduleinstance = $DB->get_record(
+ $event->get_course_module()->get('modname'),
+ ['id' => $event->get_course_module()->get('instance')],
+ '*',
+ MUST_EXIST
+ );
$legacyevent->timestart = $starttime->getTimestamp();
- // If this event is from an activity then we need to call
- // the activity callback to let it validate that the changes
- // to the event are correct.
- component_callback(
+
+ // If there is a timestart range callback implemented then we can
+ // use the values returned from the valid timestart range to apply
+ // some default validation on the event's timestart value to ensure
+ // that it falls within the specified range.
+ list($min, $max) = component_callback(
'mod_' . $event->get_course_module()->get('modname'),
- 'core_calendar_validate_event_timestart',
- [$legacyevent]
+ 'core_calendar_get_valid_event_timestart_range',
+ [$legacyevent, $moduleinstance],
+ [null, null]
);
+
+ if ($min && $legacyevent->timestart < $min[0]) {
+ throw new \moodle_exception($min[1]);
+ }
+
+ if ($max && $legacyevent->timestart > $max[0]) {
+ throw new \moodle_exception($max[1]);
+ }
}
// This function does our capability checks.
// We don't want to call the event update callback if the user isn't allowed
// to modify course modules because depending on the callback it can make
// some changes that would be considered security issues, such as updating the
- // due date for and assignment.
+ // due date for an assignment.
if ($hascoursemodule && calendar_edit_event_allowed($legacyevent, true)) {
// If this event is from an activity then we need to call
// the activity callback to let it know that the event it
component_callback(
'mod_' . $event->get_course_module()->get('modname'),
'core_calendar_event_timestart_updated',
- [$legacyevent]
+ [$legacyevent, $moduleinstance]
);
}
$this->resetAfterTest();
}
+ /**
+ * Create a feedback activity instance and a calendar event for
+ * that instance.
+ *
+ * @param array $feedbackproperties Properties to set on the feedback activity
+ * @param array $eventproperties Properties to set on the calendar event
+ * @return array The feedback activity and the calendar event
+ */
+ protected function create_feedback_activity_and_event(array $feedbackproperties = [], array $eventproperties = []) {
+ $generator = $this->getDataGenerator();
+ $course = $generator->create_course();
+ $mapper = container::get_event_mapper();
+ $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
+ $feedback = $feedbackgenerator->create_instance(array_merge(
+ ['course' => $course->id],
+ $feedbackproperties
+ ));
+
+ $event = create_event(array_merge(
+ [
+ 'courseid' => $course->id,
+ 'modulename' => 'feedback',
+ 'instance' => $feedback->id
+ ],
+ $eventproperties
+ ));
+ $event = $mapper->from_legacy_event_to_event($event);
+
+ return [$feedback, $event];
+ }
+
/**
* Requesting calendar events from a given time should return all events with a sort
* time at or after the requested time. All events prior to that time should not
$this->expectException('moodle_exception');
$newEvent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
}
+
+ /**
+ * Updating the start day of an event with no maximum cutoff should
+ * update the corresponding activity property.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_no_max() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
+ $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => 0
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
+ 'timestart' => $timeopen->getTimestamp()
+ ]
+ );
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ $actual = $newevent->get_times()->get_start_time();
+ $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
+
+ $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
+ $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
+ }
+
+ /**
+ * Updating the start day of an event belonging to an activity to a value
+ * less than the maximum cutoff should update the corresponding activity
+ * property.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_less_than_max() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $timeclose = new DateTimeImmutable('2019-01-1T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
+ $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => $timeclose->getTimestamp()
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
+ 'timestart' => $timeopen->getTimestamp()
+ ]
+ );
+
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ $actual = $newevent->get_times()->get_start_time();
+ $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
+
+ $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
+ $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
+ }
+
+ /**
+ * Updating the start day of an event belonging to an activity to a value
+ * equal to the maximum cutoff should update the corresponding activity
+ * property.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_equal_to_max() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $timeclose = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => $timeclose->getTimestamp(),
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
+ 'timestart' => $timeopen->getTimestamp()
+ ]
+ );
+
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ $actual = $newevent->get_times()->get_start_time();
+ $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
+
+ $this->assertEquals($timeclose->getTimestamp(), $actual->getTimestamp());
+ $this->assertEquals($timeclose->getTimestamp(), $feedback->timeopen);
+ }
+
+ /**
+ * Updating the start day of an event belonging to an activity to a value
+ * after the maximum cutoff should not update the corresponding activity
+ * property. Instead it should throw an exception.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_after_max() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $timeclose = new DateTimeImmutable('2017-02-2T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => $timeclose->getTimestamp(),
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
+ 'timestart' => $timeopen->getTimestamp()
+ ]
+ );
+
+ $this->expectException('moodle_exception');
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ }
+
+ /**
+ * Updating the start day of an event with no minimum cutoff should
+ * update the corresponding activity property.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_no_min() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeclose = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2016-02-2T10:00:00+08:00');
+ $expected = new DateTimeImmutable('2016-02-2T15:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => 0,
+ 'timeclose' => $timeclose->getTimestamp()
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
+ 'timestart' => $timeclose->getTimestamp()
+ ]
+ );
+
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ $actual = $newevent->get_times()->get_start_time();
+ $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
+
+ $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
+ $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
+ }
+
+ /**
+ * Updating the start day of an event belonging to an activity to a value
+ * greater than the minimum cutoff should update the corresponding activity
+ * property.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_greater_than_min() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2016-01-1T15:00:00+08:00');
+ $timeclose = new DateTimeImmutable('2019-01-1T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
+ $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => $timeclose->getTimestamp()
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
+ 'timestart' => $timeclose->getTimestamp()
+ ]
+ );
+
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ $actual = $newevent->get_times()->get_start_time();
+ $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
+
+ $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
+ $this->assertEquals($expected->getTimestamp(), $feedback->timeclose);
+ }
+
+ /**
+ * Updating the start day of an event belonging to an activity to a value
+ * equal to the minimum cutoff should update the corresponding activity
+ * property.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_equal_to_min() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $timeclose = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2017-01-1T10:00:00+08:00');
+ $expected = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => $timeclose->getTimestamp(),
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
+ 'timestart' => $timeclose->getTimestamp()
+ ]
+ );
+
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ $actual = $newevent->get_times()->get_start_time();
+ $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
+
+ $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
+ $this->assertEquals($expected->getTimestamp(), $feedback->timeclose);
+ }
+
+ /**
+ * Updating the start day of an event belonging to an activity to a value
+ * before the minimum cutoff should not update the corresponding activity
+ * property. Instead it should throw an exception.
+ *
+ * Note: This test uses the feedback activity because it requires
+ * module callbacks to be in place to test.
+ */
+ public function test_update_event_start_day_activity_event_before_min() {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/mod/feedback/lib.php');
+
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+ $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
+ $timeclose = new DateTimeImmutable('2017-02-2T15:00:00+08:00');
+ $newstartdate = new DateTimeImmutable('2016-02-2T10:00:00+08:00');
+ list($feedback, $event) = $this->create_feedback_activity_and_event(
+ [
+ 'timeopen' => $timeopen->getTimestamp(),
+ 'timeclose' => $timeclose->getTimestamp(),
+ ],
+ [
+ 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
+ 'timestart' => $timeclose->getTimestamp()
+ ]
+ );
+
+ $this->expectException('moodle_exception');
+ $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
+ }
}
=== 3.4 ===
* calendar_get_mini has been deprecated. Please update to use the new
exporters and renderers.
-* added core_calendar_validate_event_timestart and core_calendar_event_timestart_updated callbacks for module events
+* added core_calendar_get_valid_event_timestart_range and core_calendar_event_timestart_updated callbacks for module events
when the update_event_start_day function is used in the local api.
=== 3.3 ===
* ]
*
* @param calendar_event $event The calendar event to get the time range for
- * @param stdClass|null $instance The module instance to get the range from
+ * @param stdClass $instance The module instance to get the range from
*/
-function mod_assign_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance = null) {
- global $CFG, $DB;
+function mod_assign_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance) {
+ global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
- if (!$instance) {
- $instance = $DB->get_record('assign', ['id' => $event->instance]);
- }
-
- $coursemodule = get_coursemodule_from_instance('assign',
- $event->instance,
- $event->courseid,
- false,
- MUST_EXIST);
-
- if (empty($coursemodule)) {
- // If we don't have a course module yet then it likely means
- // the activity is still being set up. In this case there is
- // nothing for us to do anyway.
- return;
- }
-
+ $courseid = $event->courseid;
+ $modulename = $event->modulename;
+ $instanceid = $event->instance;
+ $coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid];
$context = context_module::instance($coursemodule->id);
$assign = new assign($context, null, null);
$assign->set_instance($instance);
return $assign->get_valid_calendar_event_timestart_range($event);
}
-/**
- * This function will check that the given event is valid for it's
- * corresponding assign module instance.
- *
- * An exception is thrown if the event fails validation.
- *
- * @throws \moodle_exception
- * @param \calendar_event $event
- * @return bool
- */
-function mod_assign_core_calendar_validate_event_timestart(\calendar_event $event) {
- global $DB;
-
- if (!isset($event->instance)) {
- return;
- }
-
- // We need to read from the DB directly because course module may
- // currently be getting created so it won't be in mod info yet.
- $instance = $DB->get_record('assign', ['id' => $event->instance], '*', MUST_EXIST);
- $timestart = $event->timestart;
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
-
- if ($min && $timestart < $min[0]) {
- throw new \moodle_exception($min[1]);
- }
-
- if ($max && $timestart > $max[0]) {
- throw new \moodle_exception($max[1]);
- }
-}
-
/**
* This function will update the assign module according to the
* event that has been modified.
*
* @throws \moodle_exception
* @param \calendar_event $event
+ * @param stdClass $instance The module instance to get the range from
*/
-function mod_assign_core_calendar_event_timestart_updated(\calendar_event $event) {
+function mod_assign_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $instance) {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
return;
}
- $coursemodule = get_coursemodule_from_instance('assign',
- $event->instance,
- $event->courseid,
- false,
- MUST_EXIST);
+ if ($instance->id != $event->instance) {
+ return;
+ }
- if (empty($coursemodule)) {
- // If we don't have a course module yet then it likely means
- // the activity is still being set up. In this case there is
- // nothing for us to do anyway.
+ if (!in_array($event->eventtype, [ASSIGN_EVENT_TYPE_DUE, ASSIGN_EVENT_TYPE_GRADINGDUE])) {
return;
}
+ $courseid = $event->courseid;
+ $modulename = $event->modulename;
+ $instanceid = $event->instance;
+ $modified = false;
+ $coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid];
$context = context_module::instance($coursemodule->id);
// The user does not have the capability to modify this activity.
}
$assign = new assign($context, $coursemodule, null);
- $modified = false;
+ $assign->set_instance($instance);
if ($event->eventtype == ASSIGN_EVENT_TYPE_DUE) {
// This check is in here because due date events are currently
return;
}
- $instance = $assign->get_instance();
$newduedate = $event->timestart;
if ($newduedate != $instance->duedate) {
$instance->duedate = $newduedate;
- $instance->timemodified = time();
$modified = true;
}
} else if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) {
- $instance = $assign->get_instance();
$newduedate = $event->timestart;
if ($newduedate != $instance->gradingduedate) {
$instance->gradingduedate = $newduedate;
- $instance->timemodified = time();
$modified = true;
}
}
if ($modified) {
+ $instance->timemodified = time();
// Persist the assign instance changes.
$DB->update_record('assign', $instance);
$assign->update_calendar($coursemodule->id);
'eventtype' => 'SOME RANDOM EVENT'
]);
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
$this->assertNull($min);
$this->assertNull($max);
}
$DB->insert_record('assign_overrides', $record);
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
$this->assertNull($min);
$this->assertNull($max);
}
'eventtype' => ASSIGN_EVENT_TYPE_DUE
]);
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
$this->assertNull($min);
$this->assertNull($max);
}
'eventtype' => ASSIGN_EVENT_TYPE_DUE
]);
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
$this->assertEquals($submissionsfromdate, $min[0]);
$this->assertNotEmpty($min[1]);
$this->assertEquals($cutoffdate, $max[0]);
'eventtype' => ASSIGN_EVENT_TYPE_GRADINGDUE
]);
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
$this->assertNull($min);
$this->assertNull($max);
}
'eventtype' => ASSIGN_EVENT_TYPE_GRADINGDUE
]);
- list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_assign_core_calendar_get_valid_event_timestart_range($event, $instance);
$this->assertEquals($duedate, $min[0]);
$this->assertNotEmpty($min[1]);
$this->assertNull($max);
}
- /**
- * Calendar events without and instance id should be ignored by the validate
- * event function.
- */
- public function test_mod_assign_core_calendar_validate_event_timestart_no_instance_id() {
- global $CFG;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $event = new \calendar_event((object) [
- 'modulename' => 'assign',
- 'eventtype' => ASSIGN_EVENT_TYPE_DUE
- ]);
-
- mod_assign_core_calendar_validate_event_timestart($event);
- // The function above throws an exception so all we need to do is make sure
- // it gets here and that is considered success.
- $this->assertTrue(true);
- }
-
- /**
- * Calendar events for an unknown instance should throw an exception.
- */
- public function test_mod_assign_core_calendar_validate_event_timestart_no_instance_found() {
- global $CFG;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $event = new \calendar_event((object) [
- 'modulename' => 'assign',
- 'instance' => 1234,
- 'eventtype' => ASSIGN_EVENT_TYPE_DUE
- ]);
-
- $this->expectException('moodle_exception');
- mod_assign_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * Assignments configured without any limits on the due date should not
- * throw an exception.
- */
- public function test_mod_assign_core_calendar_validate_event_timestart_no_limit() {
- global $CFG, $DB;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $assign = $this->create_instance([
- 'duedate' => 0,
- 'allowsubmissionsfromdate' => 0,
- 'cutoffdate' => 0,
- ]);
- $instance = $assign->get_instance();
-
- $event = new \calendar_event((object) [
- 'courseid' => $instance->course,
- 'modulename' => 'assign',
- 'instance' => $instance->id,
- 'eventtype' => ASSIGN_EVENT_TYPE_DUE,
- 'timestart' => time()
- ]);
-
- mod_assign_core_calendar_validate_event_timestart($event);
- // The function above throws an exception so all we need to do is make sure
- // it gets here and that is considered success.
- $this->assertTrue(true);
- }
-
- /**
- * Due date events with a timestart equal to or greater than the minimum limit
- * should not throw an exception. Timestart values below the minimum limit should
- * throw an exception.
- */
- public function test_mod_assign_core_calendar_validate_due_event_min_limit() {
- global $CFG, $DB;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $duedate = time();
- $submissionsfromdate = $duedate - DAYSECS;
- $cutoffdate = $duedate + DAYSECS;
- $assign = $this->create_instance([
- 'duedate' => $duedate,
- 'allowsubmissionsfromdate' => $submissionsfromdate,
- 'cutoffdate' => $cutoffdate,
- ]);
- $instance = $assign->get_instance();
-
- $event = new \calendar_event((object) [
- 'courseid' => $instance->course,
- 'modulename' => 'assign',
- 'instance' => $instance->id,
- 'eventtype' => ASSIGN_EVENT_TYPE_DUE,
- 'timestart' => $submissionsfromdate + 1,
- ]);
-
- // No exception when new time is above minimum cutoff.
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // No exception when new time is equal to minimum cutoff.
- $event->timestart = $submissionsfromdate;
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // Exception when new time is earlier than minimum cutoff.
- $event->timestart = $submissionsfromdate - 1;
- $this->expectException('moodle_exception');
- mod_assign_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A due date event with a timestart less than or equal to the max limit should
- * not throw an exception. A timestart greater than the max limit should throw
- * an exception.
- */
- public function test_mod_assign_core_calendar_validate_due_event_max_limit() {
- global $CFG, $DB;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $duedate = time();
- $submissionsfromdate = $duedate - DAYSECS;
- $cutoffdate = $duedate + DAYSECS;
- $assign = $this->create_instance([
- 'duedate' => $duedate,
- 'allowsubmissionsfromdate' => $submissionsfromdate,
- 'cutoffdate' => $cutoffdate,
- ]);
- $instance = $assign->get_instance();
-
- $event = new \calendar_event((object) [
- 'courseid' => $instance->course,
- 'modulename' => 'assign',
- 'instance' => $instance->id,
- 'eventtype' => ASSIGN_EVENT_TYPE_DUE,
- 'timestart' => $cutoffdate - 1,
- ]);
-
- // No exception when new time is below maximum cutoff.
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // No exception when new time is equal to maximum cutoff.
- $event->timestart = $cutoffdate;
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // Exception when new time is later than maximum cutoff.
- $event->timestart = $submissionsfromdate - 1;
- $this->expectException('moodle_exception');
- mod_assign_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * Due date override events should not throw an exception.
- */
- public function test_mod_assign_core_calendar_validate_due_event_override() {
- global $CFG, $DB;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $duedate = time();
- $submissionsfromdate = $duedate - DAYSECS;
- $cutoffdate = $duedate + DAYSECS;
- $assign = $this->create_instance([
- 'duedate' => $duedate,
- 'allowsubmissionsfromdate' => $submissionsfromdate,
- 'cutoffdate' => $cutoffdate,
- ]);
- $instance = $assign->get_instance();
- $userid = $this->students[0]->id;
-
- $event = new \calendar_event((object) [
- 'courseid' => $instance->course,
- 'modulename' => 'assign',
- 'instance' => $instance->id,
- 'userid' => $userid,
- 'eventtype' => ASSIGN_EVENT_TYPE_DUE,
- 'timestart' => $duedate + (2 * DAYSECS)
- ]);
-
- $record = (object) [
- 'assignid' => $instance->id,
- 'userid' => $userid,
- 'duedate' => $duedate + (2 * DAYSECS)
- ];
-
- $DB->insert_record('assign_overrides', $record);
-
- // No exception when dealing with an override.
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
- }
-
- /**
- * Grading due date event should throw an exception if it's timestart is less than the
- * assignment due date.
- */
- public function test_mod_assign_core_calendar_validate_gradingdue_event_min_limit_duedate() {
- global $CFG, $DB;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $duedate = time();
- $submissionsfromdate = $duedate - DAYSECS;
- $cutoffdate = $duedate + DAYSECS;
- $assign = $this->create_instance([
- 'duedate' => $duedate,
- 'allowsubmissionsfromdate' => $submissionsfromdate,
- 'cutoffdate' => $cutoffdate,
- ]);
- $instance = $assign->get_instance();
-
- $event = new \calendar_event((object) [
- 'courseid' => $instance->course,
- 'modulename' => 'assign',
- 'instance' => $instance->id,
- 'eventtype' => ASSIGN_EVENT_TYPE_GRADINGDUE,
- 'timestart' => $duedate + 1,
- ]);
-
- // No exception when new time is above minimum cutoff.
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // No exception when new time is equal to minimum cutoff.
- $event->timestart = $duedate;
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // Exception when new time is earlier than minimum cutoff.
- $event->timestart = $duedate - 1;
- $this->expectException('moodle_exception');
- mod_assign_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * Grading due date event should throw an exception if it's timestart is less than the
- * submissions allowed from date if there is no due date set.
- */
- public function test_mod_assign_core_calendar_validate_gradingdue_event_min_limit_submissionsfromdate() {
- global $CFG, $DB;
- require_once($CFG->dirroot . '/calendar/lib.php');
-
- $this->resetAfterTest();
- $this->setAdminUser();
-
- $duedate = 0;
- $submissionsfromdate = time() - DAYSECS;
- $cutoffdate = time() + DAYSECS;
- $assign = $this->create_instance([
- 'duedate' => $duedate,
- 'allowsubmissionsfromdate' => $submissionsfromdate,
- 'cutoffdate' => $cutoffdate,
- ]);
- $instance = $assign->get_instance();
-
- $event = new \calendar_event((object) [
- 'courseid' => $instance->course,
- 'modulename' => 'assign',
- 'instance' => $instance->id,
- 'eventtype' => ASSIGN_EVENT_TYPE_GRADINGDUE,
- 'timestart' => $submissionsfromdate + 1,
- ]);
-
- // No exception when new time is above minimum cutoff.
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // No exception when new time is equal to minimum cutoff.
- $event->timestart = $submissionsfromdate;
- mod_assign_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
-
- // Exception when new time is earlier than minimum cutoff.
- $event->timestart = $submissionsfromdate - 1;
- $this->expectException('moodle_exception');
- mod_assign_core_calendar_validate_event_timestart($event);
- }
-
/**
* Non due date events should not update the assignment due date.
*/
'timestart' => $duedate + 1
]);
- mod_assign_core_calendar_event_timestart_updated($event);
+ mod_assign_core_calendar_event_timestart_updated($event, $instance);
$newinstance = $DB->get_record('assign', ['id' => $instance->id]);
$this->assertEquals($duedate, $newinstance->duedate);
$DB->insert_record('assign_overrides', $record);
- mod_assign_core_calendar_event_timestart_updated($event);
+ mod_assign_core_calendar_event_timestart_updated($event, $instance);
$newinstance = $DB->get_record('assign', ['id' => $instance->id]);
$this->assertEquals($duedate, $newinstance->duedate);
'timestart' => $newduedate
]);
- mod_assign_core_calendar_event_timestart_updated($event);
+ mod_assign_core_calendar_event_timestart_updated($event, $instance);
$newinstance = $DB->get_record('assign', ['id' => $instance->id]);
$this->assertEquals($newduedate, $newinstance->duedate);
* ]
*
* @param calendar_event $event The calendar event to get the time range for
- * @param stdClass|null $instance The module instance to get the range from
+ * @param stdClass $choice The module instance to get the range from
*/
-function mod_choice_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $choice = null) {
- global $DB;
-
- if (!$choice) {
- $choice = $DB->get_record('choice', ['id' => $event->instance]);
- }
-
+function mod_choice_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $choice) {
$mindate = null;
$maxdate = null;
return [$mindate, $maxdate];
}
-/**
- * This function will check that the given event is valid for it's
- * corresponding choice module.
- *
- * An exception is thrown if the event fails validation.
- *
- * @throws \moodle_exception
- * @param \calendar_event $event
- * @return bool
- */
-function mod_choice_core_calendar_validate_event_timestart(\calendar_event $event) {
- global $DB;
-
- if (!isset($event->instance)) {
- return;
- }
-
- // We need to read from the DB directly because course module may
- // currently be getting created so it won't be in mod info yet.
- $instance = $DB->get_record('choice', ['id' => $event->instance], '*', MUST_EXIST);
- $timestart = $event->timestart;
- list($min, $max) = mod_choice_core_calendar_get_valid_event_timestart_range($event, $instance);
-
- if ($min && $timestart < $min[0]) {
- throw new \moodle_exception($min[1]);
- }
-
- if ($max && $timestart > $max[0]) {
- throw new \moodle_exception($max[1]);
- }
-}
-
/**
* This function will update the choice module according to the
* event that has been modified.
*
* @throws \moodle_exception
* @param \calendar_event $event
+ * @param stdClass $choice The module instance to get the range from
*/
-function mod_choice_core_calendar_event_timestart_updated(\calendar_event $event) {
+function mod_choice_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $choice) {
global $DB;
+ if (!in_array($event->eventtype, [CHOICE_EVENT_TYPE_OPEN, CHOICE_EVENT_TYPE_CLOSE])) {
+ return;
+ }
+
$courseid = $event->courseid;
$modulename = $event->modulename;
$instanceid = $event->instance;
return;
}
+ if ($choice->id != $instanceid) {
+ return;
+ }
+
$coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid];
$context = context_module::instance($coursemodule->id);
// If the event is for the choice activity opening then we should
// set the start time of the choice activity to be the new start
// time of the event.
- $record = $DB->get_record('choice', ['id' => $instanceid], '*', MUST_EXIST);
-
- if ($record->timeopen != $event->timestart) {
- $record->timeopen = $event->timestart;
- $record->timemodified = time();
+ if ($choice->timeopen != $event->timestart) {
+ $choice->timeopen = $event->timestart;
$modified = true;
}
} else if ($event->eventtype == CHOICE_EVENT_TYPE_CLOSE) {
// If the event is for the choice activity closing then we should
// set the end time of the choice activity to be the new start
// time of the event.
- $record = $DB->get_record('choice', ['id' => $instanceid], '*', MUST_EXIST);
-
- if ($record->timeclose != $event->timestart) {
- $record->timeclose = $event->timestart;
- $record->timemodified = time();
+ if ($choice->timeclose != $event->timestart) {
+ $choice->timeclose = $event->timestart;
$modified = true;
}
}
if ($modified) {
+ $choice->timemodified = time();
// Persist the instance changes.
- $DB->update_record('choice', $record);
+ $DB->update_record('choice', $choice);
$event = \core\event\course_module_updated::create_from_cm($coursemodule, $context);
$event->trigger();
}
$this->assertEquals(mod_choice_get_completion_active_rule_descriptions(new stdClass()), []);
}
- /**
- * You can't create a choice module event when the module doesn't exist.
- */
- public function test_mod_choice_core_calendar_validate_event_timestart_no_activity() {
- global $CFG;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'choice',
- 'instance' => 1234,
- 'eventtype' => CHOICE_EVENT_TYPE_OPEN,
- 'timestart' => time(),
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_choice_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A CHOICE_EVENT_TYPE_OPEN must be before the close time of the choice activity.
- */
- public function test_mod_choice_core_calendar_validate_event_timestart_valid_open_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $choicegenerator = $generator->get_plugin_generator('mod_choice');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $choice = $choicegenerator->create_instance(['course' => $course->id]);
- $choice->timeopen = $timeopen;
- $choice->timeclose = $timeclose;
- $DB->update_record('choice', $choice);
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'choice',
- 'instance' => $choice->id,
- 'eventtype' => CHOICE_EVENT_TYPE_OPEN,
- 'timestart' => $timeopen,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- mod_choice_core_calendar_validate_event_timestart($event);
- // The function above will throw an exception if the event is
- // invalid.
- $this->assertTrue(true);
- }
-
- /**
- * A CHOICE_EVENT_TYPE_OPEN can not have a start time set after the close time
- * of the choice activity.
- */
- public function test_mod_choice_core_calendar_validate_event_timestart_invalid_open_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $choicegenerator = $generator->get_plugin_generator('mod_choice');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $choice = $choicegenerator->create_instance(['course' => $course->id]);
- $choice->timeopen = $timeopen;
- $choice->timeclose = $timeclose;
- $DB->update_record('choice', $choice);
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'choice',
- 'instance' => $choice->id,
- 'eventtype' => CHOICE_EVENT_TYPE_OPEN,
- 'timestart' => $timeclose + 1,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_choice_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A CHOICE_EVENT_TYPE_CLOSE must be after the open time of the choice activity.
- */
- public function test_mod_choice_core_calendar_validate_event_timestart_valid_close_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $choicegenerator = $generator->get_plugin_generator('mod_choice');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $choice = $choicegenerator->create_instance(['course' => $course->id]);
- $choice->timeopen = $timeopen;
- $choice->timeclose = $timeclose;
- $DB->update_record('choice', $choice);
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'choice',
- 'instance' => $choice->id,
- 'eventtype' => CHOICE_EVENT_TYPE_CLOSE,
- 'timestart' => $timeclose,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- mod_choice_core_calendar_validate_event_timestart($event);
- // The function above will throw an exception if the event isn't
- // valid.
- $this->assertTrue(true);
- }
-
- /**
- * A CHOICE_EVENT_TYPE_CLOSE can not have a start time set before the open time
- * of the choice activity.
- */
- public function test_mod_choice_core_calendar_validate_event_timestart_invalid_close_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $choicegenerator = $generator->get_plugin_generator('mod_choice');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $choice = $choicegenerator->create_instance(['course' => $course->id]);
- $choice->timeopen = $timeopen;
- $choice->timeclose = $timeclose;
- $DB->update_record('choice', $choice);
-
- // Create a valid event.
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'choice',
- 'instance' => $choice->id,
- 'eventtype' => CHOICE_EVENT_TYPE_CLOSE,
- 'timestart' => $timeopen - 1,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_choice_core_calendar_validate_event_timestart($event);
- }
-
/**
* An unkown event type should not change the choice instance.
*/
'visible' => 1
]);
- mod_choice_core_calendar_event_timestart_updated($event);
+ mod_choice_core_calendar_event_timestart_updated($event, $choice);
$choice = $DB->get_record('choice', ['id' => $choice->id]);
$this->assertEquals($timeopen, $choice->timeopen);
// Trigger and capture the event when adding a contact.
$sink = $this->redirectEvents();
- mod_choice_core_calendar_event_timestart_updated($event);
+ mod_choice_core_calendar_event_timestart_updated($event, $choice);
$triggeredevents = $sink->get_events();
$moduleupdatedevents = array_filter($triggeredevents, function($e) {
// Trigger and capture the event when adding a contact.
$sink = $this->redirectEvents();
- mod_choice_core_calendar_event_timestart_updated($event);
+ mod_choice_core_calendar_event_timestart_updated($event, $choice);
$triggeredevents = $sink->get_events();
$moduleupdatedevents = array_filter($triggeredevents, function($e) {
* ]
*
* @param calendar_event $event The calendar event to get the time range for
- * @param stdClass|null $instance The module instance to get the range from
+ * @param stdClass $instance The module instance to get the range from
* @return array
*/
-function mod_feedback_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance = null) {
- global $DB;
-
- if (!$instance) {
- $instance = $DB->get_record('feedback', ['id' => $event->instance], '*', MUST_EXIST);
- }
-
+function mod_feedback_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance) {
$mindate = null;
$maxdate = null;
return [$mindate, $maxdate];
}
-/**
- * This function will check that the given event is valid for it's
- * corresponding feedback module.
- *
- * An exception is thrown if the event fails validation.
- *
- * @throws \moodle_exception
- * @param \calendar_event $event
- */
-function mod_feedback_core_calendar_validate_event_timestart(\calendar_event $event) {
- global $DB;
-
- $record = $DB->get_record('feedback', ['id' => $event->instance], '*', MUST_EXIST);
- $timestart = $event->timestart;
-
- list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $record);
-
- if ($min && $timestart < $min[0]) {
- throw new \moodle_exception($min[1]);
- }
-
- if ($max && $timestart > $max[0]) {
- throw new \moodle_exception($max[1]);
- }
-}
-
/**
* This function will update the feedback module according to the
* event that has been modified.
*
* @throws \moodle_exception
* @param \calendar_event $event
+ * @param stdClass $feedback The module instance to get the range from
*/
-function mod_feedback_core_calendar_event_timestart_updated(\calendar_event $event) {
+function mod_feedback_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $feedback) {
global $CFG, $DB;
if (empty($event->instance) || $event->modulename != 'feedback') {
return;
}
- $coursemodule = get_coursemodule_from_instance('feedback',
- $event->instance,
- $event->courseid,
- false,
- MUST_EXIST);
+ if ($event->instance != $feedback->id) {
+ return;
+ }
- if (empty($coursemodule)) {
- // If we don't have a course module yet then it likely means
- // the activity is still being set up. In this case there is
- // nothing for us to do anyway.
+ if (!in_array($event->eventtype, [FEEDBACK_EVENT_TYPE_OPEN, FEEDBACK_EVENT_TYPE_CLOSE])) {
return;
}
+ $courseid = $event->courseid;
+ $modulename = $event->modulename;
+ $instanceid = $event->instance;
+ $modified = false;
+
+ $coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid];
$context = context_module::instance($coursemodule->id);
// The user does not have the capability to modify this activity.
return;
}
- $modified = false;
-
if ($event->eventtype == FEEDBACK_EVENT_TYPE_OPEN) {
// If the event is for the feedback activity opening then we should
// set the start time of the feedback activity to be the new start
// time of the event.
- $record = $DB->get_record('feedback', ['id' => $event->instance], '*', MUST_EXIST);
-
- if ($record->timeopen != $event->timestart) {
- $record->timeopen = $event->timestart;
- $record->timemodified = time();
+ if ($feedback->timeopen != $event->timestart) {
+ $feedback->timeopen = $event->timestart;
+ $feedback->timemodified = time();
$modified = true;
}
} else if ($event->eventtype == FEEDBACK_EVENT_TYPE_CLOSE) {
// If the event is for the feedback activity closing then we should
// set the end time of the feedback activity to be the new start
// time of the event.
- $record = $DB->get_record('feedback', ['id' => $event->instance], '*', MUST_EXIST);
-
- if ($record->timeclose != $event->timestart) {
- $record->timeclose = $event->timestart;
- $record->timemodified = time();
+ if ($feedback->timeclose != $event->timestart) {
+ $feedback->timeclose = $event->timestart;
$modified = true;
}
}
if ($modified) {
- $DB->update_record('feedback', $record);
+ $feedback->timemodified = time();
+ $DB->update_record('feedback', $feedback);
$event = \core\event\course_module_updated::create_from_cm($coursemodule, $context);
$event->trigger();
}
'visible' => 1
]);
- list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
$this->assertNull($min);
$this->assertNull($max);
}
'visible' => 1
]);
- list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
$this->assertNull($min);
$this->assertEquals($timeclose, $max[0]);
$this->assertNotEmpty($max[1]);
'visible' => 1
]);
- list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
$this->assertNull($min);
$this->assertNull($max);
}
'visible' => 1
]);
- list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
$this->assertEquals($timeopen, $min[0]);
$this->assertNotEmpty($min[1]);
$this->assertNull($max);
'visible' => 1
]);
- list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event);
+ list($min, $max) = mod_feedback_core_calendar_get_valid_event_timestart_range($event, $feedback);
$this->assertNull($min);
$this->assertNull($max);
}
- /**
- * You can't create a feedback module event when the module doesn't exist.
- */
- public function test_mod_feedback_core_calendar_validate_event_timestart_no_activity() {
- global $CFG;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'feedback',
- 'instance' => 1234,
- 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
- 'timestart' => time(),
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_feedback_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A FEEDBACK_EVENT_TYPE_OPEN must be before the close time of the feedback activity.
- */
- public function test_mod_feedback_core_calendar_validate_event_timestart_valid_open_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
- $feedback->timeopen = $timeopen;
- $feedback->timeclose = $timeclose;
- $DB->update_record('feedback', $feedback);
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'feedback',
- 'instance' => $feedback->id,
- 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
- 'timestart' => $timeopen,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- // This will throw an exception if the event is invald.
- mod_feedback_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
- }
-
- /**
- * A FEEDBACK_EVENT_TYPE_OPEN can not have a start time set after the close time
- * of the feedback activity.
- */
- public function test_mod_feedback_core_calendar_validate_event_timestart_invalid_open_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
- $feedback->timeopen = $timeopen;
- $feedback->timeclose = $timeclose;
- $DB->update_record('feedback', $feedback);
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'feedback',
- 'instance' => $feedback->id,
- 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
- 'timestart' => $timeclose + 1,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_feedback_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A FEEDBACK_EVENT_TYPE_CLOSE must be after the open time of the feedback activity.
- */
- public function test_mod_feedback_core_calendar_validate_event_timestart_valid_close_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
- $feedback->timeopen = $timeopen;
- $feedback->timeclose = $timeclose;
- $DB->update_record('feedback', $feedback);
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'feedback',
- 'instance' => $feedback->id,
- 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
- 'timestart' => $timeclose,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- // This will throw an exception if the event is invald.
- mod_feedback_core_calendar_validate_event_timestart($event);
- $this->assertTrue(true);
- }
-
- /**
- * A FEEDBACK_EVENT_TYPE_CLOSE can not have a start time set before the open time
- * of the feedback activity.
- */
- public function test_mod_feedback_core_calendar_validate_event_timestart_invalid_close_event() {
- global $CFG, $DB;
- require_once($CFG->dirroot . "/calendar/lib.php");
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
- $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $feedback = $feedbackgenerator->create_instance(['course' => $course->id]);
- $feedback->timeopen = $timeopen;
- $feedback->timeclose = $timeclose;
- $DB->update_record('feedback', $feedback);
-
- // Create a valid event.
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'feedback',
- 'instance' => $feedback->id,
- 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
- 'timestart' => $timeopen - 1,
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_feedback_core_calendar_validate_event_timestart($event);
- }
-
/**
* An unkown event type should not change the feedback instance.
*/
'visible' => 1
]);
- mod_feedback_core_calendar_event_timestart_updated($event);
+ mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
$feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
$this->assertEquals($timeopen, $feedback->timeopen);
'visible' => 1
]);
- mod_feedback_core_calendar_event_timestart_updated($event);
+ mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
$feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
// Ensure the timeopen property matches the event timestart.
'visible' => 1
]);
- mod_feedback_core_calendar_event_timestart_updated($event);
+ mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
$feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
// Ensure the timeclose property matches the event timestart.
$this->setUser($user);
- mod_feedback_core_calendar_event_timestart_updated($event);
+ mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
$newfeedback = $DB->get_record('feedback', ['id' => $feedback->id]);
// The activity shouldn't have been updated because the user
$sink = $this->redirectEvents();
- mod_feedback_core_calendar_event_timestart_updated($event);
+ mod_feedback_core_calendar_event_timestart_updated($event, $feedback);
$triggeredevents = $sink->get_events();
$moduleupdatedevents = array_filter($triggeredevents, function($e) {
* [1506741172, 'The date must be before this date']
* ]
*
+ * @throws \moodle_exception
* @param \calendar_event $event The calendar event to get the time range for
- * @param stdClass|null $quiz The module instance to get the range from
+ * @param stdClass $quiz The module instance to get the range from
* @return array
*/
-function mod_quiz_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $quiz = null) {
+function mod_quiz_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $quiz) {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
return [null, null];
}
- if (!$quiz) {
- $quiz = $DB->get_record('quiz', ['id' => $event->instance]);
- }
-
$mindate = null;
$maxdate = null;
return [$mindate, $maxdate];
}
-/**
- * This function will check that the given event is valid for it's
- * corresponding quiz module.
- *
- * An exception is thrown if the event fails validation.
- *
- * @throws \moodle_exception
- * @param \calendar_event $event
- * @return bool
- */
-function mod_quiz_core_calendar_validate_event_timestart(\calendar_event $event) {
- global $DB;
-
- if (!isset($event->instance)) {
- return;
- }
-
- // Something weird going on. The event is for a different module so
- // we should ignore it.
- if ($event->modulename != 'quiz') {
- return;
- }
-
- // We need to read from the DB directly because course module may
- // currently be getting created so it won't be in mod info yet.
- $quiz = $DB->get_record('quiz', ['id' => $event->instance], '*', MUST_EXIST);
- $timestart = $event->timestart;
- list($min, $max) = mod_quiz_core_calendar_get_valid_event_timestart_range($event, $quiz);
-
- if ($min && $timestart < $min[0]) {
- throw new \moodle_exception($min[1]);
- }
-
- if ($max && $timestart > $max[0]) {
- throw new \moodle_exception($max[1]);
- }
-}
-
/**
* This function will update the quiz module according to the
* event that has been modified.
* according to the type of event provided.
*
* @throws \moodle_exception
- * @param \calendar_event $event
+ * @param \calendar_event $event A quiz activity calendar event
+ * @param \stdClass $quiz A quiz activity instance
*/
-function mod_quiz_core_calendar_event_timestart_updated(\calendar_event $event) {
+function mod_quiz_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $quiz) {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
- // We don't update the activity if it's an override event that has
- // been modified.
- if (quiz_is_overriden_calendar_event($event)) {
+ if (!in_array($event->eventtype, [QUIZ_EVENT_TYPE_OPEN, QUIZ_EVENT_TYPE_CLOSE])) {
+ // This isn't an event that we care about so we can ignore it.
return;
}
return;
}
+ if ($quiz->id != $instanceid) {
+ // The provided quiz instance doesn't match the event so
+ // there is nothing to do here.
+ return;
+ }
+
+ // We don't update the activity if it's an override event that has
+ // been modified.
+ if (quiz_is_overriden_calendar_event($event)) {
+ return;
+ }
+
$coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid];
$context = context_module::instance($coursemodule->id);
// If the event is for the quiz activity opening then we should
// set the start time of the quiz activity to be the new start
// time of the event.
- $quiz = $DB->get_record('quiz', ['id' => $instanceid], '*', MUST_EXIST);
-
if ($quiz->timeopen != $event->timestart) {
$quiz->timeopen = $event->timestart;
$modified = true;
// If the event is for the quiz activity closing then we should
// set the end time of the quiz activity to be the new start
// time of the event.
- $quiz = $DB->get_record('quiz', ['id' => $instanceid], '*', MUST_EXIST);
-
if ($quiz->timeclose != $event->timestart) {
$quiz->timeclose = $event->timestart;
$modified = true;
return new \calendar_event(array_merge($defaultproperties, $eventproperties));
}
- /**
- * You can't create a quiz module event when the module doesn't exist.
- */
- public function test_mod_quiz_core_calendar_validate_event_timestart_no_activity() {
- global $CFG;
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $generator = $this->getDataGenerator();
- $course = $generator->create_course();
-
- $event = new \calendar_event([
- 'name' => 'Test event',
- 'description' => '',
- 'format' => 1,
- 'courseid' => $course->id,
- 'groupid' => 0,
- 'userid' => 2,
- 'modulename' => 'quiz',
- 'instance' => 1234,
- 'eventtype' => QUIZ_EVENT_TYPE_OPEN,
- 'timestart' => time(),
- 'timeduration' => 86400,
- 'visible' => 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_quiz_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A QUIZ_EVENT_TYPE_OPEN must be before the close time of the quiz activity.
- */
- public function test_mod_quiz_core_calendar_validate_event_timestart_valid_open_event() {
- global $DB;
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $quiz = $this->create_quiz_instance(['timeopen' => $timeopen, 'timeclose' => $timeclose]);
- $event = $this->create_quiz_calendar_event($quiz, [
- 'eventtype' => QUIZ_EVENT_TYPE_OPEN,
- 'timestart' => $timeopen
- ]);
-
- mod_quiz_core_calendar_validate_event_timestart($event);
- // The function above will throw an exception if the event is
- // invalid.
- $this->assertTrue(true);
- }
-
- /**
- * A QUIZ_EVENT_TYPE_OPEN can not have a start time set after the close time
- * of the quiz activity.
- */
- public function test_mod_quiz_core_calendar_validate_event_timestart_invalid_open_event() {
- global $DB;
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $quiz = $this->create_quiz_instance(['timeopen' => $timeopen, 'timeclose' => $timeclose]);
- $event = $this->create_quiz_calendar_event($quiz, [
- 'eventtype' => QUIZ_EVENT_TYPE_OPEN,
- 'timestart' => $timeclose + 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_quiz_core_calendar_validate_event_timestart($event);
- }
-
- /**
- * A QUIZ_EVENT_TYPE_CLOSE must be after the open time of the quiz activity.
- */
- public function test_mod_quiz_core_calendar_validate_event_timestart_valid_close_event() {
- global $DB;
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $quiz = $this->create_quiz_instance(['timeopen' => $timeopen, 'timeclose' => $timeclose]);
- $event = $this->create_quiz_calendar_event($quiz, [
- 'eventtype' => QUIZ_EVENT_TYPE_OPEN,
- 'timestart' => $timeclose
- ]);
-
- mod_quiz_core_calendar_validate_event_timestart($event);
- // The function above will throw an exception if the event isn't
- // valid.
- $this->assertTrue(true);
- }
-
- /**
- * A QUIZ_EVENT_TYPE_CLOSE can not have a start time set before the open time
- * of the quiz activity.
- */
- public function test_mod_quiz_core_calendar_validate_event_timestart_invalid_close_event() {
- global $DB;
-
- $this->resetAfterTest(true);
- $this->setAdminUser();
- $timeopen = time();
- $timeclose = $timeopen + DAYSECS;
- $quiz = $this->create_quiz_instance(['timeopen' => $timeopen, 'timeclose' => $timeclose]);
- $event = $this->create_quiz_calendar_event($quiz, [
- 'eventtype' => QUIZ_EVENT_TYPE_CLOSE,
- 'timestart' => $timeopen - 1
- ]);
-
- $this->expectException('moodle_exception');
- mod_quiz_core_calendar_validate_event_timestart($event);
- }
-
/**
* An unkown event type should not change the quiz instance.
*/
'timestart' => 1
]);
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$quiz = $DB->get_record('quiz', ['id' => $quiz->id]);
$this->assertEquals($timeopen, $quiz->timeopen);
'timestart' => $newtimeopen
]);
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$quiz = $DB->get_record('quiz', ['id' => $quiz->id]);
// Ensure the timeopen property matches the event timestart.
'timestart' => $newtimeclose
]);
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$quiz = $DB->get_record('quiz', ['id' => $quiz->id]);
// Ensure the timeclose property matches the event timestart.
$DB->insert_record('quiz_overrides', $record);
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$quiz = $DB->get_record('quiz', ['id' => $quiz->id]);
// Ensure the timeopen property doesn't change.
$this->setUser($user);
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$newquiz = $DB->get_record('quiz', ['id' => $quiz->id]);
// The time open shouldn't have changed even though we updated the calendar
// Trigger and capture the event.
$sink = $this->redirectEvents();
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$triggeredevents = $sink->get_events();
$moduleupdatedevents = array_filter($triggeredevents, function($e) {
$this->setUser($teacher);
- mod_quiz_core_calendar_event_timestart_updated($event);
+ mod_quiz_core_calendar_event_timestart_updated($event, $quiz);
$quiz = $DB->get_record('quiz', ['id' => $quiz->id]);
$attempt = $DB->get_record('quiz_attempts', ['id' => $attemptid]);