Merge branch 'MDL-33509-master' of git://github.com/mihailges/moodle
[moodle.git] / calendar / tests / local_api_test.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Contains the class containing unit tests for the calendar local API.
19  *
20  * @package    core_calendar
21  * @copyright  2017 Mark Nelson <markn@moodle.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 require_once(__DIR__ . '/helpers.php');
29 use \core_calendar\local\event\container;
31 /**
32  * Class contaning unit tests for the calendar local API.
33  *
34  * @package    core_calendar
35  * @copyright  2017 Mark Nelson <markn@moodle.com>
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class core_calendar_local_api_testcase extends advanced_testcase {
40     /**
41      * Tests set up
42      */
43     protected function setUp() {
44         $this->resetAfterTest();
45     }
47     /**
48      * Create a feedback activity instance and a calendar event for
49      * that instance.
50      *
51      * @param array $feedbackproperties Properties to set on the feedback activity
52      * @param array $eventproperties Properties to set on the calendar event
53      * @return array The feedback activity and the calendar event
54      */
55     protected function create_feedback_activity_and_event(array $feedbackproperties = [], array $eventproperties = []) {
56         $generator = $this->getDataGenerator();
57         $course = $generator->create_course();
58         $mapper = container::get_event_mapper();
59         $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
60         $feedback = $feedbackgenerator->create_instance(array_merge(
61             ['course' => $course->id],
62             $feedbackproperties
63         ));
65         $event = create_event(array_merge(
66             [
67                 'courseid' => $course->id,
68                 'modulename' => 'feedback',
69                 'instance' => $feedback->id
70             ],
71              $eventproperties
72         ));
73         $event = $mapper->from_legacy_event_to_event($event);
75         return [$feedback, $event];
76     }
78     /**
79      * Requesting calendar events from a given time should return all events with a sort
80      * time at or after the requested time. All events prior to that time should not
81      * be return.
82      *
83      * If there are no events on or after the given time then an empty result set should
84      * be returned.
85      */
86     public function test_get_calendar_action_events_by_timesort_after_time() {
87         $user = $this->getDataGenerator()->create_user();
88         $course = $this->getDataGenerator()->create_course();
89         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
90         $moduleinstance = $generator->create_instance(['course' => $course->id]);
92         $this->getDataGenerator()->enrol_user($user->id, $course->id);
93         $this->resetAfterTest(true);
94         $this->setAdminUser();
96         $params = [
97             'type' => CALENDAR_EVENT_TYPE_ACTION,
98             'courseid' => $course->id,
99             'modulename' => 'assign',
100             'instance' => $moduleinstance->id,
101             'userid' => $user->id,
102             'eventtype' => 'user',
103             'repeats' => 0,
104             'timestart' => 1,
105         ];
107         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
108         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
109         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
110         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
111         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
112         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
113         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
114         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
116         $this->setUser($user);
117         $result = \core_calendar\local\api::get_action_events_by_timesort(5);
119         $this->assertCount(4, $result);
120         $this->assertEquals('Event 5', $result[0]->get_name());
121         $this->assertEquals('Event 6', $result[1]->get_name());
122         $this->assertEquals('Event 7', $result[2]->get_name());
123         $this->assertEquals('Event 8', $result[3]->get_name());
125         $result = \core_calendar\local\api::get_action_events_by_timesort(9);
127         $this->assertEmpty($result);
128     }
130     /**
131      * Requesting calendar events before a given time should return all events with a sort
132      * time at or before the requested time (inclusive). All events after that time
133      * should not be returned.
134      *
135      * If there are no events before the given time then an empty result set should be
136      * returned.
137      */
138     public function test_get_calendar_action_events_by_timesort_before_time() {
139         $user = $this->getDataGenerator()->create_user();
140         $course = $this->getDataGenerator()->create_course();
141         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
142         $moduleinstance = $generator->create_instance(['course' => $course->id]);
144         $this->getDataGenerator()->enrol_user($user->id, $course->id);
145         $this->resetAfterTest(true);
146         $this->setAdminUser();
148         $params = [
149             'type' => CALENDAR_EVENT_TYPE_ACTION,
150             'courseid' => $course->id,
151             'modulename' => 'assign',
152             'instance' => $moduleinstance->id,
153             'userid' => 1,
154             'eventtype' => 'user',
155             'repeats' => 0,
156             'timestart' => 1,
157         ];
159         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 2]));
160         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 3]));
161         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 4]));
162         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 5]));
163         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 6]));
164         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 7]));
165         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 8]));
166         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 9]));
168         $this->setUser($user);
169         $result = \core_calendar\local\api::get_action_events_by_timesort(null, 5);
171         $this->assertCount(4, $result);
172         $this->assertEquals('Event 1', $result[0]->get_name());
173         $this->assertEquals('Event 2', $result[1]->get_name());
174         $this->assertEquals('Event 3', $result[2]->get_name());
175         $this->assertEquals('Event 4', $result[3]->get_name());
177         $result = \core_calendar\local\api::get_action_events_by_timesort(null, 1);
179         $this->assertEmpty($result);
180     }
182     /**
183      * Requesting calendar events within a given time range should return all events with
184      * a sort time between the lower and upper time bound (inclusive).
185      *
186      * If there are no events in the given time range then an empty result set should be
187      * returned.
188      */
189     public function test_get_calendar_action_events_by_timesort_time_range() {
190         $user = $this->getDataGenerator()->create_user();
191         $course = $this->getDataGenerator()->create_course();
192         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
193         $moduleinstance = $generator->create_instance(['course' => $course->id]);
195         $this->getDataGenerator()->enrol_user($user->id, $course->id);
196         $this->resetAfterTest(true);
197         $this->setAdminUser();
199         $params = [
200             'type' => CALENDAR_EVENT_TYPE_ACTION,
201             'courseid' => $course->id,
202             'modulename' => 'assign',
203             'instance' => $moduleinstance->id,
204             'userid' => 1,
205             'eventtype' => 'user',
206             'repeats' => 0,
207             'timestart' => 1,
208         ];
210         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
211         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
212         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
213         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
214         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
215         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
216         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
217         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
219         $this->setUser($user);
220         $result = \core_calendar\local\api::get_action_events_by_timesort(3, 6);
222         $this->assertCount(4, $result);
223         $this->assertEquals('Event 3', $result[0]->get_name());
224         $this->assertEquals('Event 4', $result[1]->get_name());
225         $this->assertEquals('Event 5', $result[2]->get_name());
226         $this->assertEquals('Event 6', $result[3]->get_name());
228         $result = \core_calendar\local\api::get_action_events_by_timesort(10, 15);
230         $this->assertEmpty($result);
231     }
233     /**
234      * Requesting calendar events within a given time range and a limit and offset should return
235      * the number of events up to the given limit value that have a sort time between the lower
236      * and uppper time bound (inclusive) where the result set is shifted by the offset value.
237      *
238      * If there are no events in the given time range then an empty result set should be
239      * returned.
240      */
241     public function test_get_calendar_action_events_by_timesort_time_limit_offset() {
242         $user = $this->getDataGenerator()->create_user();
243         $course = $this->getDataGenerator()->create_course();
244         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
245         $moduleinstance = $generator->create_instance(['course' => $course->id]);
247         $this->getDataGenerator()->enrol_user($user->id, $course->id);
248         $this->resetAfterTest(true);
249         $this->setAdminUser();
251         $params = [
252             'type' => CALENDAR_EVENT_TYPE_ACTION,
253             'courseid' => $course->id,
254             'modulename' => 'assign',
255             'instance' => $moduleinstance->id,
256             'userid' => 1,
257             'eventtype' => 'user',
258             'repeats' => 0,
259             'timestart' => 1,
260         ];
262         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
263         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
264         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
265         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
266         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
267         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
268         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
269         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
271         $this->setUser($user);
272         $result = \core_calendar\local\api::get_action_events_by_timesort(2, 7, $event3->id, 2);
274         $this->assertCount(2, $result);
275         $this->assertEquals('Event 4', $result[0]->get_name());
276         $this->assertEquals('Event 5', $result[1]->get_name());
278         $result = \core_calendar\local\api::get_action_events_by_timesort(2, 7, $event5->id, 2);
280         $this->assertCount(2, $result);
281         $this->assertEquals('Event 6', $result[0]->get_name());
282         $this->assertEquals('Event 7', $result[1]->get_name());
284         $result = \core_calendar\local\api::get_action_events_by_timesort(2, 7, $event7->id, 2);
286         $this->assertEmpty($result);
287     }
289     /**
290      * Requesting calendar events from a given course and time should return all
291      * events with a sort time at or after the requested time. All events prior
292      * to that time should not be return.
293      *
294      * If there are no events on or after the given time then an empty result set should
295      * be returned.
296      */
297     public function test_get_calendar_action_events_by_course_after_time() {
298         $user = $this->getDataGenerator()->create_user();
299         $course1 = $this->getDataGenerator()->create_course();
300         $course2 = $this->getDataGenerator()->create_course();
301         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
302         $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
303         $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
305         $this->getDataGenerator()->enrol_user($user->id, $course1->id);
306         $this->getDataGenerator()->enrol_user($user->id, $course2->id);
307         $this->resetAfterTest(true);
308         $this->setUser($user);
310         $params = [
311             'type' => CALENDAR_EVENT_TYPE_ACTION,
312             'modulename' => 'assign',
313             'instance' => $moduleinstance1->id,
314             'userid' => $user->id,
315             'courseid' => $course1->id,
316             'eventtype' => 'user',
317             'repeats' => 0,
318             'timestart' => 1,
319         ];
321         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
322         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
323         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
324         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
325         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
326         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
327         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
328         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
330         $params['courseid'] = $course2->id;
331         $params['instance'] = $moduleinstance2->id;
332         $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 1]));
333         $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 2]));
334         $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 3]));
335         $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 4]));
336         $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 5]));
337         $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 6]));
338         $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 7]));
339         $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 8]));
341         $result = \core_calendar\local\api::get_action_events_by_course($course1, 5);
343         $this->assertCount(4, $result);
344         $this->assertEquals('Event 5', $result[0]->get_name());
345         $this->assertEquals('Event 6', $result[1]->get_name());
346         $this->assertEquals('Event 7', $result[2]->get_name());
347         $this->assertEquals('Event 8', $result[3]->get_name());
349         $result = \core_calendar\local\api::get_action_events_by_course($course1, 9);
351         $this->assertEmpty($result);
352     }
354     /**
355      * Requesting calendar events for a course and before a given time should return
356      * all events with a sort time at or before the requested time (inclusive). All
357      * events after that time should not be returned.
358      *
359      * If there are no events before the given time then an empty result set should be
360      * returned.
361      */
362     public function test_get_calendar_action_events_by_course_before_time() {
363         $user = $this->getDataGenerator()->create_user();
364         $course1 = $this->getDataGenerator()->create_course();
365         $course2 = $this->getDataGenerator()->create_course();
366         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
367         $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
368         $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
370         $this->getDataGenerator()->enrol_user($user->id, $course1->id);
371         $this->getDataGenerator()->enrol_user($user->id, $course2->id);
372         $this->resetAfterTest(true);
373         $this->setUser($user);
375         $params = [
376             'type' => CALENDAR_EVENT_TYPE_ACTION,
377             'modulename' => 'assign',
378             'instance' => $moduleinstance1->id,
379             'userid' => $user->id,
380             'courseid' => $course1->id,
381             'eventtype' => 'user',
382             'repeats' => 0,
383             'timestart' => 1,
384         ];
386         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 2]));
387         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 3]));
388         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 4]));
389         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 5]));
390         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 6]));
391         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 7]));
392         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 8]));
393         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 9]));
395         $params['courseid'] = $course2->id;
396         $params['instance'] = $moduleinstance2->id;
397         $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 2]));
398         $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 3]));
399         $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 4]));
400         $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 5]));
401         $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 6]));
402         $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 7]));
403         $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 8]));
404         $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 9]));
406         $result = \core_calendar\local\api::get_action_events_by_course($course1, null, 5);
408         $this->assertCount(4, $result);
409         $this->assertEquals('Event 1', $result[0]->get_name());
410         $this->assertEquals('Event 2', $result[1]->get_name());
411         $this->assertEquals('Event 3', $result[2]->get_name());
412         $this->assertEquals('Event 4', $result[3]->get_name());
414         $result = \core_calendar\local\api::get_action_events_by_course($course1, null, 1);
416         $this->assertEmpty($result);
417     }
419     /**
420      * Requesting calendar events for a course and within a given time range should
421      * return all events with a sort time between the lower and upper time bound
422      * (inclusive).
423      *
424      * If there are no events in the given time range then an empty result set should be
425      * returned.
426      */
427     public function test_get_calendar_action_events_by_course_time_range() {
428         $user = $this->getDataGenerator()->create_user();
429         $course1 = $this->getDataGenerator()->create_course();
430         $course2 = $this->getDataGenerator()->create_course();
431         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
432         $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
433         $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
435         $this->getDataGenerator()->enrol_user($user->id, $course1->id);
436         $this->getDataGenerator()->enrol_user($user->id, $course2->id);
437         $this->resetAfterTest(true);
438         $this->setUser($user);
440         $params = [
441             'type' => CALENDAR_EVENT_TYPE_ACTION,
442             'modulename' => 'assign',
443             'instance' => $moduleinstance1->id,
444             'userid' => $user->id,
445             'courseid' => $course1->id,
446             'eventtype' => 'user',
447             'repeats' => 0,
448             'timestart' => 1,
449         ];
451         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
452         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
453         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
454         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
455         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
456         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
457         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
458         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
460         $params['courseid'] = $course2->id;
461         $params['instance'] = $moduleinstance2->id;
462         $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 1]));
463         $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 2]));
464         $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 3]));
465         $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 4]));
466         $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 5]));
467         $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 6]));
468         $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 7]));
469         $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 8]));
471         $result = \core_calendar\local\api::get_action_events_by_course($course1, 3, 6);
473         $this->assertCount(4, $result);
474         $this->assertEquals('Event 3', $result[0]->get_name());
475         $this->assertEquals('Event 4', $result[1]->get_name());
476         $this->assertEquals('Event 5', $result[2]->get_name());
477         $this->assertEquals('Event 6', $result[3]->get_name());
479         $result = \core_calendar\local\api::get_action_events_by_course($course1, 10, 15);
481         $this->assertEmpty($result);
482     }
484     /**
485      * Requesting calendar events for a course and within a given time range and a limit
486      * and offset should return the number of events up to the given limit value that have
487      * a sort time between the lower and uppper time bound (inclusive) where the result
488      * set is shifted by the offset value.
489      *
490      * If there are no events in the given time range then an empty result set should be
491      * returned.
492      */
493     public function test_get_calendar_action_events_by_course_time_limit_offset() {
494         $user = $this->getDataGenerator()->create_user();
495         $course1 = $this->getDataGenerator()->create_course();
496         $course2 = $this->getDataGenerator()->create_course();
497         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
498         $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
499         $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
501         $this->getDataGenerator()->enrol_user($user->id, $course1->id);
502         $this->getDataGenerator()->enrol_user($user->id, $course2->id);
503         $this->resetAfterTest(true);
504         $this->setUser($user);
506         $params = [
507             'type' => CALENDAR_EVENT_TYPE_ACTION,
508             'modulename' => 'assign',
509             'instance' => $moduleinstance1->id,
510             'userid' => $user->id,
511             'courseid' => $course1->id,
512             'eventtype' => 'user',
513             'repeats' => 0,
514             'timestart' => 1,
515         ];
517         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
518         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
519         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
520         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
521         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
522         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
523         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
524         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
526         $params['courseid'] = $course2->id;
527         $params['instance'] = $moduleinstance2->id;
528         $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 1]));
529         $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 2]));
530         $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 3]));
531         $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 4]));
532         $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 5]));
533         $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 6]));
534         $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 7]));
535         $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 8]));
537         $result = \core_calendar\local\api::get_action_events_by_course($course1, 2, 7, $event3->id, 2);
539         $this->assertCount(2, $result);
540         $this->assertEquals('Event 4', $result[0]->get_name());
541         $this->assertEquals('Event 5', $result[1]->get_name());
543         $result = \core_calendar\local\api::get_action_events_by_course($course1, 2, 7, $event5->id, 2);
545         $this->assertCount(2, $result);
546         $this->assertEquals('Event 6', $result[0]->get_name());
547         $this->assertEquals('Event 7', $result[1]->get_name());
549         $result = \core_calendar\local\api::get_action_events_by_course($course1, 2, 7, $event7->id, 2);
551         $this->assertEmpty($result);
552     }
554     /**
555      * Test that get_action_events_by_courses will return a list of events for each
556      * course you provided as long as the user is enrolled in the course.
557      */
558     public function test_get_action_events_by_courses() {
559         $user = $this->getDataGenerator()->create_user();
560         $course1 = $this->getDataGenerator()->create_course();
561         $course2 = $this->getDataGenerator()->create_course();
562         $course3 = $this->getDataGenerator()->create_course();
563         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
564         $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
565         $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
566         $moduleinstance3 = $generator->create_instance(['course' => $course3->id]);
568         $this->getDataGenerator()->enrol_user($user->id, $course1->id);
569         $this->getDataGenerator()->enrol_user($user->id, $course2->id);
570         $this->getDataGenerator()->enrol_user($user->id, $course3->id);
571         $this->resetAfterTest(true);
572         $this->setUser($user);
574         $params = [
575             'type' => CALENDAR_EVENT_TYPE_ACTION,
576             'modulename' => 'assign',
577             'instance' => $moduleinstance1->id,
578             'userid' => $user->id,
579             'courseid' => $course1->id,
580             'eventtype' => 'user',
581             'repeats' => 0,
582             'timestart' => 1,
583         ];
585         $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
586         $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
588         $params['courseid'] = $course2->id;
589         $params['instance'] = $moduleinstance2->id;
590         $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
591         $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
592         $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
594         $params['courseid'] = $course3->id;
595         $params['instance'] = $moduleinstance3->id;
596         $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
597         $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
598         $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
599         $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 9]));
601         $result = \core_calendar\local\api::get_action_events_by_courses([], 1);
603         $this->assertEmpty($result);
605         $result = \core_calendar\local\api::get_action_events_by_courses([$course1], 3);
607         $this->assertEmpty($result[$course1->id]);
609         $result = \core_calendar\local\api::get_action_events_by_courses([$course1], 1);
611         $this->assertCount(2, $result[$course1->id]);
612         $this->assertEquals('Event 1', $result[$course1->id][0]->get_name());
613         $this->assertEquals('Event 2', $result[$course1->id][1]->get_name());
615         $result = \core_calendar\local\api::get_action_events_by_courses([$course1, $course2], 1);
617         $this->assertCount(2, $result[$course1->id]);
618         $this->assertEquals('Event 1', $result[$course1->id][0]->get_name());
619         $this->assertEquals('Event 2', $result[$course1->id][1]->get_name());
620         $this->assertCount(3, $result[$course2->id]);
621         $this->assertEquals('Event 3', $result[$course2->id][0]->get_name());
622         $this->assertEquals('Event 4', $result[$course2->id][1]->get_name());
623         $this->assertEquals('Event 5', $result[$course2->id][2]->get_name());
625         $result = \core_calendar\local\api::get_action_events_by_courses([$course1, $course2], 2, 4);
627         $this->assertCount(1, $result[$course1->id]);
628         $this->assertEquals('Event 2', $result[$course1->id][0]->get_name());
629         $this->assertCount(2, $result[$course2->id]);
630         $this->assertEquals('Event 3', $result[$course2->id][0]->get_name());
631         $this->assertEquals('Event 4', $result[$course2->id][1]->get_name());
633         $result = \core_calendar\local\api::get_action_events_by_courses([$course1, $course2, $course3], 1, null, 1);
635         $this->assertCount(1, $result[$course1->id]);
636         $this->assertEquals('Event 1', $result[$course1->id][0]->get_name());
637         $this->assertCount(1, $result[$course2->id]);
638         $this->assertEquals('Event 3', $result[$course2->id][0]->get_name());
639         $this->assertCount(1, $result[$course3->id]);
640         $this->assertEquals('Event 6', $result[$course3->id][0]->get_name());
641     }
643     /**
644      * Test that the get_legacy_events() function only returns activity events that are enabled.
645      */
646     public function test_get_legacy_events_with_disabled_module() {
647         global $DB;
649         $this->setAdminUser();
651         $course = $this->getDataGenerator()->create_course();
653         $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
654         $assigninstance = $assigngenerator->create_instance(['course' => $course->id]);
656         $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
657         $lessoninstance = $lessongenerator->create_instance(['course' => $course->id]);
658         $student = $this->getDataGenerator()->create_user();
659         $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
660         $this->setUser($student);
661         $events = [
662             [
663                 'name' => 'Start of assignment',
664                 'description' => '',
665                 'location' => 'Test',
666                 'format' => 1,
667                 'courseid' => $course->id,
668                 'groupid' => 0,
669                 'userid' => 2,
670                 'modulename' => 'assign',
671                 'instance' => $assigninstance->id,
672                 'eventtype' => 'due',
673                 'timestart' => time(),
674                 'timeduration' => 86400,
675                 'visible' => 1
676             ], [
677                 'name' => 'Start of lesson',
678                 'description' => '',
679                 'location' => 'Test',
680                 'format' => 1,
681                 'courseid' => $course->id,
682                 'groupid' => 0,
683                 'userid' => 2,
684                 'modulename' => 'lesson',
685                 'instance' => $lessoninstance->id,
686                 'eventtype' => 'end',
687                 'timestart' => time(),
688                 'timeduration' => 86400,
689                 'visible' => 1
690             ]
691         ];
692         foreach ($events as $event) {
693             calendar_event::create($event, false);
694         }
695         $timestart = time() - 60;
696         $timeend = time() + 60;
698         // Get all events.
699         $events = calendar_get_legacy_events($timestart, $timeend, true, 0, true);
700         $this->assertCount(2, $events);
702         // Disable the lesson module.
703         $modulerecord = $DB->get_record('modules', ['name' => 'lesson']);
704         $modulerecord->visible = 0;
705         $DB->update_record('modules', $modulerecord);
707         // Check that we only return the assign event.
708         $events = calendar_get_legacy_events($timestart, $timeend, true, 0, true);
709         $this->assertCount(1, $events);
710         $event = reset($events);
711         $this->assertEquals('assign', $event->modulename);
712     }
714     /**
715      * Test for \core_calendar\local\api::get_legacy_events() when there are user and group overrides.
716      */
717     public function test_get_legacy_events_with_overrides() {
718         $generator = $this->getDataGenerator();
720         $course = $generator->create_course();
722         $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
723         if (!isset($params['course'])) {
724             $params['course'] = $course->id;
725         }
727         $instance = $plugingenerator->create_instance($params);
729         // Create users.
730         $useroverridestudent = $generator->create_user();
731         $group1student = $generator->create_user();
732         $group2student = $generator->create_user();
733         $group12student = $generator->create_user();
734         $nogroupstudent = $generator->create_user();
736         // Enrol users.
737         $generator->enrol_user($useroverridestudent->id, $course->id, 'student');
738         $generator->enrol_user($group1student->id, $course->id, 'student');
739         $generator->enrol_user($group2student->id, $course->id, 'student');
740         $generator->enrol_user($group12student->id, $course->id, 'student');
741         $generator->enrol_user($nogroupstudent->id, $course->id, 'student');
743         // Create groups.
744         $group1 = $generator->create_group(['courseid' => $course->id]);
745         $group2 = $generator->create_group(['courseid' => $course->id]);
747         // Add members to groups.
748         $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
749         $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
750         $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
751         $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
752         $now = time();
754         // Events with the same module name, instance and event type.
755         $events = [
756             [
757                 'name' => 'Assignment 1 due date',
758                 'description' => '',
759                 'location' => 'Test',
760                 'format' => 0,
761                 'courseid' => $course->id,
762                 'groupid' => 0,
763                 'userid' => 2,
764                 'modulename' => 'assign',
765                 'instance' => $instance->id,
766                 'eventtype' => 'due',
767                 'timestart' => $now,
768                 'timeduration' => 0,
769                 'visible' => 1
770             ], [
771                 'name' => 'Assignment 1 due date - User override',
772                 'description' => '',
773                 'location' => 'Test',
774                 'format' => 1,
775                 'courseid' => 0,
776                 'groupid' => 0,
777                 'userid' => $useroverridestudent->id,
778                 'modulename' => 'assign',
779                 'instance' => $instance->id,
780                 'eventtype' => 'due',
781                 'timestart' => $now + 86400,
782                 'timeduration' => 0,
783                 'visible' => 1,
784                 'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
785             ], [
786                 'name' => 'Assignment 1 due date - Group A override',
787                 'description' => '',
788                 'location' => 'Test',
789                 'format' => 1,
790                 'courseid' => $course->id,
791                 'groupid' => $group1->id,
792                 'userid' => 2,
793                 'modulename' => 'assign',
794                 'instance' => $instance->id,
795                 'eventtype' => 'due',
796                 'timestart' => $now + (2 * 86400),
797                 'timeduration' => 0,
798                 'visible' => 1,
799                 'priority' => 1,
800             ], [
801                 'name' => 'Assignment 1 due date - Group B override',
802                 'description' => '',
803                 'location' => 'Test',
804                 'format' => 1,
805                 'courseid' => $course->id,
806                 'groupid' => $group2->id,
807                 'userid' => 2,
808                 'modulename' => 'assign',
809                 'instance' => $instance->id,
810                 'eventtype' => 'due',
811                 'timestart' => $now + (3 * 86400),
812                 'timeduration' => 0,
813                 'visible' => 1,
814                 'priority' => 2,
815             ],
816         ];
818         foreach ($events as $event) {
819             calendar_event::create($event, false);
820         }
822         $timestart = $now - 100;
823         $timeend = $now + (3 * 86400);
824         $groups = [$group1->id, $group2->id];
826         // Get user override events.
827         $this->setUser($useroverridestudent);
828         $events = calendar_get_legacy_events($timestart, $timeend, $useroverridestudent->id, $groups, $course->id);
829         $this->assertCount(1, $events);
830         $event = reset($events);
831         $this->assertEquals('Assignment 1 due date - User override', $event->name);
833         // Get event for user with override but with the timestart and timeend parameters only covering the original event.
834         $events = calendar_get_legacy_events($timestart, $now, $useroverridestudent->id, $groups, $course->id);
835         $this->assertCount(0, $events);
837         // Get events for user that does not belong to any group and has no user override events.
838         $this->setUser($nogroupstudent);
839         $events = calendar_get_legacy_events($timestart, $timeend, $nogroupstudent->id, $groups, $course->id);
840         $this->assertCount(1, $events);
841         $event = reset($events);
842         $this->assertEquals('Assignment 1 due date', $event->name);
844         // Get events for user that belongs to groups A and B and has no user override events.
845         $this->setUser($group12student);
846         $events = calendar_get_legacy_events($timestart, $timeend, $group12student->id, $groups, $course->id);
847         $this->assertCount(1, $events);
848         $event = reset($events);
849         $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
851         // Get events for user that belongs to group A and has no user override events.
852         $this->setUser($group1student);
853         $events = calendar_get_legacy_events($timestart, $timeend, $group1student->id, $groups, $course->id);
854         $this->assertCount(1, $events);
855         $event = reset($events);
856         $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
858         // Add repeating events.
859         $repeatingevents = [
860             [
861                 'name' => 'Repeating site event',
862                 'description' => '',
863                 'location' => 'Test',
864                 'format' => 1,
865                 'courseid' => SITEID,
866                 'groupid' => 0,
867                 'userid' => 2,
868                 'repeatid' => $event->id,
869                 'modulename' => '0',
870                 'instance' => 0,
871                 'eventtype' => 'site',
872                 'timestart' => $now + 86400,
873                 'timeduration' => 0,
874                 'visible' => 1,
875             ],
876             [
877                 'name' => 'Repeating site event',
878                 'description' => '',
879                 'location' => 'Test',
880                 'format' => 1,
881                 'courseid' => SITEID,
882                 'groupid' => 0,
883                 'userid' => 2,
884                 'repeatid' => $event->id,
885                 'modulename' => '0',
886                 'instance' => 0,
887                 'eventtype' => 'site',
888                 'timestart' => $now + (2 * 86400),
889                 'timeduration' => 0,
890                 'visible' => 1,
891             ],
892         ];
894         foreach ($repeatingevents as $event) {
895             calendar_event::create($event, false);
896         }
898         // Make sure repeating events are not filtered out.
899         $events = calendar_get_legacy_events($timestart, $timeend, true, true, true);
900         $this->assertCount(3, $events);
901     }
903     /**
904      * Setting the start date on the calendar event should update the date
905      * of the event but should leave the time of day unchanged.
906      */
907     public function test_update_event_start_day_updates_date() {
908         $generator = $this->getDataGenerator();
909         $user = $generator->create_user();
910         $roleid = $generator->create_role();
911         $context = \context_system::instance();
912         $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
913         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
914         $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
915         $mapper = container::get_event_mapper();
917         $generator->role_assign($roleid, $user->id, $context->id);
918         assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
920         $this->setUser($user);
921         $this->resetAfterTest(true);
923         $event = create_event([
924             'name' => 'Test event',
925             'userid' => $user->id,
926             'eventtype' => 'user',
927             'repeats' => 0,
928             'timestart' => $originalstarttime->getTimestamp(),
929         ]);
930         $event = $mapper->from_legacy_event_to_event($event);
932         $newEvent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
933         $actual = $newEvent->get_times()->get_start_time();
935         $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
936     }
938     /**
939      * A user should not be able to update the start date of the event
940      * that they don't have the capabilities to modify.
941      */
942     public function test_update_event_start_day_no_permission() {
943         $generator = $this->getDataGenerator();
944         $user = $generator->create_user();
945         $roleid = $generator->create_role();
946         $context = \context_system::instance();
947         $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
948         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
949         $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
950         $mapper = container::get_event_mapper();
952         $generator->role_assign($roleid, $user->id, $context->id);
954         $this->setUser($user);
955         $this->resetAfterTest(true);
957         $event = create_event([
958             'name' => 'Test event',
959             'userid' => $user->id,
960             'eventtype' => 'user',
961             'repeats' => 0,
962             'timestart' => $originalstarttime->getTimestamp(),
963         ]);
964         $event = $mapper->from_legacy_event_to_event($event);
966         assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
967         $this->expectException('moodle_exception');
968         $newEvent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
969     }
971     /**
972      * Updating the start day of an event with no maximum cutoff should
973      * update the corresponding activity property.
974      *
975      * Note: This test uses the feedback activity because it requires
976      * module callbacks to be in place to test.
977      */
978     public function test_update_event_start_day_activity_event_no_max() {
979         global $CFG, $DB;
980         require_once($CFG->dirroot . '/mod/feedback/lib.php');
982         $this->resetAfterTest(true);
983         $this->setAdminUser();
984         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
985         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
986         $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
987         list($feedback, $event) = $this->create_feedback_activity_and_event(
988             [
989                 'timeopen' => $timeopen->getTimestamp(),
990                 'timeclose' => 0
991             ],
992             [
993                 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
994                 'timestart' => $timeopen->getTimestamp()
995             ]
996         );
997         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
998         $actual = $newevent->get_times()->get_start_time();
999         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1001         $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1002         $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
1003     }
1005     /**
1006      * Updating the start day of an event belonging to an activity to a value
1007      * less than the maximum cutoff should update the corresponding activity
1008      * property.
1009      *
1010      * Note: This test uses the feedback activity because it requires
1011      * module callbacks to be in place to test.
1012      */
1013     public function test_update_event_start_day_activity_event_less_than_max() {
1014         global $CFG, $DB;
1015         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1017         $this->resetAfterTest(true);
1018         $this->setAdminUser();
1019         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1020         $timeclose = new DateTimeImmutable('2019-01-1T15:00:00+08:00');
1021         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1022         $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1023         list($feedback, $event) = $this->create_feedback_activity_and_event(
1024             [
1025                 'timeopen' => $timeopen->getTimestamp(),
1026                 'timeclose' => $timeclose->getTimestamp()
1027             ],
1028             [
1029                 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1030                 'timestart' => $timeopen->getTimestamp()
1031             ]
1032         );
1034         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1035         $actual = $newevent->get_times()->get_start_time();
1036         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1038         $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1039         $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
1040     }
1042     /**
1043      * Updating the start day of an event belonging to an activity to a value
1044      * equal to the maximum cutoff should update the corresponding activity
1045      * property.
1046      *
1047      * Note: This test uses the feedback activity because it requires
1048      * module callbacks to be in place to test.
1049      */
1050     public function test_update_event_start_day_activity_event_equal_to_max() {
1051         global $CFG, $DB;
1052         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1054         $this->resetAfterTest(true);
1055         $this->setAdminUser();
1056         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1057         $timeclose = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1058         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1059         list($feedback, $event) = $this->create_feedback_activity_and_event(
1060             [
1061                 'timeopen' => $timeopen->getTimestamp(),
1062                 'timeclose' => $timeclose->getTimestamp(),
1063             ],
1064             [
1065                 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1066                 'timestart' => $timeopen->getTimestamp()
1067             ]
1068         );
1070         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1071         $actual = $newevent->get_times()->get_start_time();
1072         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1074         $this->assertEquals($timeclose->getTimestamp(), $actual->getTimestamp());
1075         $this->assertEquals($timeclose->getTimestamp(), $feedback->timeopen);
1076     }
1078     /**
1079      * Updating the start day of an event belonging to an activity to a value
1080      * after the maximum cutoff should not update the corresponding activity
1081      * property. Instead it should throw an exception.
1082      *
1083      * Note: This test uses the feedback activity because it requires
1084      * module callbacks to be in place to test.
1085      */
1086     public function test_update_event_start_day_activity_event_after_max() {
1087         global $CFG, $DB;
1088         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1090         $this->resetAfterTest(true);
1091         $this->setAdminUser();
1092         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1093         $timeclose = new DateTimeImmutable('2017-02-2T15:00:00+08:00');
1094         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1095         list($feedback, $event) = $this->create_feedback_activity_and_event(
1096             [
1097                 'timeopen' => $timeopen->getTimestamp(),
1098                 'timeclose' => $timeclose->getTimestamp(),
1099             ],
1100             [
1101                 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1102                 'timestart' => $timeopen->getTimestamp()
1103             ]
1104         );
1106         $this->expectException('moodle_exception');
1107         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1108     }
1110     /**
1111      * Updating the start day of an event with no minimum cutoff should
1112      * update the corresponding activity property.
1113      *
1114      * Note: This test uses the feedback activity because it requires
1115      * module callbacks to be in place to test.
1116      */
1117     public function test_update_event_start_day_activity_event_no_min() {
1118         global $CFG, $DB;
1119         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1121         $this->resetAfterTest(true);
1122         $this->setAdminUser();
1123         $timeclose = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1124         $newstartdate = new DateTimeImmutable('2016-02-2T10:00:00+08:00');
1125         $expected = new DateTimeImmutable('2016-02-2T15:00:00+08:00');
1126         list($feedback, $event) = $this->create_feedback_activity_and_event(
1127             [
1128                 'timeopen' => 0,
1129                 'timeclose' => $timeclose->getTimestamp()
1130             ],
1131             [
1132                 'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1133                 'timestart' => $timeclose->getTimestamp()
1134             ]
1135         );
1137         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1138         $actual = $newevent->get_times()->get_start_time();
1139         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1141         $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1142         $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
1143     }
1145     /**
1146      * Updating the start day of an event belonging to an activity to a value
1147      * greater than the minimum cutoff should update the corresponding activity
1148      * property.
1149      *
1150      * Note: This test uses the feedback activity because it requires
1151      * module callbacks to be in place to test.
1152      */
1153     public function test_update_event_start_day_activity_event_greater_than_min() {
1154         global $CFG, $DB;
1155         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1157         $this->resetAfterTest(true);
1158         $this->setAdminUser();
1159         $timeopen = new DateTimeImmutable('2016-01-1T15:00:00+08:00');
1160         $timeclose = new DateTimeImmutable('2019-01-1T15:00:00+08:00');
1161         $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1162         $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1163         list($feedback, $event) = $this->create_feedback_activity_and_event(
1164             [
1165                 'timeopen' => $timeopen->getTimestamp(),
1166                 'timeclose' => $timeclose->getTimestamp()
1167             ],
1168             [
1169                 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
1170                 'timestart' => $timeclose->getTimestamp()
1171             ]
1172         );
1174         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1175         $actual = $newevent->get_times()->get_start_time();
1176         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1178         $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1179         $this->assertEquals($expected->getTimestamp(), $feedback->timeclose);
1180     }
1182     /**
1183      * Updating the start day of an event belonging to an activity to a value
1184      * equal to the minimum cutoff should update the corresponding activity
1185      * property.
1186      *
1187      * Note: This test uses the feedback activity because it requires
1188      * module callbacks to be in place to test.
1189      */
1190     public function test_update_event_start_day_activity_event_equal_to_min() {
1191         global $CFG, $DB;
1192         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1194         $this->resetAfterTest(true);
1195         $this->setAdminUser();
1196         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1197         $timeclose = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1198         $newstartdate = new DateTimeImmutable('2017-01-1T10:00:00+08:00');
1199         $expected = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1200         list($feedback, $event) = $this->create_feedback_activity_and_event(
1201             [
1202                 'timeopen' => $timeopen->getTimestamp(),
1203                 'timeclose' => $timeclose->getTimestamp(),
1204             ],
1205             [
1206                 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
1207                 'timestart' => $timeclose->getTimestamp()
1208             ]
1209         );
1211         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1212         $actual = $newevent->get_times()->get_start_time();
1213         $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1215         $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1216         $this->assertEquals($expected->getTimestamp(), $feedback->timeclose);
1217     }
1219     /**
1220      * Updating the start day of an event belonging to an activity to a value
1221      * before the minimum cutoff should not update the corresponding activity
1222      * property. Instead it should throw an exception.
1223      *
1224      * Note: This test uses the feedback activity because it requires
1225      * module callbacks to be in place to test.
1226      */
1227     public function test_update_event_start_day_activity_event_before_min() {
1228         global $CFG, $DB;
1229         require_once($CFG->dirroot . '/mod/feedback/lib.php');
1231         $this->resetAfterTest(true);
1232         $this->setAdminUser();
1233         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1234         $timeclose = new DateTimeImmutable('2017-02-2T15:00:00+08:00');
1235         $newstartdate = new DateTimeImmutable('2016-02-2T10:00:00+08:00');
1236         list($feedback, $event) = $this->create_feedback_activity_and_event(
1237             [
1238                 'timeopen' => $timeopen->getTimestamp(),
1239                 'timeclose' => $timeclose->getTimestamp(),
1240             ],
1241             [
1242                 'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
1243                 'timestart' => $timeclose->getTimestamp()
1244             ]
1245         );
1247         $this->expectException('moodle_exception');
1248         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1249     }
1251     /**
1252      * Updating the start day of an overridden event belonging to an activity
1253      * should result in an exception. This is to prevent the drag and drop
1254      * of override events.
1255      *
1256      * Note: This test uses the quiz activity because it requires
1257      * module callbacks to be in place and override event support to test.
1258      */
1259     public function test_update_event_start_day_activity_event_override() {
1260         global $CFG, $DB;
1261         require_once($CFG->dirroot . '/calendar/lib.php');
1262         require_once($CFG->dirroot . '/mod/quiz/lib.php');
1264         $this->resetAfterTest(true);
1265         $this->setAdminUser();
1266         $mapper = container::get_event_mapper();
1267         $timeopen = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1268         $newstartdate = new DateTimeImmutable('2016-02-2T10:00:00+08:00');
1269         $generator = $this->getDataGenerator();
1270         $user = $generator->create_user();
1271         $course = $generator->create_course();
1272         $quizgenerator = $generator->get_plugin_generator('mod_quiz');
1273         $quiz = $quizgenerator->create_instance([
1274             'course' => $course->id,
1275             'timeopen' => $timeopen->getTimestamp(),
1276         ]);
1277         $event = create_event([
1278             'courseid' => $course->id,
1279             'userid' => $user->id,
1280             'modulename' => 'quiz',
1281             'instance' => $quiz->id,
1282             'eventtype' => QUIZ_EVENT_TYPE_OPEN,
1283             'timestart' => $timeopen->getTimestamp()
1284         ]);
1285         $event = $mapper->from_legacy_event_to_event($event);
1286         $record = (object) [
1287             'quiz' => $quiz->id,
1288             'userid' => $user->id
1289         ];
1291         $DB->insert_record('quiz_overrides', $record);
1293         $this->expectException('moodle_exception');
1294         $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1295     }