2 // This file is part of Moodle - http://moodle.org/
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.
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.
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 namespace core_calendar
;
19 use core_calendar_external
;
20 use externallib_advanced_testcase
;
22 defined('MOODLE_INTERNAL') ||
die();
26 require_once($CFG->dirroot
. '/webservice/tests/helpers.php');
29 * External course functions unit tests
31 * @package core_calendar
33 * @copyright 2012 Ankit Agarwal
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 class externallib_test
extends externallib_advanced_testcase
{
42 protected function setUp(): void
{
44 require_once($CFG->dirroot
. '/calendar/externallib.php');
47 /** Create calendar events or update them
48 * Set $prop->id, if you want to do an update instead of creating an new event
50 * @param string $name Event title
51 * @param int $userid User id
52 * @param string $type Event type
53 * @param int $repeats Number of repeated events to create
54 * @param int $timestart Time stamp of the event start
55 * @param mixed $prop List of event properties as array or object
56 * @return mixed Event object or false;
60 public static function create_calendar_event($name, $userid = 0, $type = 'user', $repeats = 0, $timestart = null, $prop = null) {
61 global $CFG, $DB, $SITE;
63 require_once("$CFG->dirroot/calendar/lib.php");
65 if (is_array($prop)) {
66 $prop = (object)$prop;
69 $prop = new \
stdClass();
72 if (empty($prop->eventtype
)) {
73 $prop->eventtype
= $type;
75 if (empty($prop->repeats
)) {
76 $prop->repeats
= $repeats;
78 if (empty($prop->timestart
)) {
79 $prop->timestart
= time();
81 if (empty($prop->timeduration
)) {
82 $prop->timeduration
= 0;
84 if (empty($prop->timesort
)) {
87 if (empty($prop->type
)) {
88 $prop->type
= CALENDAR_EVENT_TYPE_STANDARD
;
90 if (empty($prop->repeats
)) {
95 if (empty($prop->userid
)) {
96 if (!empty($userid)) {
97 $prop->userid
= $userid;
102 if (!isset($prop->courseid
)) {
103 // Set a default value of the event's course ID field.
104 if ($type === 'user') {
105 // If it's a user event, course ID should be zero.
108 // Otherwise, default to the site ID.
109 $prop->courseid
= $SITE->id
;
113 // Determine event priority.
114 if ($prop->courseid
== 0 && isset($prop->groupid
) && $prop->groupid
== 0 && !empty($prop->userid
)) {
115 // User override event.
116 $prop->priority
= CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
;
117 } else if ($prop->courseid
!= $SITE->id
&& !empty($prop->groupid
)) {
118 // Group override event.
119 $priorityparams = ['courseid' => $prop->courseid
, 'groupid' => $prop->groupid
];
120 // Group override event with the highest priority.
121 $groupevents = $DB->get_records('event', $priorityparams, 'priority DESC', 'id, priority', 0, 1);
123 if (!empty($groupevents)) {
124 $event = reset($groupevents);
125 if (!empty($event->priority
)) {
126 $priority = $event->priority +
1;
129 $prop->priority
= $priority;
132 $event = new \
calendar_event($prop);
133 return $event->create($prop);
136 public function test_create_calendar_events () {
139 $this->setAdminUser();
140 $this->resetAfterTest();
141 $prevcount = count($DB->get_records("event"));
143 // Create a few events and do asserts.
144 $this->create_calendar_event('test', $USER->id
);
145 $where = $DB->sql_compare_text('name') ." = ?";
146 $count = count($DB->get_records_select("event", $where, array('test')));
147 $this->assertEquals(1, $count);
148 $aftercount = count($DB->get_records("event"));
149 $this->assertEquals($prevcount +
1, $aftercount);
151 $this->create_calendar_event('user', $USER->id
, 'user', 3);
152 $where = $DB->sql_compare_text('name') ." = ?";
153 $count = count($DB->get_records_select("event", $where, array('user')));
155 $this->assertEquals(3, $count);
156 $aftercount = count($DB->get_records("event"));
157 $this->assertEquals($prevcount +
4, $aftercount);
162 * Test delete_calendar_events
164 public function test_delete_calendar_events() {
167 $this->resetAfterTest(true);
168 $this->setAdminUser();
170 // Create a few stuff to test with.
171 $user = $this->getDataGenerator()->create_user();
172 $course = $this->getDataGenerator()->create_course();
173 $record = new \
stdClass();
174 $record->courseid
= $course->id
;
175 $group = $this->getDataGenerator()->create_group($record);
177 $notdeletedcount = $DB->count_records('event');
179 // Let's create a few events.
180 $siteevent = $this->create_calendar_event('site', $USER->id
, 'site');
181 $record = new \
stdClass();
182 $record->courseid
= $course->id
;
183 $courseevent = $this->create_calendar_event('course', $USER->id
, 'course', 2, time(), $record);
184 $userevent = $this->create_calendar_event('user', $USER->id
);
185 $record = new \
stdClass();
186 $record->courseid
= $course->id
;
187 $record->groupid
= $group->id
;
188 $groupevent = $this->create_calendar_event('group', $USER->id
, 'group', 0, time(), $record);
190 // Now lets try to delete stuff with proper rights.
192 array('eventid' => $siteevent->id
, 'repeat' => 0),
193 array('eventid' => $courseevent->id
, 'repeat' => 1),
194 array('eventid' => $userevent->id
, 'repeat' => 0),
195 array('eventid' => $groupevent->id
, 'repeat' => 0)
197 core_calendar_external
::delete_calendar_events($events);
199 // Check to see if things were deleted properly.
200 $deletedcount = $DB->count_records('event');
201 $this->assertEquals($notdeletedcount, $deletedcount);
203 // Let's create a few events.
204 $siteevent = $this->create_calendar_event('site', $USER->id
, 'site');
205 $record = new \
stdClass();
206 $record->courseid
= $course->id
;
207 $courseevent = $this->create_calendar_event('course', $USER->id
, 'course', 3, time(), $record);
208 $userevent = $this->create_calendar_event('user', $user->id
);
209 $record = new \
stdClass();
210 $record->courseid
= $course->id
;
211 $record->groupid
= $group->id
;
212 $groupevent = $this->create_calendar_event('group', $USER->id
, 'group', 0, time(), $record);
214 $this->setuser($user);
215 $sitecontext = \context_system
::instance();
216 $coursecontext = \context_course
::instance($course->id
);
217 $usercontext = \context_user
::instance($user->id
);
218 $role = $DB->get_record('role', array('shortname' => 'student'));
219 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
222 $this->unassignUserCapability('moodle/calendar:manageentries', $sitecontext->id
, $role->id
);
223 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id
, $role->id
);
224 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id
, $role->id
);
225 $this->unassignUserCapability('moodle/calendar:manageownentries', $usercontext->id
, $role->id
);
227 // Assign proper caps and attempt delete.
228 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id
, $role->id
);
230 array('eventid' => $siteevent->id
, 'repeat' => 0),
232 core_calendar_external
::delete_calendar_events($events);
233 $deletedcount = $DB->count_records('event');
234 $count = $notdeletedcount+
5;
235 $this->assertEquals($count, $deletedcount);
237 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id
, $role->id
);
239 array('eventid' => $courseevent->id
, 'repeat' => 0),
241 core_calendar_external
::delete_calendar_events($events);
242 $deletedcount = $DB->count_records('event');
243 $count = $notdeletedcount+
4;
244 $this->assertEquals($count, $deletedcount);
246 $this->assignUserCapability('moodle/calendar:manageownentries', $usercontext->id
, $role->id
);
248 array('eventid' => $userevent->id
, 'repeat' => 0),
250 core_calendar_external
::delete_calendar_events($events);
251 $deletedcount = $DB->count_records('event');
252 $count = $notdeletedcount+
3;
253 $this->assertEquals($count, $deletedcount);
255 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id
, $role->id
);
257 array('eventid' => $groupevent->id
, 'repeat' => 0),
259 core_calendar_external
::delete_calendar_events($events);
260 $deletedcount = $DB->count_records('event');
261 $count = $notdeletedcount+
2;
262 $this->assertEquals($count, $deletedcount);
264 $notdeletedcount = $deletedcount;
266 // Let us try deleting without caps.
268 $siteevent = $this->create_calendar_event('site', $USER->id
, 'site');
269 $record = new \
stdClass();
270 $record->courseid
= $course->id
;
271 $courseevent = $this->create_calendar_event('course', $USER->id
, 'course', 3, time(), $record);
272 $userevent = $this->create_calendar_event('user', $USER->id
);
273 $record = new \
stdClass();
274 $record->courseid
= $course->id
;
275 $record->groupid
= $group->id
;
276 $groupevent = $this->create_calendar_event('group', $USER->id
, 'group', 0, time(), $record);
278 $this->setGuestUser();
281 array('eventid' => $siteevent->id
, 'repeat' => 0),
282 array('eventid' => $courseevent->id
, 'repeat' => 0),
283 array('eventid' => $userevent->id
, 'repeat' => 0),
284 array('eventid' => $groupevent->id
, 'repeat' => 0)
286 $this->expectException(\moodle_exception
::class);
287 core_calendar_external
::delete_calendar_events($events);
291 * Test get_calendar_events
293 public function test_get_calendar_events() {
296 $this->resetAfterTest(true);
297 set_config('calendar_adminseesall', 1);
298 $this->setAdminUser();
300 // Create a few stuff to test with.
301 $user = $this->getDataGenerator()->create_user();
302 $user2 = $this->getDataGenerator()->create_user();
303 $course = $this->getDataGenerator()->create_course();
305 $category = $this->getDataGenerator()->create_category();
307 $category2 = $this->getDataGenerator()->create_category();
308 $category2b = $this->getDataGenerator()->create_category(['parent' => $category2->id
]);
309 $course3 = $this->getDataGenerator()->create_course(['category' => $category2b->id
]);
311 $role = $DB->get_record('role', array('shortname' => 'student'));
312 $this->getDataGenerator()->enrol_user($user2->id
, $course3->id
, $role->id
);
314 $record = new \
stdClass();
315 $record->courseid
= $course->id
;
316 $group = $this->getDataGenerator()->create_group($record);
318 $beforecount = $DB->count_records('event');
320 // Let's create a few events.
321 $siteevent = $this->create_calendar_event('site', $USER->id
, 'site');
323 // This event will have description with an inline fake image.
324 $draftidfile = file_get_unused_draft_itemid();
325 $usercontext = \context_course
::instance($course->id
);
327 'contextid' => $usercontext->id
,
328 'component' => 'user',
329 'filearea' => 'draft',
330 'itemid' => $draftidfile,
332 'filename' => 'fakeimage.png',
334 $fs = get_file_storage();
335 $fs->create_file_from_string($filerecord, 'img contents');
337 $record = new \
stdClass();
338 $record->courseid
= $course->id
;
339 $record->groupid
= 0;
340 $record->description
= array(
341 'format' => FORMAT_HTML
,
342 'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">',
343 'itemid' => $draftidfile
345 $courseevent = $this->create_calendar_event('course', $USER->id
, 'course', 2, time(), $record);
347 $record = new \
stdClass();
348 $record->courseid
= 0;
349 $record->groupid
= 0;
350 $userevent = $this->create_calendar_event('user', $USER->id
, 'user', 0, time(), $record);
352 $record = new \
stdClass();
353 $record->courseid
= $course->id
;
354 $record->groupid
= $group->id
;
355 $groupevent = $this->create_calendar_event('group', $USER->id
, 'group', 0, time(), $record);
357 $paramevents = array ('eventids' => array($siteevent->id
), 'courseids' => array($course->id
),
358 'groupids' => array($group->id
), 'categoryids' => array($category->id
));
360 $options = array ('siteevents' => true, 'userevents' => true);
361 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
362 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
364 // Check to see if we got all events.
365 $this->assertEquals(5, count($events['events']));
366 $this->assertEquals(0, count($events['warnings']));
367 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() +
7*WEEKSECS
);
368 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
369 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
370 $this->assertEquals(5, count($events['events']));
371 $this->assertEquals(0, count($events['warnings']));
373 // Expect the same URL in the description of two different events (because they are repeated).
374 $coursecontext = \context_course
::instance($course->id
);
375 $expectedurl = "webservice/pluginfile.php/$coursecontext->id/calendar/event_description/$courseevent->id/fakeimage.png";
376 $withdescription = 0;
377 foreach ($events['events'] as $event) {
378 if (!empty($event['description'])) {
380 $this->assertStringContainsString($expectedurl, $event['description']);
383 $this->assertEquals(2, $withdescription);
385 // Let's play around with caps.
387 // Create user event for the user $user.
388 $record = new \
stdClass();
389 $record->courseid
= 0;
390 $record->groupid
= 0;
391 $this->create_calendar_event('user', $user->id
, 'user', 0, time(), $record);
393 $this->setUser($user);
394 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
395 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
396 $this->assertEquals(2, count($events['events'])); // site, user.
397 $this->assertEquals(2, count($events['warnings'])); // course, group.
399 $role = $DB->get_record('role', array('shortname' => 'student'));
400 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
401 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
402 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
403 $this->assertEquals(4, count($events['events'])); // site, user, both course events.
404 $this->assertEquals(1, count($events['warnings'])); // group.
406 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS
);
407 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
408 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
409 $this->assertEquals(3, count($events['events'])); // site, user, one course event.
410 $this->assertEquals(1, count($events['warnings'])); // group.
412 groups_add_member($group, $user);
413 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
414 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
415 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
416 $this->assertEquals(0, count($events['warnings']));
418 $paramevents = array ('courseids' => array($course->id
), 'groupids' => array($group->id
));
419 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
420 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
421 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
422 $this->assertEquals(0, count($events['warnings']));
424 $paramevents = array ('groupids' => array($group->id
, 23));
425 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
426 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
427 $this->assertEquals(3, count($events['events'])); // site, user, group.
428 $this->assertEquals(1, count($events['warnings']));
430 $paramevents = array ('courseids' => array(23));
431 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
432 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
433 $this->assertEquals(2, count($events['events'])); // site, user.
434 $this->assertEquals(1, count($events['warnings']));
436 $paramevents = array ();
437 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() +
7*WEEKSECS
);
438 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
439 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
440 $this->assertEquals(0, count($events['events'])); // nothing returned.
441 $this->assertEquals(0, count($events['warnings']));
443 $paramevents = array ('eventids' => array($siteevent->id
, $groupevent->id
));
444 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() +
7*WEEKSECS
);
445 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
446 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
447 $this->assertEquals(2, count($events['events'])); // site, group.
448 $this->assertEquals(0, count($events['warnings']));
450 $paramevents = array ('eventids' => array($siteevent->id
));
451 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
452 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
453 $this->assertEquals(1, count($events['events'])); // site.
454 $this->assertEquals(0, count($events['warnings']));
456 // Try getting a course event by its id.
457 $paramevents = array ('eventids' => array($courseevent->id
));
458 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
459 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
460 $this->assertEquals(1, count($events['events']));
461 $this->assertEquals(0, count($events['warnings']));
463 // Now, create an activity event.
464 $this->setAdminUser();
465 $nexttime = time() + DAYSECS
;
466 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id
, 'duedate' => $nexttime));
468 $this->setUser($user);
469 $paramevents = array ('courseids' => array($course->id
));
470 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS
);
471 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
472 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
474 $this->assertCount(5, $events['events']);
476 // Hide the assignment.
477 set_coursemodule_visible($assign->cmid
, 0);
478 // Empty all the caches that may be affected by this change.
479 accesslib_clear_all_caches_for_unit_testing();
480 \course_modinfo
::clear_instance_cache();
482 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
483 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
485 $this->assertCount(4, $events['events']);
487 // Create some category events.
488 $this->setAdminUser();
489 $record = new \
stdClass();
490 $record->courseid
= 0;
491 $record->categoryid
= $category->id
;
492 $record->timestart
= time() - DAYSECS
;
493 $catevent1 = $this->create_calendar_event('category a', $USER->id
, 'category', 0, time(), $record);
495 $record = new \
stdClass();
496 $record->courseid
= 0;
497 $record->categoryid
= $category2->id
;
498 $record->timestart
= time() + DAYSECS
;
499 $catevent2 = $this->create_calendar_event('category b', $USER->id
, 'category', 0, time(), $record);
501 // Now as student, make sure we get the events of the courses I am enrolled.
502 $this->setUser($user2);
503 $paramevents = array('categoryids' => array($category2b->id
));
504 $options = array('timeend' => time() +
7 * WEEKSECS
, 'userevents' => false, 'siteevents' => false);
505 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
506 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
508 // Should be just one, since there's just one category event of the course I am enrolled (course3 - cat2b).
509 $this->assertEquals(1, count($events['events']));
510 $this->assertEquals($catevent2->id
, $events['events'][0]['id']);
511 $this->assertEquals($category2->id
, $events['events'][0]['categoryid']);
512 $this->assertEquals(0, count($events['warnings']));
514 // Now get category events but by course (there aren't course events in the course).
515 $paramevents = array('courseids' => array($course3->id
));
516 $options = array('timeend' => time() +
7 * WEEKSECS
, 'userevents' => false, 'siteevents' => false);
517 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
518 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
519 $this->assertEquals(1, count($events['events']));
520 $this->assertEquals($catevent2->id
, $events['events'][0]['id']);
521 $this->assertEquals(0, count($events['warnings']));
523 // Empty events in one where I'm not enrolled and one parent category
524 // (parent of a category where this is a course where the user is enrolled).
525 $paramevents = array('categoryids' => array($category2->id
, $category->id
));
526 $options = array('timeend' => time() +
7 * WEEKSECS
, 'userevents' => false, 'siteevents' => false);
527 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
528 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
529 $this->assertEquals(1, count($events['events']));
530 $this->assertEquals($catevent2->id
, $events['events'][0]['id']);
531 $this->assertEquals(0, count($events['warnings']));
533 // Admin can see all category events.
534 $this->setAdminUser();
535 $paramevents = array('categoryids' => array($category->id
, $category2->id
, $category2b->id
));
536 $options = array('timeend' => time() +
7 * WEEKSECS
, 'userevents' => false, 'siteevents' => false);
537 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
538 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
539 $this->assertEquals(2, count($events['events']));
540 $this->assertEquals(0, count($events['warnings']));
541 $this->assertEquals($catevent1->id
, $events['events'][0]['id']);
542 $this->assertEquals($category->id
, $events['events'][0]['categoryid']);
543 $this->assertEquals($catevent2->id
, $events['events'][1]['id']);
544 $this->assertEquals($category2->id
, $events['events'][1]['categoryid']);
548 * Test get_calendar_events with mathjax in the name.
550 public function test_get_calendar_events_with_mathjax() {
553 $this->resetAfterTest(true);
554 set_config('calendar_adminseesall', 1);
555 $this->setAdminUser();
557 // Enable MathJax filter in content and headings.
558 $this->configure_filters([
559 ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON
, 'move' => -1, 'applytostrings' => true],
562 // Create a site event with mathjax in the name and description.
563 $siteevent = $this->create_calendar_event('Site Event $$(a+b)=2$$', $USER->id
, 'site', 0, time(),
564 ['description' => 'Site Event Description $$(a+b)=2$$']);
566 // Now call the WebService.
567 $events = core_calendar_external
::get_calendar_events();
568 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
570 // Format the original data.
571 $sitecontext = \context_system
::instance();
572 $siteevent->name
= $siteevent->format_external_name();
573 list($siteevent->description
, $siteevent->descriptionformat
) = $siteevent->format_external_text();
575 // Check that the event data is formatted.
576 $this->assertCount(1, $events['events']);
577 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $events['events'][0]['name']);
578 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $events['events'][0]['description']);
579 $this->assertEquals($siteevent->name
, $events['events'][0]['name']);
580 $this->assertEquals($siteevent->description
, $events['events'][0]['description']);
584 * Test core_calendar_external::create_calendar_events
586 public function test_core_create_calendar_events() {
587 global $DB, $USER, $SITE;
589 $this->resetAfterTest(true);
590 $this->setAdminUser();
592 // Create a few stuff to test with.
593 $user = $this->getDataGenerator()->create_user();
594 $course = $this->getDataGenerator()->create_course();
595 $record = new \
stdClass();
596 $record->courseid
= $course->id
;
597 $group = $this->getDataGenerator()->create_group($record);
599 $prevcount = $DB->count_records('event');
601 // Let's create a few events.
603 array('name' => 'site', 'courseid' => $SITE->id
, 'eventtype' => 'site'),
604 array('name' => 'course', 'courseid' => $course->id
, 'eventtype' => 'course', 'repeats' => 2),
605 array('name' => 'group', 'courseid' => $course->id
, 'groupid' => $group->id
, 'eventtype' => 'group'),
606 array('name' => 'user')
608 $eventsret = core_calendar_external
::create_calendar_events($events);
609 $eventsret = \external_api
::clean_returnvalue(core_calendar_external
::create_calendar_events_returns(), $eventsret);
611 // Check to see if things were created properly.
612 $aftercount = $DB->count_records('event');
613 $this->assertEquals($prevcount +
5, $aftercount);
614 $this->assertEquals(5, count($eventsret['events']));
615 $this->assertEquals(0, count($eventsret['warnings']));
617 $sitecontext = \context_system
::instance();
618 $coursecontext = \context_course
::instance($course->id
);
620 $this->setUser($user);
621 $prevcount = $aftercount;
623 array('name' => 'course', 'courseid' => $course->id
, 'eventtype' => 'course', 'repeats' => 2),
624 array('name' => 'group', 'courseid' => $course->id
, 'groupid' => $group->id
, 'eventtype' => 'group'),
625 array('name' => 'user')
627 $role = $DB->get_record('role', array('shortname' => 'student'));
628 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
629 groups_add_member($group, $user);
630 $this->assignUserCapability('moodle/calendar:manageentries', $coursecontext->id
, $role->id
);
631 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id
, $role->id
);
632 $eventsret = core_calendar_external
::create_calendar_events($events);
633 $eventsret = \external_api
::clean_returnvalue(core_calendar_external
::create_calendar_events_returns(), $eventsret);
634 // Check to see if things were created properly.
635 $aftercount = $DB->count_records('event');
636 $this->assertEquals($prevcount +
4, $aftercount);
637 $this->assertEquals(4, count($eventsret['events']));
638 $this->assertEquals(0, count($eventsret['warnings']));
640 // Check to see nothing was created without proper permission.
641 $this->setGuestUser();
642 $prevcount = $DB->count_records('event');
643 $eventsret = core_calendar_external
::create_calendar_events($events);
644 $eventsret = \external_api
::clean_returnvalue(core_calendar_external
::create_calendar_events_returns(), $eventsret);
645 $aftercount = $DB->count_records('event');
646 $this->assertEquals($prevcount, $aftercount);
647 $this->assertEquals(0, count($eventsret['events']));
648 $this->assertEquals(3, count($eventsret['warnings']));
650 $this->setUser($user);
651 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id
, $role->id
);
652 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id
, $role->id
);
653 $prevcount = $DB->count_records('event');
654 $eventsret = core_calendar_external
::create_calendar_events($events);
655 $eventsret = \external_api
::clean_returnvalue(core_calendar_external
::create_calendar_events_returns(), $eventsret);
656 $aftercount = $DB->count_records('event');
657 $this->assertEquals($prevcount +
1, $aftercount); // User event.
658 $this->assertEquals(1, count($eventsret['events']));
659 $this->assertEquals(2, count($eventsret['warnings']));
663 * Requesting calendar events from a given time should return all events with a sort
664 * time at or after the requested time. All events prior to that time should not
667 * If there are no events on or after the given time then an empty result set should
670 public function test_get_calendar_action_events_by_timesort_after_time() {
671 $user = $this->getDataGenerator()->create_user();
672 $course = $this->getDataGenerator()->create_course();
673 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
674 $moduleinstance = $generator->create_instance(['course' => $course->id
]);
676 $this->getDataGenerator()->enrol_user($user->id
, $course->id
);
677 $this->resetAfterTest(true);
678 $this->setUser($user);
681 'type' => CALENDAR_EVENT_TYPE_ACTION
,
682 'modulename' => 'assign',
683 'instance' => $moduleinstance->id
,
684 'courseid' => $course->id
,
687 $event1 = $this->create_calendar_event('Event 1', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
688 $event2 = $this->create_calendar_event('Event 2', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
689 $event3 = $this->create_calendar_event('Event 3', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
690 $event4 = $this->create_calendar_event('Event 4', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
691 $event5 = $this->create_calendar_event('Event 5', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
692 $event6 = $this->create_calendar_event('Event 6', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
693 $event7 = $this->create_calendar_event('Event 7', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
694 $event8 = $this->create_calendar_event('Event 8', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
696 $result = core_calendar_external
::get_calendar_action_events_by_timesort(5);
697 $result = \external_api
::clean_returnvalue(
698 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
701 $events = $result['events'];
703 $this->assertCount(4, $events);
704 $this->assertEquals('Event 5', $events[0]['name']);
705 $this->assertEquals('Event 6', $events[1]['name']);
706 $this->assertEquals('Event 7', $events[2]['name']);
707 $this->assertEquals('Event 8', $events[3]['name']);
708 $this->assertEquals($event5->id
, $result['firstid']);
709 $this->assertEquals($event8->id
, $result['lastid']);
711 $result = core_calendar_external
::get_calendar_action_events_by_timesort(9);
712 $result = \external_api
::clean_returnvalue(
713 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
717 $this->assertEmpty($result['events']);
718 $this->assertNull($result['firstid']);
719 $this->assertNull($result['lastid']);
721 // Requesting action events on behalf of another user.
722 $this->setAdminUser();
723 $result = core_calendar_external
::get_calendar_action_events_by_timesort(5, null, 0, 20, false, $user->id
);
724 $result = \external_api
::clean_returnvalue(
725 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
728 $events = $result['events'];
730 $this->assertCount(4, $events);
731 $this->assertEquals('Event 5', $events[0]['name']);
732 $this->assertEquals('Event 6', $events[1]['name']);
733 $this->assertEquals('Event 7', $events[2]['name']);
734 $this->assertEquals('Event 8', $events[3]['name']);
735 $this->assertEquals($event5->id
, $result['firstid']);
736 $this->assertEquals($event8->id
, $result['lastid']);
740 * Requesting calendar events before a given time should return all events with a sort
741 * time at or before the requested time (inclusive). All events after that time
742 * should not be returned.
744 * If there are no events before the given time then an empty result set should be
747 public function test_get_calendar_action_events_by_timesort_before_time() {
748 $user = $this->getDataGenerator()->create_user();
749 $course = $this->getDataGenerator()->create_course();
750 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
751 $moduleinstance = $generator->create_instance(['course' => $course->id
]);
753 $this->getDataGenerator()->enrol_user($user->id
, $course->id
);
754 $this->resetAfterTest(true);
755 $this->setUser($user);
758 'type' => CALENDAR_EVENT_TYPE_ACTION
,
759 'modulename' => 'assign',
760 'instance' => $moduleinstance->id
,
761 'courseid' => $course->id
,
764 $event1 = $this->create_calendar_event('Event 1', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
765 $event2 = $this->create_calendar_event('Event 2', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
766 $event3 = $this->create_calendar_event('Event 3', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
767 $event4 = $this->create_calendar_event('Event 4', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
768 $event5 = $this->create_calendar_event('Event 5', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
769 $event6 = $this->create_calendar_event('Event 6', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
770 $event7 = $this->create_calendar_event('Event 7', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
771 $event8 = $this->create_calendar_event('Event 8', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 9]));
773 $result = core_calendar_external
::get_calendar_action_events_by_timesort(null, 5);
774 $result = \external_api
::clean_returnvalue(
775 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
778 $events = $result['events'];
780 $this->assertCount(4, $events);
781 $this->assertEquals('Event 1', $events[0]['name']);
782 $this->assertEquals('Event 2', $events[1]['name']);
783 $this->assertEquals('Event 3', $events[2]['name']);
784 $this->assertEquals('Event 4', $events[3]['name']);
785 $this->assertEquals($event1->id
, $result['firstid']);
786 $this->assertEquals($event4->id
, $result['lastid']);
788 $result = core_calendar_external
::get_calendar_action_events_by_timesort(null, 1);
789 $result = \external_api
::clean_returnvalue(
790 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
794 $this->assertEmpty($result['events']);
795 $this->assertNull($result['firstid']);
796 $this->assertNull($result['lastid']);
798 // Requesting action events on behalf of another user.
799 $this->setAdminUser();
801 $result = core_calendar_external
::get_calendar_action_events_by_timesort(null, 5, 0, 20, false, $user->id
);
802 $result = \external_api
::clean_returnvalue(
803 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
806 $events = $result['events'];
808 $this->assertCount(4, $events);
809 $this->assertEquals('Event 1', $events[0]['name']);
810 $this->assertEquals('Event 2', $events[1]['name']);
811 $this->assertEquals('Event 3', $events[2]['name']);
812 $this->assertEquals('Event 4', $events[3]['name']);
813 $this->assertEquals($event1->id
, $result['firstid']);
814 $this->assertEquals($event4->id
, $result['lastid']);
818 * Test retrieving event that was overridden for a user
820 public function test_get_calendar_events_override() {
821 $user = $this->getDataGenerator()->create_user();
822 $user2 = $this->getDataGenerator()->create_user();
823 $teacher = $this->getDataGenerator()->create_user();
824 $anotheruser = $this->getDataGenerator()->create_user();
825 $course = $this->getDataGenerator()->create_course();
826 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
827 $moduleinstance = $generator->create_instance(['course' => $course->id
]);
829 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, 'student');
830 $this->getDataGenerator()->enrol_user($user2->id
, $course->id
, 'student');
831 $this->getDataGenerator()->enrol_user($teacher->id
, $course->id
, 'editingteacher');
832 $this->resetAfterTest(true);
833 $this->setAdminUser();
836 'type' => CALENDAR_EVENT_TYPE_ACTION
,
837 'modulename' => 'assign',
838 'instance' => $moduleinstance->id
,
842 // Create two events - one for everybody in the course and one only for the first student.
843 $event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS
, $params +
['courseid' => $course->id
]);
844 $event2 = $this->create_calendar_event('User event', $user->id
, 'due', 0, $now +
2*DAYSECS
, $params +
['courseid' => 0]);
846 // Retrieve course events for the second student - only one "Base event" is returned.
847 $this->setUser($user2);
848 $paramevents = array('courseids' => array($course->id
));
849 $options = array ('siteevents' => true, 'userevents' => true);
850 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
851 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
852 $this->assertEquals(1, count($events['events']));
853 $this->assertEquals(0, count($events['warnings']));
854 $this->assertEquals('Base event', $events['events'][0]['name']);
856 // Retrieve events for the first student - both events are returned.
857 $this->setUser($user);
858 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
859 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
860 $this->assertEquals(2, count($events['events']));
861 $this->assertEquals(0, count($events['warnings']));
862 $this->assertEquals('Base event', $events['events'][0]['name']);
863 $this->assertEquals('User event', $events['events'][1]['name']);
865 // Retrieve events by id as a teacher, 'User event' should be returned since teacher has access to this course.
866 $this->setUser($teacher);
867 $paramevents = ['eventids' => [$event2->id
]];
868 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
869 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
870 $this->assertEquals(1, count($events['events']));
871 $this->assertEquals(0, count($events['warnings']));
872 $this->assertEquals('User event', $events['events'][0]['name']);
874 // Retrieve events by id as another user, nothing should be returned.
875 $this->setUser($anotheruser);
876 $paramevents = ['eventids' => [$event2->id
, $event1->id
]];
877 $events = core_calendar_external
::get_calendar_events($paramevents, $options);
878 $events = \external_api
::clean_returnvalue(core_calendar_external
::get_calendar_events_returns(), $events);
879 $this->assertEquals(0, count($events['events']));
880 $this->assertEquals(0, count($events['warnings']));
884 * Requesting calendar events within a given time range should return all events with
885 * a sort time between the lower and upper time bound (inclusive).
887 * If there are no events in the given time range then an empty result set should be
890 public function test_get_calendar_action_events_by_timesort_time_range() {
891 $user = $this->getDataGenerator()->create_user();
892 $course = $this->getDataGenerator()->create_course();
893 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
894 $moduleinstance = $generator->create_instance(['course' => $course->id
]);
896 $this->getDataGenerator()->enrol_user($user->id
, $course->id
);
897 $this->resetAfterTest(true);
898 $this->setUser($user);
901 'type' => CALENDAR_EVENT_TYPE_ACTION
,
902 'modulename' => 'assign',
903 'instance' => $moduleinstance->id
,
904 'courseid' => $course->id
,
907 $event1 = $this->create_calendar_event('Event 1', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
908 $event2 = $this->create_calendar_event('Event 2', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
909 $event3 = $this->create_calendar_event('Event 3', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
910 $event4 = $this->create_calendar_event('Event 4', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
911 $event5 = $this->create_calendar_event('Event 5', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
912 $event6 = $this->create_calendar_event('Event 6', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
913 $event7 = $this->create_calendar_event('Event 7', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
914 $event8 = $this->create_calendar_event('Event 8', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
916 $result = core_calendar_external
::get_calendar_action_events_by_timesort(3, 6);
917 $result = \external_api
::clean_returnvalue(
918 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
921 $events = $result['events'];
923 $this->assertCount(4, $events);
924 $this->assertEquals('Event 3', $events[0]['name']);
925 $this->assertEquals('Event 4', $events[1]['name']);
926 $this->assertEquals('Event 5', $events[2]['name']);
927 $this->assertEquals('Event 6', $events[3]['name']);
928 $this->assertEquals($event3->id
, $result['firstid']);
929 $this->assertEquals($event6->id
, $result['lastid']);
931 $result = core_calendar_external
::get_calendar_action_events_by_timesort(10, 15);
932 $result = \external_api
::clean_returnvalue(
933 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
937 $this->assertEmpty($result['events']);
938 $this->assertNull($result['firstid']);
939 $this->assertNull($result['lastid']);
943 * Requesting calendar events within a given time range and a limit and offset should return
944 * the number of events up to the given limit value that have a sort time between the lower
945 * and uppper time bound (inclusive) where the result set is shifted by the offset value.
947 * If there are no events in the given time range then an empty result set should be
950 public function test_get_calendar_action_events_by_timesort_time_limit_offset() {
951 $user = $this->getDataGenerator()->create_user();
952 $course = $this->getDataGenerator()->create_course();
953 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
954 $moduleinstance = $generator->create_instance(['course' => $course->id
]);
956 $this->getDataGenerator()->enrol_user($user->id
, $course->id
);
957 $this->resetAfterTest(true);
958 $this->setUser($user);
961 'type' => CALENDAR_EVENT_TYPE_ACTION
,
962 'modulename' => 'assign',
963 'instance' => $moduleinstance->id
,
964 'courseid' => $course->id
,
967 $event1 = $this->create_calendar_event('Event 1', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
968 $event2 = $this->create_calendar_event('Event 2', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
969 $event3 = $this->create_calendar_event('Event 3', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
970 $event4 = $this->create_calendar_event('Event 4', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
971 $event5 = $this->create_calendar_event('Event 5', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
972 $event6 = $this->create_calendar_event('Event 6', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
973 $event7 = $this->create_calendar_event('Event 7', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
974 $event8 = $this->create_calendar_event('Event 8', $user->id
, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
976 $result = core_calendar_external
::get_calendar_action_events_by_timesort(2, 7, $event3->id
, 2);
977 $result = \external_api
::clean_returnvalue(
978 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
981 $events = $result['events'];
983 $this->assertCount(2, $events);
984 $this->assertEquals('Event 4', $events[0]['name']);
985 $this->assertEquals('Event 5', $events[1]['name']);
986 $this->assertEquals($event4->id
, $result['firstid']);
987 $this->assertEquals($event5->id
, $result['lastid']);
989 $result = core_calendar_external
::get_calendar_action_events_by_timesort(2, 7, $event5->id
, 2);
990 $result = \external_api
::clean_returnvalue(
991 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
994 $events = $result['events'];
996 $this->assertCount(2, $events);
997 $this->assertEquals('Event 6', $events[0]['name']);
998 $this->assertEquals('Event 7', $events[1]['name']);
999 $this->assertEquals($event6->id
, $result['firstid']);
1000 $this->assertEquals($event7->id
, $result['lastid']);
1002 $result = core_calendar_external
::get_calendar_action_events_by_timesort(2, 7, $event7->id
, 2);
1003 $result = \external_api
::clean_returnvalue(
1004 core_calendar_external
::get_calendar_action_events_by_timesort_returns(),
1008 $this->assertEmpty($result['events']);
1009 $this->assertNull($result['firstid']);
1010 $this->assertNull($result['lastid']);
1014 * Check that it is possible to restrict the calendar events to events where the user is not suspended in the course.
1016 public function test_get_calendar_action_events_by_timesort_suspended_course() {
1017 $this->resetAfterTest();
1018 $user1 = $this->getDataGenerator()->create_user();
1019 $user2 = $this->getDataGenerator()->create_user();
1020 $course = $this->getDataGenerator()->create_course();
1021 $this->setAdminUser();
1022 $lesson = $this->getDataGenerator()->create_module('lesson', [
1023 'name' => 'Lesson 1',
1024 'course' => $course->id
,
1025 'available' => time(),
1026 'deadline' => (time() +
(60 * 60 * 24 * 5))
1029 $this->getDataGenerator()->enrol_user($user1->id
, $course->id
, null, 'manual', 0, 0, ENROL_USER_SUSPENDED
);
1030 $this->getDataGenerator()->enrol_user($user2->id
, $course->id
);
1032 $this->setUser($user1);
1033 $result = core_calendar_external
::get_calendar_action_events_by_timesort(0, null, 0, 20, true);
1034 $this->assertEmpty($result->events
);
1035 $this->setUser($user2);
1036 $result = core_calendar_external
::get_calendar_action_events_by_timesort(0, null, 0, 20, true);
1037 $this->assertCount(1, $result->events
);
1038 $this->assertEquals('Lesson 1 closes', $result->events
[0]->name
);
1042 * Check that it is possible to get other user's events without the permission.
1044 public function test_get_calendar_action_events_by_timesort_for_other_users() {
1045 $this->resetAfterTest();
1046 // Create test users.
1047 $user1 = $this->getDataGenerator()->create_user(['email' => 'student1@localhost.com']);
1048 $user2 = $this->getDataGenerator()->create_user(['email' => 'student2@localhost.com']);
1049 // Create test course.
1050 $course = $this->getDataGenerator()->create_course();
1051 $this->setAdminUser();
1052 // Create test activity and make it available only for student2.
1053 $lesson = $this->getDataGenerator()->create_module('lesson', [
1054 'name' => 'Lesson 1',
1055 'course' => $course->id
,
1056 'available' => time(),
1057 'deadline' => (time() +
(60 * 60 * 24 * 5)),
1058 'availability' => '{"op":"&","c":[{"type":"profile","sf":"email","op":"isequalto","v":"student2@localhost.com"}],"showc":[true]}'
1062 $this->getDataGenerator()->enrol_user($user1->id
, $course->id
);
1063 $this->getDataGenerator()->enrol_user($user2->id
, $course->id
);
1065 // Student2 can see the event.
1066 $this->setUser($user2);
1067 $result = core_calendar_external
::get_calendar_action_events_by_timesort(0, null, 0, 20, true);
1068 $this->assertCount(1, $result->events
);
1069 $this->assertEquals('Lesson 1 closes', $result->events
[0]->name
);
1071 // Student1 cannot see the event.
1072 $this->setUser($user1);
1073 $result = core_calendar_external
::get_calendar_action_events_by_timesort(0, null, 0, 20, true);
1074 $this->assertEmpty($result->events
);
1076 // Admin, Manager, Teacher can view student2's data.
1077 $this->setAdminUser();
1078 $result = core_calendar_external
::get_calendar_action_events_by_timesort(0, null, 0, 20, true, $user2->id
);
1079 $this->assertCount(1, $result->events
);
1080 $this->assertEquals('Lesson 1 closes', $result->events
[0]->name
);
1082 // Student1 will see an exception if he/she trying to view student2's data.
1083 $this->setUser($user1);
1084 $this->expectException(\required_capability_exception
::class);
1085 $this->expectExceptionMessage('error/nopermission');
1086 $result = core_calendar_external
::get_calendar_action_events_by_timesort(0, null, 0, 20, true, $user2->id
);
1090 * Requesting calendar events from a given course and time should return all
1091 * events with a sort time at or after the requested time. All events prior
1092 * to that time should not be return.
1094 * If there are no events on or after the given time then an empty result set should
1097 public function test_get_calendar_action_events_by_course_after_time() {
1098 $user = $this->getDataGenerator()->create_user();
1099 $course1 = $this->getDataGenerator()->create_course();
1100 $course2 = $this->getDataGenerator()->create_course();
1101 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1102 $instance1 = $generator->create_instance(['course' => $course1->id
]);
1103 $instance2 = $generator->create_instance(['course' => $course2->id
]);
1106 $this->getDataGenerator()->enrol_user($user->id
, $course1->id
);
1107 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
);
1108 $this->resetAfterTest(true);
1109 $this->setUser($user);
1111 for ($i = 1; $i < 19; $i++
) {
1112 $courseid = ($i < 9) ?
$course1->id
: $course2->id
;
1113 $instance = ($i < 9) ?
$instance1->id
: $instance2->id
;
1114 $records[] = $this->create_calendar_event(
1115 sprintf('Event %d', $i),
1121 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1122 'courseid' => $courseid,
1124 'modulename' => 'assign',
1125 'instance' => $instance,
1130 $result = core_calendar_external
::get_calendar_action_events_by_course($course1->id
, 5);
1131 $result = \external_api
::clean_returnvalue(
1132 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1135 $result = $result['events'];
1137 $this->assertCount(4, $result);
1138 $this->assertEquals('Event 5', $result[0]['name']);
1139 $this->assertEquals('Event 6', $result[1]['name']);
1140 $this->assertEquals('Event 7', $result[2]['name']);
1141 $this->assertEquals('Event 8', $result[3]['name']);
1143 $result = core_calendar_external
::get_calendar_action_events_by_course($course1->id
, 9);
1144 $result = \external_api
::clean_returnvalue(
1145 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1148 $result = $result['events'];
1150 $this->assertEmpty($result);
1154 * Requesting calendar events for a course and before a given time should return
1155 * all events with a sort time at or before the requested time (inclusive). All
1156 * events after that time should not be returned.
1158 * If there are no events before the given time then an empty result set should be
1161 public function test_get_calendar_action_events_by_course_before_time() {
1162 $user = $this->getDataGenerator()->create_user();
1163 $course1 = $this->getDataGenerator()->create_course();
1164 $course2 = $this->getDataGenerator()->create_course();
1165 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1166 $instance1 = $generator->create_instance(['course' => $course1->id
]);
1167 $instance2 = $generator->create_instance(['course' => $course2->id
]);
1170 $this->getDataGenerator()->enrol_user($user->id
, $course1->id
);
1171 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
);
1172 $this->resetAfterTest(true);
1173 $this->setUser($user);
1175 for ($i = 1; $i < 19; $i++
) {
1176 $courseid = ($i < 9) ?
$course1->id
: $course2->id
;
1177 $instance = ($i < 9) ?
$instance1->id
: $instance2->id
;
1178 $records[] = $this->create_calendar_event(
1179 sprintf('Event %d', $i),
1185 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1186 'courseid' => $courseid,
1187 'timesort' => $i +
1,
1188 'modulename' => 'assign',
1189 'instance' => $instance,
1194 $result = core_calendar_external
::get_calendar_action_events_by_course($course1->id
, null, 5);
1195 $result = \external_api
::clean_returnvalue(
1196 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1199 $result = $result['events'];
1201 $this->assertCount(4, $result);
1202 $this->assertEquals('Event 1', $result[0]['name']);
1203 $this->assertEquals('Event 2', $result[1]['name']);
1204 $this->assertEquals('Event 3', $result[2]['name']);
1205 $this->assertEquals('Event 4', $result[3]['name']);
1207 $result = core_calendar_external
::get_calendar_action_events_by_course($course1->id
, null, 1);
1208 $result = \external_api
::clean_returnvalue(
1209 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1212 $result = $result['events'];
1214 $this->assertEmpty($result);
1218 * Requesting calendar events for a course and within a given time range should
1219 * return all events with a sort time between the lower and upper time bound
1222 * If there are no events in the given time range then an empty result set should be
1225 public function test_get_calendar_action_events_by_course_time_range() {
1226 $user = $this->getDataGenerator()->create_user();
1227 $course1 = $this->getDataGenerator()->create_course();
1228 $course2 = $this->getDataGenerator()->create_course();
1229 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1230 $instance1 = $generator->create_instance(['course' => $course1->id
]);
1231 $instance2 = $generator->create_instance(['course' => $course2->id
]);
1234 $this->getDataGenerator()->enrol_user($user->id
, $course1->id
);
1235 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
);
1236 $this->resetAfterTest(true);
1237 $this->setUser($user);
1239 for ($i = 1; $i < 19; $i++
) {
1240 $courseid = ($i < 9) ?
$course1->id
: $course2->id
;
1241 $instance = ($i < 9) ?
$instance1->id
: $instance2->id
;
1242 $records[] = $this->create_calendar_event(
1243 sprintf('Event %d', $i),
1249 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1250 'courseid' => $courseid,
1252 'modulename' => 'assign',
1253 'instance' => $instance,
1258 $result = core_calendar_external
::get_calendar_action_events_by_course($course1->id
, 3, 6);
1259 $result = \external_api
::clean_returnvalue(
1260 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1263 $result = $result['events'];
1265 $this->assertCount(4, $result);
1266 $this->assertEquals('Event 3', $result[0]['name']);
1267 $this->assertEquals('Event 4', $result[1]['name']);
1268 $this->assertEquals('Event 5', $result[2]['name']);
1269 $this->assertEquals('Event 6', $result[3]['name']);
1271 $result = core_calendar_external
::get_calendar_action_events_by_course($course1->id
, 10, 15);
1272 $result = \external_api
::clean_returnvalue(
1273 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1276 $result = $result['events'];
1278 $this->assertEmpty($result);
1282 * Requesting calendar events for a course and within a given time range and a limit
1283 * and offset should return the number of events up to the given limit value that have
1284 * a sort time between the lower and uppper time bound (inclusive) where the result
1285 * set is shifted by the offset value.
1287 * If there are no events in the given time range then an empty result set should be
1290 public function test_get_calendar_action_events_by_course_time_limit_offset() {
1291 $user = $this->getDataGenerator()->create_user();
1292 $course1 = $this->getDataGenerator()->create_course();
1293 $course2 = $this->getDataGenerator()->create_course();
1294 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1295 $instance1 = $generator->create_instance(['course' => $course1->id
]);
1296 $instance2 = $generator->create_instance(['course' => $course2->id
]);
1299 $this->getDataGenerator()->enrol_user($user->id
, $course1->id
);
1300 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
);
1301 $this->resetAfterTest(true);
1302 $this->setUser($user);
1304 for ($i = 1; $i < 19; $i++
) {
1305 $courseid = ($i < 9) ?
$course1->id
: $course2->id
;
1306 $instance = ($i < 9) ?
$instance1->id
: $instance2->id
;
1307 $records[] = $this->create_calendar_event(
1308 sprintf('Event %d', $i),
1314 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1315 'courseid' => $courseid,
1317 'modulename' => 'assign',
1318 'instance' => $instance,
1323 $result = core_calendar_external
::get_calendar_action_events_by_course(
1324 $course1->id
, 2, 7, $records[2]->id
, 2);
1325 $result = \external_api
::clean_returnvalue(
1326 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1329 $result = $result['events'];
1331 $this->assertCount(2, $result);
1332 $this->assertEquals('Event 4', $result[0]['name']);
1333 $this->assertEquals('Event 5', $result[1]['name']);
1335 $result = core_calendar_external
::get_calendar_action_events_by_course(
1336 $course1->id
, 2, 7, $records[4]->id
, 2);
1337 $result = \external_api
::clean_returnvalue(
1338 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1341 $result = $result['events'];
1343 $this->assertCount(2, $result);
1344 $this->assertEquals('Event 6', $result[0]['name']);
1345 $this->assertEquals('Event 7', $result[1]['name']);
1347 $result = core_calendar_external
::get_calendar_action_events_by_course(
1348 $course1->id
, 2, 7, $records[6]->id
, 2);
1349 $result = \external_api
::clean_returnvalue(
1350 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1353 $result = $result['events'];
1355 $this->assertEmpty($result);
1359 * Test get_calendar_action_events_by_course with search feature
1361 public function test_get_calendar_action_events_by_course_with_search() {
1363 $user = $this->getDataGenerator()->create_user();
1364 $course = $this->getDataGenerator()->create_course();
1365 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1366 $instance = $generator->create_instance(['course' => $course->id
]);
1369 $this->getDataGenerator()->enrol_user($user->id
, $course->id
);
1370 $this->resetAfterTest(true);
1371 $this->setUser($user);
1373 for ($i = 1; $i < 5; $i++
) {
1374 $this->create_calendar_event(
1375 sprintf('Event %d', $i),
1381 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1382 'courseid' => $course->id
,
1384 'modulename' => 'assign',
1385 'instance' => $instance->id
,
1390 // No result found for fake search.
1391 $result = core_calendar_external
::get_calendar_action_events_by_course($course->id
, null, null, 0, 20, 'Fake search');
1392 $result = \external_api
::clean_returnvalue(
1393 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1396 $result = $result['events'];
1397 $this->assertEmpty($result);
1399 // Search for event name called 'Event 1'.
1400 $result = core_calendar_external
::get_calendar_action_events_by_course($course->id
, null, null, 0, 20, 'Event 1');
1401 $result = \external_api
::clean_returnvalue(
1402 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1405 $result = $result['events'];
1406 $this->assertCount(1, $result);
1407 $this->assertEquals('Event 1', $result[0]['name']);
1409 // Search for activity type called 'assign'.
1410 $result = core_calendar_external
::get_calendar_action_events_by_course($course->id
, null, null, 0, 20, 'assign');
1411 $result = \external_api
::clean_returnvalue(
1412 core_calendar_external
::get_calendar_action_events_by_course_returns(),
1415 $result = $result['events'];
1416 $this->assertCount(4, $result);
1417 $this->assertEquals('Event 1', $result[0]['name']);
1418 $this->assertEquals('Event 2', $result[1]['name']);
1419 $this->assertEquals('Event 3', $result[2]['name']);
1420 $this->assertEquals('Event 4', $result[3]['name']);
1424 * Test that get_action_events_by_courses will return a list of events for each
1425 * course you provided as long as the user is enrolled in the course.
1427 public function test_get_action_events_by_courses() {
1428 $user = $this->getDataGenerator()->create_user();
1429 $course1 = $this->getDataGenerator()->create_course();
1430 $course2 = $this->getDataGenerator()->create_course();
1431 $course3 = $this->getDataGenerator()->create_course();
1432 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1433 $instance1 = $generator->create_instance(['course' => $course1->id
]);
1434 $instance2 = $generator->create_instance(['course' => $course2->id
]);
1435 $instance3 = $generator->create_instance(['course' => $course3->id
]);
1437 $mapresult = function($result) {
1438 $groupedbycourse = [];
1439 foreach ($result['groupedbycourse'] as $group) {
1440 $events = $group['events'];
1441 $courseid = $group['courseid'];
1442 $groupedbycourse[$courseid] = $events;
1445 return $groupedbycourse;
1448 $this->getDataGenerator()->enrol_user($user->id
, $course1->id
);
1449 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
);
1450 $this->resetAfterTest(true);
1451 $this->setUser($user);
1453 for ($i = 1; $i < 10; $i++
) {
1455 $courseid = $course1->id
;
1456 $instance = $instance1->id
;
1457 } else if ($i < 6) {
1458 $courseid = $course2->id
;
1459 $instance = $instance2->id
;
1461 $courseid = $course3->id
;
1462 $instance = $instance3->id
;
1465 $records[] = $this->create_calendar_event(
1466 sprintf('Event %d', $i),
1472 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1473 'courseid' => $courseid,
1475 'modulename' => 'assign',
1476 'instance' => $instance,
1481 $result = core_calendar_external
::get_calendar_action_events_by_courses([], 1);
1482 $result = \external_api
::clean_returnvalue(
1483 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1486 $result = $result['groupedbycourse'];
1488 $this->assertEmpty($result);
1490 $result = core_calendar_external
::get_calendar_action_events_by_courses([$course1->id
], 3);
1491 $result = \external_api
::clean_returnvalue(
1492 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1496 $groupedbycourse = $mapresult($result);
1498 $this->assertEmpty($groupedbycourse[$course1->id
]);
1500 $result = core_calendar_external
::get_calendar_action_events_by_courses([$course1->id
], 1);
1501 $result = \external_api
::clean_returnvalue(
1502 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1505 $groupedbycourse = $mapresult($result);
1507 $this->assertCount(2, $groupedbycourse[$course1->id
]);
1508 $this->assertEquals('Event 1', $groupedbycourse[$course1->id
][0]['name']);
1509 $this->assertEquals('Event 2', $groupedbycourse[$course1->id
][1]['name']);
1511 $result = core_calendar_external
::get_calendar_action_events_by_courses(
1512 [$course1->id
, $course2->id
], 1);
1513 $result = \external_api
::clean_returnvalue(
1514 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1517 $groupedbycourse = $mapresult($result);
1519 $this->assertCount(2, $groupedbycourse[$course1->id
]);
1520 $this->assertEquals('Event 1', $groupedbycourse[$course1->id
][0]['name']);
1521 $this->assertEquals('Event 2', $groupedbycourse[$course1->id
][1]['name']);
1522 $this->assertCount(3, $groupedbycourse[$course2->id
]);
1523 $this->assertEquals('Event 3', $groupedbycourse[$course2->id
][0]['name']);
1524 $this->assertEquals('Event 4', $groupedbycourse[$course2->id
][1]['name']);
1525 $this->assertEquals('Event 5', $groupedbycourse[$course2->id
][2]['name']);
1527 $result = core_calendar_external
::get_calendar_action_events_by_courses(
1528 [$course1->id
, $course2->id
], 2, 4);
1529 $result = \external_api
::clean_returnvalue(
1530 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1533 $groupedbycourse = $mapresult($result);
1535 $this->assertCount(2, $groupedbycourse);
1536 $this->assertCount(1, $groupedbycourse[$course1->id
]);
1537 $this->assertEquals('Event 2', $groupedbycourse[$course1->id
][0]['name']);
1538 $this->assertCount(2, $groupedbycourse[$course2->id
]);
1539 $this->assertEquals('Event 3', $groupedbycourse[$course2->id
][0]['name']);
1540 $this->assertEquals('Event 4', $groupedbycourse[$course2->id
][1]['name']);
1542 $result = core_calendar_external
::get_calendar_action_events_by_courses(
1543 [$course1->id
, $course2->id
], 1, null, 1);
1544 $result = \external_api
::clean_returnvalue(
1545 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1548 $groupedbycourse = $mapresult($result);
1550 $this->assertCount(2, $groupedbycourse);
1551 $this->assertCount(1, $groupedbycourse[$course1->id
]);
1552 $this->assertEquals('Event 1', $groupedbycourse[$course1->id
][0]['name']);
1553 $this->assertCount(1, $groupedbycourse[$course2->id
]);
1554 $this->assertEquals('Event 3', $groupedbycourse[$course2->id
][0]['name']);
1558 * Test get_action_events_by_courses with search feature
1560 public function test_get_action_events_by_courses_with_search() {
1562 $user = $this->getDataGenerator()->create_user();
1563 $course1 = $this->getDataGenerator()->create_course();
1564 $course2 = $this->getDataGenerator()->create_course();
1565 $course3 = $this->getDataGenerator()->create_course();
1566 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1567 $instance1 = $generator->create_instance(['course' => $course1->id
]);
1568 $instance2 = $generator->create_instance(['course' => $course2->id
]);
1569 $instance3 = $generator->create_instance(['course' => $course3->id
]);
1571 $this->getDataGenerator()->enrol_user($user->id
, $course1->id
);
1572 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
);
1573 $this->resetAfterTest(true);
1574 $this->setUser($user);
1576 $mapresult = function($result) {
1577 $groupedbycourse = [];
1578 foreach ($result['groupedbycourse'] as $group) {
1579 $events = $group['events'];
1580 $courseid = $group['courseid'];
1581 $groupedbycourse[$courseid] = $events;
1584 return $groupedbycourse;
1587 for ($i = 1; $i < 10; $i++
) {
1589 $courseid = $course1->id
;
1590 $instance = $instance1->id
;
1591 } else if ($i < 6) {
1592 $courseid = $course2->id
;
1593 $instance = $instance2->id
;
1595 $courseid = $course3->id
;
1596 $instance = $instance3->id
;
1599 $records[] = $this->create_calendar_event(
1600 sprintf('Event %d', $i),
1606 'type' => CALENDAR_EVENT_TYPE_ACTION
,
1607 'courseid' => $courseid,
1609 'modulename' => 'assign',
1610 'instance' => $instance,
1615 // No result found for fake search.
1616 $result = core_calendar_external
::get_calendar_action_events_by_courses([$course1->id
, $course2->id
, $course3->id
],
1617 1, null, 20, 'Fake search');
1618 $result = \external_api
::clean_returnvalue(
1619 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1622 $groupedbycourse = $mapresult($result);
1624 $this->assertEmpty($groupedbycourse[$course1->id
]);
1625 $this->assertEmpty($groupedbycourse[$course2->id
]);
1626 $this->assertArrayNotHasKey($course3->id
, $groupedbycourse);
1628 // Search for event name called 'Event 1'.
1629 $result = core_calendar_external
::get_calendar_action_events_by_courses([$course1->id
, $course2->id
, $course3->id
],
1630 1, null, 20, 'Event 1');
1631 $result = \external_api
::clean_returnvalue(
1632 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1635 $groupedbycourse = $mapresult($result);
1637 $this->assertArrayNotHasKey($course3->id
, $groupedbycourse);
1638 $this->assertCount(2, $groupedbycourse);
1639 $this->assertCount(1, $groupedbycourse[$course1->id
]);
1640 $this->assertCount(0, $groupedbycourse[$course2->id
]);
1641 $this->assertEquals('Event 1', $groupedbycourse[$course1->id
][0]['name']);
1643 // Search for activity type called 'assign'.
1644 $result = core_calendar_external
::get_calendar_action_events_by_courses([$course1->id
, $course2->id
, $course3->id
],
1645 1, null, 20, 'assign');
1646 $result = \external_api
::clean_returnvalue(
1647 core_calendar_external
::get_calendar_action_events_by_courses_returns(),
1650 $groupedbycourse = $mapresult($result);
1652 $this->assertArrayNotHasKey($course3->id
, $groupedbycourse);
1653 $this->assertCount(2, $groupedbycourse);
1654 $this->assertCount(2, $groupedbycourse[$course1->id
]);
1655 $this->assertCount(3, $groupedbycourse[$course2->id
]);
1656 $this->assertEquals('Event 1', $groupedbycourse[$course1->id
][0]['name']);
1657 $this->assertEquals('Event 2', $groupedbycourse[$course1->id
][1]['name']);
1658 $this->assertEquals('Event 3', $groupedbycourse[$course2->id
][0]['name']);
1659 $this->assertEquals('Event 4', $groupedbycourse[$course2->id
][1]['name']);
1660 $this->assertEquals('Event 5', $groupedbycourse[$course2->id
][2]['name']);
1664 * Test for deleting module events.
1666 public function test_delete_calendar_events_for_modules() {
1667 $this->resetAfterTest();
1668 $this->setAdminUser();
1669 $course = $this->getDataGenerator()->create_course();
1670 $nexttime = time() + DAYSECS
;
1671 $this->getDataGenerator()->create_module('assign', ['course' => $course->id
, 'duedate' => $nexttime]);
1672 $events = calendar_get_events(time(), $nexttime, true, true, true);
1673 $this->assertCount(1, $events);
1675 foreach ($events as $event) {
1677 'eventid' => $event->id
,
1682 $this->expectException(\moodle_exception
::class);
1683 core_calendar_external
::delete_calendar_events($params);
1687 * Updating the event start day should change the date value but leave
1688 * the time of day unchanged.
1690 public function test_update_event_start_day() {
1691 $generator = $this->getDataGenerator();
1692 $user = $generator->create_user();
1693 $roleid = $generator->create_role();
1694 $context = \context_system
::instance();
1695 $originalstarttime = new \
DateTimeImmutable('2017-01-1T15:00:00+08:00');
1696 $newstartdate = new \
DateTimeImmutable('2018-02-2T10:00:00+08:00');
1697 $expected = new \
DateTimeImmutable('2018-02-2T15:00:00+08:00');
1699 $generator->role_assign($roleid, $user->id
, $context->id
);
1700 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW
, $roleid, $context, true);
1702 $this->setUser($user);
1703 $this->resetAfterTest(true);
1705 $event = $this->create_calendar_event(
1713 'timestart' => $originalstarttime->getTimestamp()
1717 $result = core_calendar_external
::update_event_start_day($event->id
, $newstartdate->getTimestamp());
1718 $result = \external_api
::clean_returnvalue(
1719 core_calendar_external
::update_event_start_day_returns(),
1723 $this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);
1727 * A user should not be able to edit an event that they don't have
1730 public function test_update_event_start_day_no_permission() {
1731 $generator = $this->getDataGenerator();
1732 $user = $generator->create_user();
1733 $roleid = $generator->create_role();
1734 $context = \context_system
::instance();
1735 $originalstarttime = new \
DateTimeImmutable('2017-01-1T15:00:00+08:00');
1736 $newstartdate = new \
DateTimeImmutable('2018-02-2T10:00:00+08:00');
1737 $expected = new \
DateTimeImmutable('2018-02-2T15:00:00+08:00');
1739 $generator->role_assign($roleid, $user->id
, $context->id
);
1740 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW
, $roleid, $context, true);
1742 $this->setUser($user);
1743 $this->resetAfterTest(true);
1745 $event = $this->create_calendar_event(
1753 'timestart' => $originalstarttime->getTimestamp()
1757 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT
, $roleid, $context, true);
1758 $this->expectException(\moodle_exception
::class);
1759 $result = core_calendar_external
::update_event_start_day($event->id
, $newstartdate->getTimestamp());
1760 $result = \external_api
::clean_returnvalue(
1761 core_calendar_external
::update_event_start_day_returns(),
1767 * A user should not be able to update a module event.
1769 public function test_update_event_start_day_module_event() {
1770 $generator = $this->getDataGenerator();
1771 $user = $generator->create_user();
1772 $course = $generator->create_course();
1773 $plugingenerator = $generator->get_plugin_generator('mod_assign');
1774 $moduleinstance = $plugingenerator->create_instance(['course' => $course->id
]);
1775 $roleid = $generator->create_role();
1776 $context = \context_course
::instance($course->id
);
1777 $originalstarttime = new \
DateTimeImmutable('2017-01-1T15:00:00+08:00');
1778 $newstartdate = new \
DateTimeImmutable('2018-02-2T10:00:00+08:00');
1779 $expected = new \
DateTimeImmutable('2018-02-2T15:00:00+08:00');
1781 $generator->role_assign($roleid, $user->id
, $context->id
);
1782 $generator->enrol_user($user->id
, $course->id
);
1784 $this->setUser($user);
1785 $this->resetAfterTest(true);
1787 $event = $this->create_calendar_event(
1794 'modulename' => 'assign',
1795 'instance' => $moduleinstance->id
,
1796 'courseid' => $course->id
,
1797 'timestart' => $originalstarttime->getTimestamp()
1801 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
1802 $this->expectException(\moodle_exception
::class);
1803 $result = core_calendar_external
::update_event_start_day($event->id
, $newstartdate->getTimestamp());
1804 $result = \external_api
::clean_returnvalue(
1805 core_calendar_external
::update_event_start_day_returns(),
1811 * Submit a request where the time duration until is earlier than the time
1812 * start in order to get a validation error from the server.
1814 public function test_submit_create_update_form_validation_error() {
1815 $user = $this->getDataGenerator()->create_user();
1816 $timestart = new \
DateTime();
1817 $interval = new \
DateInterval("P1D"); // One day.
1818 $timedurationuntil = new \
DateTime();
1819 $timedurationuntil->sub($interval);
1822 'userid' => $user->id
,
1828 'day' => $timestart->format('j'),
1829 'month' => $timestart->format('n'),
1830 'year' => $timestart->format('Y'),
1831 'hour' => $timestart->format('G'),
1834 'eventtype' => 'user',
1839 'location' => 'Test',
1841 'timedurationuntil' => [
1842 'day' => $timedurationuntil->format('j'),
1843 'month' => $timedurationuntil->format('n'),
1844 'year' => $timedurationuntil->format('Y'),
1845 'hour' => $timedurationuntil->format('G'),
1850 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
1852 $querystring = http_build_query($formdata, '', '&');
1854 $this->resetAfterTest(true);
1855 $this->setUser($user);
1857 $result = \external_api
::clean_returnvalue(
1858 core_calendar_external
::submit_create_update_form_returns(),
1859 core_calendar_external
::submit_create_update_form($querystring)
1862 $this->assertTrue($result['validationerror']);
1866 * A user with the moodle/calendar:manageownentries capability at the
1867 * system context should be able to create a user event.
1869 public function test_submit_create_update_form_create_user_event() {
1870 $generator = $this->getDataGenerator();
1871 $user = $generator->create_user();
1872 $roleid = $generator->create_role();
1873 $context = \context_system
::instance();
1874 $timestart = new \
DateTime();
1875 $interval = new \
DateInterval("P1D"); // One day.
1876 $timedurationuntil = new \
DateTime();
1877 $timedurationuntil->add($interval);
1880 'userid' => $user->id
,
1886 'day' => $timestart->format('j'),
1887 'month' => $timestart->format('n'),
1888 'year' => $timestart->format('Y'),
1889 'hour' => $timestart->format('G'),
1892 'eventtype' => 'user',
1898 'location' => 'Test',
1900 'timedurationuntil' => [
1901 'day' => $timedurationuntil->format('j'),
1902 'month' => $timedurationuntil->format('n'),
1903 'year' => $timedurationuntil->format('Y'),
1904 'hour' => $timedurationuntil->format('G'),
1909 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
1910 $querystring = http_build_query($formdata, '', '&');
1912 $generator->role_assign($roleid, $user->id
, $context->id
);
1913 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW
, $roleid, $context, true);
1915 $user->ignoresesskey
= true;
1916 $this->resetAfterTest(true);
1917 $this->setUser($user);
1919 $result = \external_api
::clean_returnvalue(
1920 core_calendar_external
::submit_create_update_form_returns(),
1921 core_calendar_external
::submit_create_update_form($querystring)
1924 $event = $result['event'];
1925 $this->assertEquals($user->id
, $event['userid']);
1926 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1927 $this->assertEquals($formdata['name'], $event['name']);
1931 * A user without the moodle/calendar:manageownentries capability at the
1932 * system context should not be able to create a user event.
1934 public function test_submit_create_update_form_create_user_event_no_permission() {
1935 $generator = $this->getDataGenerator();
1936 $user = $generator->create_user();
1937 $roleid = $generator->create_role();
1938 $context = \context_system
::instance();
1939 $timestart = new \
DateTime();
1940 $interval = new \
DateInterval("P1D"); // One day.
1941 $timedurationuntil = new \
DateTime();
1942 $timedurationuntil->add($interval);
1945 'userid' => $user->id
,
1951 'day' => $timestart->format('j'),
1952 'month' => $timestart->format('n'),
1953 'year' => $timestart->format('Y'),
1954 'hour' => $timestart->format('G'),
1957 'eventtype' => 'user',
1962 'location' => 'Test',
1964 'timedurationuntil' => [
1965 'day' => $timedurationuntil->format('j'),
1966 'month' => $timedurationuntil->format('n'),
1967 'year' => $timedurationuntil->format('Y'),
1968 'hour' => $timedurationuntil->format('G'),
1973 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
1974 $querystring = http_build_query($formdata, '', '&');
1976 $generator->role_assign($roleid, $user->id
, $context->id
);
1977 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT
, $roleid, $context, true);
1979 $user->ignoresesskey
= true;
1980 $this->resetAfterTest(true);
1981 $this->setUser($user);
1983 $this->expectException(\moodle_exception
::class);
1985 \external_api
::clean_returnvalue(
1986 core_calendar_external
::submit_create_update_form_returns(),
1987 core_calendar_external
::submit_create_update_form($querystring)
1992 * A user with the moodle/calendar:manageentries capability at the
1993 * site course context should be able to create a site event.
1995 public function test_submit_create_update_form_create_site_event() {
1996 $generator = $this->getDataGenerator();
1997 $user = $generator->create_user();
1998 $context = \context_system
::instance();
1999 $roleid = $generator->create_role();
2000 $timestart = new \
DateTime();
2001 $interval = new \
DateInterval("P1D"); // One day.
2002 $timedurationuntil = new \
DateTime();
2003 $timedurationuntil->add($interval);
2006 'userid' => $user->id
,
2012 'day' => $timestart->format('j'),
2013 'month' => $timestart->format('n'),
2014 'year' => $timestart->format('Y'),
2015 'hour' => $timestart->format('G'),
2018 'eventtype' => 'site',
2024 'location' => 'Test',
2026 'timedurationuntil' => [
2027 'day' => $timedurationuntil->format('j'),
2028 'month' => $timedurationuntil->format('n'),
2029 'year' => $timedurationuntil->format('Y'),
2030 'hour' => $timedurationuntil->format('G'),
2035 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2036 $querystring = http_build_query($formdata, '', '&');
2038 $generator->role_assign($roleid, $user->id
, $context->id
);
2040 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
2042 $user->ignoresesskey
= true;
2043 $this->resetAfterTest(true);
2044 $this->setUser($user);
2046 $result = \external_api
::clean_returnvalue(
2047 core_calendar_external
::submit_create_update_form_returns(),
2048 core_calendar_external
::submit_create_update_form($querystring)
2051 $event = $result['event'];
2052 $this->assertEquals($user->id
, $event['userid']);
2053 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2054 $this->assertEquals($formdata['name'], $event['name']);
2058 * A user without the moodle/calendar:manageentries capability at the
2059 * site course context should not be able to create a site event.
2061 public function test_submit_create_update_form_create_site_event_no_permission() {
2062 $generator = $this->getDataGenerator();
2063 $user = $generator->create_user();
2064 $context = \context_course
::instance(SITEID
);
2065 $roleid = $generator->create_role();
2066 $timestart = new \
DateTime();
2067 $interval = new \
DateInterval("P1D"); // One day.
2068 $timedurationuntil = new \
DateTime();
2069 $timedurationuntil->add($interval);
2072 'userid' => $user->id
,
2078 'day' => $timestart->format('j'),
2079 'month' => $timestart->format('n'),
2080 'year' => $timestart->format('Y'),
2081 'hour' => $timestart->format('G'),
2084 'eventtype' => 'site',
2089 'location' => 'Test',
2091 'timedurationuntil' => [
2092 'day' => $timedurationuntil->format('j'),
2093 'month' => $timedurationuntil->format('n'),
2094 'year' => $timedurationuntil->format('Y'),
2095 'hour' => $timedurationuntil->format('G'),
2100 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2101 $querystring = http_build_query($formdata, '', '&');
2103 $generator->role_assign($roleid, $user->id
, $context->id
);
2105 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT
, $roleid, $context, true);
2107 $user->ignoresesskey
= true;
2108 $this->resetAfterTest(true);
2109 $this->setUser($user);
2111 $result = \external_api
::clean_returnvalue(
2112 core_calendar_external
::submit_create_update_form_returns(),
2113 core_calendar_external
::submit_create_update_form($querystring)
2116 $this->assertTrue($result['validationerror']);
2120 * A user that has the moodle/calendar:manageentries in a course that they
2121 * are enrolled in should be able to create a course event in that course.
2123 public function test_submit_create_update_form_create_course_event() {
2124 $generator = $this->getDataGenerator();
2125 $user = $generator->create_user();
2126 $course = $generator->create_course();
2127 $context = \context_course
::instance($course->id
);
2128 $roleid = $generator->create_role();
2129 $timestart = new \
DateTime();
2130 $interval = new \
DateInterval("P1D"); // One day.
2131 $timedurationuntil = new \
DateTime();
2132 $timedurationuntil->add($interval);
2135 'userid' => $user->id
,
2141 'day' => $timestart->format('j'),
2142 'month' => $timestart->format('n'),
2143 'year' => $timestart->format('Y'),
2144 'hour' => $timestart->format('G'),
2147 'eventtype' => 'course',
2148 'courseid' => $course->id
,
2154 'location' => 'Test',
2156 'timedurationuntil' => [
2157 'day' => $timedurationuntil->format('j'),
2158 'month' => $timedurationuntil->format('n'),
2159 'year' => $timedurationuntil->format('Y'),
2160 'hour' => $timedurationuntil->format('G'),
2165 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2166 $querystring = http_build_query($formdata, '', '&');
2168 $generator->enrol_user($user->id
, $course->id
, 'student');
2169 $generator->role_assign($roleid, $user->id
, $context->id
);
2171 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
2173 $user->ignoresesskey
= true;
2174 $this->resetAfterTest(true);
2175 $this->setUser($user);
2177 $result = \external_api
::clean_returnvalue(
2178 core_calendar_external
::submit_create_update_form_returns(),
2179 core_calendar_external
::submit_create_update_form($querystring)
2182 $event = $result['event'];
2183 $this->assertEquals($user->id
, $event['userid']);
2184 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2185 $this->assertEquals($formdata['name'], $event['name']);
2186 $this->assertEquals($formdata['courseid'], $event['course']['id']);
2190 * A user without the moodle/calendar:manageentries capability in a course
2191 * that they are enrolled in should not be able to create a course event in that course.
2193 public function test_submit_create_update_form_create_course_event_no_permission() {
2194 $generator = $this->getDataGenerator();
2195 $user = $generator->create_user();
2196 $course = $generator->create_course();
2197 $context = \context_course
::instance($course->id
);
2198 $roleid = $generator->create_role();
2199 $timestart = new \
DateTime();
2200 $interval = new \
DateInterval("P1D"); // One day.
2201 $timedurationuntil = new \
DateTime();
2202 $timedurationuntil->add($interval);
2205 'userid' => $user->id
,
2211 'day' => $timestart->format('j'),
2212 'month' => $timestart->format('n'),
2213 'year' => $timestart->format('Y'),
2214 'hour' => $timestart->format('G'),
2217 'eventtype' => 'course',
2218 'courseid' => $course->id
,
2223 'location' => 'Test',
2225 'timedurationuntil' => [
2226 'day' => $timedurationuntil->format('j'),
2227 'month' => $timedurationuntil->format('n'),
2228 'year' => $timedurationuntil->format('Y'),
2229 'hour' => $timedurationuntil->format('G'),
2234 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2235 $querystring = http_build_query($formdata, '', '&');
2237 $generator->enrol_user($user->id
, $course->id
, 'student');
2238 $generator->role_assign($roleid, $user->id
, $context->id
);
2240 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT
, $roleid, $context, true);
2242 $user->ignoresesskey
= true;
2243 $this->resetAfterTest(true);
2244 $this->setUser($user);
2246 $result = \external_api
::clean_returnvalue(
2247 core_calendar_external
::submit_create_update_form_returns(),
2248 core_calendar_external
::submit_create_update_form($querystring)
2251 $this->assertTrue($result['validationerror']);
2255 * A user should not be able to create an event for a course that they are
2258 public function test_submit_create_update_form_create_course_event_not_enrolled() {
2259 $generator = $this->getDataGenerator();
2260 $user = $generator->create_user();
2261 $course = $generator->create_course();
2262 $course2 = $generator->create_course();
2263 $context = \context_course
::instance($course->id
);
2264 $roleid = $generator->create_role();
2265 $timestart = new \
DateTime();
2266 $interval = new \
DateInterval("P1D"); // One day.
2267 $timedurationuntil = new \
DateTime();
2268 $timedurationuntil->add($interval);
2271 'userid' => $user->id
,
2277 'day' => $timestart->format('j'),
2278 'month' => $timestart->format('n'),
2279 'year' => $timestart->format('Y'),
2280 'hour' => $timestart->format('G'),
2283 'eventtype' => 'course',
2284 'courseid' => $course2->id
, // Not enrolled.
2289 'location' => 'Test',
2291 'timedurationuntil' => [
2292 'day' => $timedurationuntil->format('j'),
2293 'month' => $timedurationuntil->format('n'),
2294 'year' => $timedurationuntil->format('Y'),
2295 'hour' => $timedurationuntil->format('G'),
2300 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2301 $querystring = http_build_query($formdata, '', '&');
2303 $generator->enrol_user($user->id
, $course->id
, 'student');
2304 $generator->role_assign($roleid, $user->id
, $context->id
);
2306 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
2308 $user->ignoresesskey
= true;
2309 $this->resetAfterTest(true);
2310 $this->setUser($user);
2312 $result = \external_api
::clean_returnvalue(
2313 core_calendar_external
::submit_create_update_form_returns(),
2314 core_calendar_external
::submit_create_update_form($querystring)
2317 $this->assertTrue($result['validationerror']);
2321 * A user should be able to create an event for a group that they are a member of in
2322 * a course in which they are enrolled and have the moodle/calendar:manageentries capability.
2324 public function test_submit_create_update_form_create_group_event_group_member_manage_course() {
2325 $generator = $this->getDataGenerator();
2326 $user = $generator->create_user();
2327 $course = $generator->create_course();
2328 $group = $generator->create_group(array('courseid' => $course->id
));
2329 $context = \context_course
::instance($course->id
);
2330 $roleid = $generator->create_role();
2331 $timestart = new \
DateTime();
2332 $interval = new \
DateInterval("P1D"); // One day.
2333 $timedurationuntil = new \
DateTime();
2334 $timedurationuntil->add($interval);
2337 'userid' => $user->id
,
2343 'day' => $timestart->format('j'),
2344 'month' => $timestart->format('n'),
2345 'year' => $timestart->format('Y'),
2346 'hour' => $timestart->format('G'),
2349 'eventtype' => 'group',
2350 'groupid' => $group->id
,
2351 'groupcourseid' => $course->id
,
2357 'location' => 'Test',
2359 'timedurationuntil' => [
2360 'day' => $timedurationuntil->format('j'),
2361 'month' => $timedurationuntil->format('n'),
2362 'year' => $timedurationuntil->format('Y'),
2363 'hour' => $timedurationuntil->format('G'),
2368 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2369 $querystring = http_build_query($formdata, '', '&');
2371 $generator->enrol_user($user->id
, $course->id
, 'student');
2372 $generator->role_assign($roleid, $user->id
, $context->id
);
2373 $generator->create_group_member(['groupid' => $group->id
, 'userid' => $user->id
]);
2375 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
2377 $user->ignoresesskey
= true;
2378 $this->resetAfterTest(true);
2379 $this->setUser($user);
2381 $result = \external_api
::clean_returnvalue(
2382 core_calendar_external
::submit_create_update_form_returns(),
2383 core_calendar_external
::submit_create_update_form($querystring)
2386 $event = $result['event'];
2387 $this->assertEquals($user->id
, $event['userid']);
2388 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2389 $this->assertEquals($formdata['name'], $event['name']);
2390 $this->assertEquals($group->id
, $event['groupid']);
2394 * A user should be able to create an event for a group that they are a member of in
2395 * a course in which they are enrolled and have the moodle/calendar:managegroupentries capability.
2397 public function test_submit_create_update_form_create_group_event_group_member_manage_group_entries() {
2398 $generator = $this->getDataGenerator();
2399 $user = $generator->create_user();
2400 $course = $generator->create_course();
2401 $group = $generator->create_group(array('courseid' => $course->id
));
2402 $context = \context_course
::instance($course->id
);
2403 $roleid = $generator->create_role();
2404 $timestart = new \
DateTime();
2405 $interval = new \
DateInterval("P1D"); // One day.
2406 $timedurationuntil = new \
DateTime();
2407 $timedurationuntil->add($interval);
2410 'userid' => $user->id
,
2416 'day' => $timestart->format('j'),
2417 'month' => $timestart->format('n'),
2418 'year' => $timestart->format('Y'),
2419 'hour' => $timestart->format('G'),
2422 'eventtype' => 'group',
2423 'groupid' => $group->id
,
2424 'groupcourseid' => $course->id
,
2430 'location' => 'Test',
2432 'timedurationuntil' => [
2433 'day' => $timedurationuntil->format('j'),
2434 'month' => $timedurationuntil->format('n'),
2435 'year' => $timedurationuntil->format('Y'),
2436 'hour' => $timedurationuntil->format('G'),
2441 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2442 $querystring = http_build_query($formdata, '', '&');
2444 $generator->enrol_user($user->id
, $course->id
, 'student');
2445 $generator->role_assign($roleid, $user->id
, $context->id
);
2446 $generator->create_group_member(['groupid' => $group->id
, 'userid' => $user->id
]);
2448 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT
, $roleid, $context, true);
2449 assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW
, $roleid, $context, true);
2451 $user->ignoresesskey
= true;
2452 $this->resetAfterTest(true);
2453 $this->setUser($user);
2455 $result = \external_api
::clean_returnvalue(
2456 core_calendar_external
::submit_create_update_form_returns(),
2457 core_calendar_external
::submit_create_update_form($querystring)
2460 $event = $result['event'];
2461 $this->assertEquals($user->id
, $event['userid']);
2462 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2463 $this->assertEquals($formdata['name'], $event['name']);
2464 $this->assertEquals($group->id
, $event['groupid']);
2468 * A user should be able to create an event for any group in a course in which
2469 * they are enrolled and have the moodle/site:accessallgroups capability.
2471 public function test_submit_create_update_form_create_group_event_access_all_groups() {
2472 $generator = $this->getDataGenerator();
2473 $user = $generator->create_user();
2474 $course = $generator->create_course();
2475 $group = $generator->create_group(array('courseid' => $course->id
));
2476 $context = \context_course
::instance($course->id
);
2477 $roleid = $generator->create_role();
2478 $timestart = new \
DateTime();
2479 $interval = new \
DateInterval("P1D"); // One day.
2480 $timedurationuntil = new \
DateTime();
2481 $timedurationuntil->add($interval);
2484 'userid' => $user->id
,
2490 'day' => $timestart->format('j'),
2491 'month' => $timestart->format('n'),
2492 'year' => $timestart->format('Y'),
2493 'hour' => $timestart->format('G'),
2496 'eventtype' => 'group',
2497 'groupid' => $group->id
,
2498 'groupcourseid' => $course->id
,
2504 'location' => 'Test',
2506 'timedurationuntil' => [
2507 'day' => $timedurationuntil->format('j'),
2508 'month' => $timedurationuntil->format('n'),
2509 'year' => $timedurationuntil->format('Y'),
2510 'hour' => $timedurationuntil->format('G'),
2515 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2516 $querystring = http_build_query($formdata, '', '&');
2518 $generator->enrol_user($user->id
, $course->id
, 'student');
2519 $generator->role_assign($roleid, $user->id
, $context->id
);
2521 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
2522 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $roleid, $context, true);
2524 $user->ignoresesskey
= true;
2525 $this->resetAfterTest(true);
2526 $this->setUser($user);
2528 $result = \external_api
::clean_returnvalue(
2529 core_calendar_external
::submit_create_update_form_returns(),
2530 core_calendar_external
::submit_create_update_form($querystring)
2533 $event = $result['event'];
2534 $this->assertEquals($user->id
, $event['userid']);
2535 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2536 $this->assertEquals($formdata['name'], $event['name']);
2537 $this->assertEquals($group->id
, $event['groupid']);
2541 * A user should not be able to create an event for any group that they are not a
2542 * member of in a course in which they are enrolled but don't have the
2543 * moodle/site:accessallgroups capability.
2545 public function test_submit_create_update_form_create_group_event_non_member_no_permission() {
2546 $generator = $this->getDataGenerator();
2547 $user = $generator->create_user();
2548 $course = $generator->create_course();
2549 $group = $generator->create_group(array('courseid' => $course->id
));
2550 $context = \context_course
::instance($course->id
);
2551 $roleid = $generator->create_role();
2552 $timestart = new \
DateTime();
2553 $interval = new \
DateInterval("P1D"); // One day.
2554 $timedurationuntil = new \
DateTime();
2555 $timedurationuntil->add($interval);
2558 'userid' => $user->id
,
2564 'day' => $timestart->format('j'),
2565 'month' => $timestart->format('n'),
2566 'year' => $timestart->format('Y'),
2567 'hour' => $timestart->format('G'),
2570 'eventtype' => 'group',
2571 'groupid' => $group->id
,
2572 'groupcourseid' => $course->id
,
2577 'location' => 'Test',
2579 'timedurationuntil' => [
2580 'day' => $timedurationuntil->format('j'),
2581 'month' => $timedurationuntil->format('n'),
2582 'year' => $timedurationuntil->format('Y'),
2583 'hour' => $timedurationuntil->format('G'),
2588 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2589 $querystring = http_build_query($formdata, '', '&');
2591 $generator->enrol_user($user->id
, $course->id
, 'student');
2592 $generator->role_assign($roleid, $user->id
, $context->id
);
2594 assign_capability('moodle/calendar:manageentries', CAP_ALLOW
, $roleid, $context, true);
2595 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT
, $roleid, $context, true);
2597 $user->ignoresesskey
= true;
2598 $this->resetAfterTest(true);
2599 $this->setUser($user);
2601 $result = \external_api
::clean_returnvalue(
2602 core_calendar_external
::submit_create_update_form_returns(),
2603 core_calendar_external
::submit_create_update_form($querystring)
2606 $this->assertTrue($result['validationerror']);
2610 * A user should not be able load the calendar monthly view for a course they cannot access.
2612 public function test_get_calendar_monthly_view_no_course_permission() {
2614 $this->resetAfterTest(true);
2615 $this->setAdminUser();
2617 $generator = $this->getDataGenerator();
2618 $user1 = $generator->create_user();
2619 $user2 = $generator->create_user();
2620 $course = $generator->create_course();
2621 $generator->enrol_user($user1->id
, $course->id
, 'student');
2622 $name = 'Course Event (course' . $course->id
. ')';
2623 $record = new \
stdClass();
2624 $record->courseid
= $course->id
;
2625 $courseevent = $this->create_calendar_event($name, $USER->id
, 'course', 0, time(), $record);
2627 $timestart = new \
DateTime();
2628 // Admin can load the course.
2629 $data = \external_api
::clean_returnvalue(
2630 core_calendar_external
::get_calendar_monthly_view_returns(),
2631 core_calendar_external
::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
2632 $course->id
, null, false, true, $timestart->format('j'))
2634 $this->assertEquals($data['courseid'], $course->id
);
2635 // User enrolled in the course can load the course calendar.
2636 $this->setUser($user1);
2637 $data = \external_api
::clean_returnvalue(
2638 core_calendar_external
::get_calendar_monthly_view_returns(),
2639 core_calendar_external
::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
2640 $course->id
, null, false, true, $timestart->format('j'))
2642 $this->assertEquals($data['courseid'], $course->id
);
2643 // User not enrolled in the course cannot load the course calendar.
2644 $this->setUser($user2);
2645 $this->expectException(\require_login_exception
::class);
2646 $data = \external_api
::clean_returnvalue(
2647 core_calendar_external
::get_calendar_monthly_view_returns(),
2648 core_calendar_external
::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
2649 $course->id
, null, false, false, $timestart->format('j'))
2654 * Test get_calendar_monthly_view when a day parameter is provided.
2656 public function test_get_calendar_monthly_view_with_day_provided() {
2657 $this->resetAfterTest();
2658 $this->setAdminUser();
2660 $timestart = new \
DateTime();
2661 $data = \external_api
::clean_returnvalue(
2662 core_calendar_external
::get_calendar_monthly_view_returns(),
2663 core_calendar_external
::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
2664 SITEID
, null, false, true, $timestart->format('j'))
2666 $this->assertEquals($data['date']['mday'], $timestart->format('d'));
2670 * A user should not be able load the calendar day view for a course they cannot access.
2672 public function test_get_calendar_day_view_no_course_permission() {
2674 $this->resetAfterTest(true);
2675 $this->setAdminUser();
2677 $generator = $this->getDataGenerator();
2678 $user1 = $generator->create_user();
2679 $user2 = $generator->create_user();
2680 $course = $generator->create_course();
2681 $generator->enrol_user($user1->id
, $course->id
, 'student');
2682 $name = 'Course Event (course' . $course->id
. ')';
2683 $record = new \
stdClass();
2684 $record->courseid
= $course->id
;
2685 $courseevent = $this->create_calendar_event($name, $USER->id
, 'course', 0, time(), $record);
2687 $timestart = new \
DateTime();
2688 // Admin can load the course.
2689 $data = \external_api
::clean_returnvalue(
2690 core_calendar_external
::get_calendar_day_view_returns(),
2691 core_calendar_external
::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),
2692 $timestart->format('j'), $course->id
, null)
2694 $this->assertEquals($data['courseid'], $course->id
);
2695 // User enrolled in the course can load the course calendar.
2696 $this->setUser($user1);
2697 $data = \external_api
::clean_returnvalue(
2698 core_calendar_external
::get_calendar_day_view_returns(),
2699 core_calendar_external
::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),
2700 $timestart->format('j'), $course->id
, null)
2702 $this->assertEquals($data['courseid'], $course->id
);
2703 // User not enrolled in the course cannot load the course calendar.
2704 $this->setUser($user2);
2705 $this->expectException(\require_login_exception
::class);
2706 $data = \external_api
::clean_returnvalue(
2707 core_calendar_external
::get_calendar_day_view_returns(),
2708 core_calendar_external
::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),
2709 $timestart->format('j'), $course->id
, null)
2714 * A user should not be able load the calendar upcoming view for a course they cannot access.
2716 public function test_get_calendar_upcoming_view_no_course_permission() {
2718 $this->resetAfterTest(true);
2719 $this->setAdminUser();
2721 $generator = $this->getDataGenerator();
2722 $user1 = $generator->create_user();
2723 $user2 = $generator->create_user();
2724 $course = $generator->create_course();
2725 $generator->enrol_user($user1->id
, $course->id
, 'student');
2726 $name = 'Course Event (course' . $course->id
. ')';
2727 $record = new \
stdClass();
2728 $record->courseid
= $course->id
;
2729 $courseevent = $this->create_calendar_event($name, $USER->id
, 'course', 0, time(), $record);
2731 // Admin can load the course.
2732 $data = \external_api
::clean_returnvalue(
2733 core_calendar_external
::get_calendar_upcoming_view_returns(),
2734 core_calendar_external
::get_calendar_upcoming_view($course->id
, null)
2736 $this->assertEquals($data['courseid'], $course->id
);
2737 // User enrolled in the course can load the course calendar.
2738 $this->setUser($user1);
2739 $data = \external_api
::clean_returnvalue(
2740 core_calendar_external
::get_calendar_upcoming_view_returns(),
2741 core_calendar_external
::get_calendar_upcoming_view($course->id
, null)
2743 $this->assertEquals($data['courseid'], $course->id
);
2744 // User not enrolled in the course cannot load the course calendar.
2745 $this->setUser($user2);
2746 $this->expectException(\require_login_exception
::class);
2747 $data = \external_api
::clean_returnvalue(
2748 core_calendar_external
::get_calendar_upcoming_view_returns(),
2749 core_calendar_external
::get_calendar_upcoming_view($course->id
, null)
2754 * A user should not be able load the calendar event for a course they cannot access.
2756 public function test_get_calendar_event_by_id_no_course_permission() {
2758 $this->resetAfterTest(true);
2759 $this->setAdminUser();
2761 $generator = $this->getDataGenerator();
2762 $user1 = $generator->create_user();
2763 $user2 = $generator->create_user();
2764 $course = $generator->create_course();
2765 $generator->enrol_user($user1->id
, $course->id
, 'student');
2766 $name = 'Course Event (course' . $course->id
. ')';
2767 $record = new \
stdClass();
2768 $record->courseid
= $course->id
;
2769 $courseevent = $this->create_calendar_event($name, $USER->id
, 'course', 0, time(), $record);
2771 // Admin can load the course event.
2772 $data = \external_api
::clean_returnvalue(
2773 core_calendar_external
::get_calendar_event_by_id_returns(),
2774 core_calendar_external
::get_calendar_event_by_id($courseevent->id
)
2776 $this->assertEquals($data['event']['id'], $courseevent->id
);
2777 // User enrolled in the course can load the course event.
2778 $this->setUser($user1);
2779 $data = \external_api
::clean_returnvalue(
2780 core_calendar_external
::get_calendar_event_by_id_returns(),
2781 core_calendar_external
::get_calendar_event_by_id($courseevent->id
)
2783 $this->assertEquals($data['event']['id'], $courseevent->id
);
2784 // User not enrolled in the course cannot load the course event.
2785 $this->setUser($user2);
2786 $this->expectException(\moodle_exception
::class);
2787 $data = \external_api
::clean_returnvalue(
2788 core_calendar_external
::get_calendar_event_by_id_returns(),
2789 core_calendar_external
::get_calendar_event_by_id($courseevent->id
)
2794 * User data for testing reading calendar events.
2798 public function test_get_calendar_event_by_id_prevent_read_other_users_events_data_provider(): array {
2799 $syscontext = \context_system
::instance();
2800 $managerrole = 'manager';
2802 [true, false, $syscontext, $managerrole, true],
2803 [false, false, $syscontext, $managerrole, false],
2804 [false, false, null, null, true],
2805 [false, true, null, null, false],
2810 * Prevent user from reading other user's event.
2812 * @covers \core_calendar_external::get_calendar_event_by_id
2813 * @dataProvider test_get_calendar_event_by_id_prevent_read_other_users_events_data_provider
2815 * @param bool $isadminevent Is admin's event
2816 * @param bool $isadmin Is current user admin user
2817 * @param null|stdClass $readerrolecontext Reader role context
2818 * @param null|string $readerrolename Role name
2819 * @param bool $expectexception Should the test throw exception
2821 public function test_get_calendar_event_by_id_prevent_read_other_users_events(
2822 bool $isadminevent, bool $isadmin, ?\stdClass
$readerrolecontext,
2823 ?
string $readerrolename, bool $expectexception) {
2826 $this->resetAfterTest();
2827 $generator = $this->getDataGenerator();
2829 if ($isadminevent) {
2830 $this->setAdminUser();
2832 $user = $generator->create_user();
2833 $this->setUser($user);
2835 $userevent = $this->create_calendar_event('user event', $USER->id
, 'user', 0, time());
2836 $results = \external_api
::clean_returnvalue(
2837 core_calendar_external
::get_calendar_event_by_id_returns(),
2838 core_calendar_external
::get_calendar_event_by_id($userevent->id
)
2840 $event = reset($results);
2841 $this->assertEquals($userevent->id
, $event['id']);
2844 $this->setAdminUser();
2846 $reader = $generator->create_user();
2847 if ($readerrolename && $readerrolecontext) {
2848 $managerroleid = $DB->get_field('role', 'id', ['shortname' => $readerrolename]);
2849 role_assign($managerroleid, $reader->id
, $readerrolecontext->id
);
2851 $this->setUser($reader);
2854 if ($expectexception) {
2855 // Setup if exception is expected for the test.
2856 $this->expectException(\moodle_exception
::class);
2858 \external_api
::clean_returnvalue(
2859 core_calendar_external
::get_calendar_event_by_id_returns(),
2860 core_calendar_external
::get_calendar_event_by_id($userevent->id
)
2865 * User data for testing editing or deleting calendar events.
2869 public function test_edit_or_delete_other_users_events_data_provider(): array {
2870 $syscontext = \context_system
::instance();
2871 $managerrole = 'manager';
2873 [false, false, $syscontext, $managerrole, false],
2874 [false, true, $syscontext, $managerrole, true],
2875 [false, false, null, null, true],
2876 [true, false, null, null, false],
2881 * Test the behavior of deleting other users' user events.
2883 * @dataProvider test_edit_or_delete_other_users_events_data_provider
2884 * @covers \core_calendar_external::delete_calendar_events
2885 * @param bool $isadmin Whether the current user is admin.
2886 * @param bool $isadminevent Whether it's an admin event or not.
2887 * @param stdClass|null $writerrolecontext The reader role context.
2888 * @param string|null $writerrolename The role name.
2889 * @param bool $expectexception Whether the test should throw an exception or not.
2891 public function test_delete_other_users_events(bool $isadmin, bool $isadminevent,
2892 ?\stdClass
$writerrolecontext, ?
string $writerrolename, bool $expectexception) {
2895 $this->resetAfterTest();
2896 $generator = $this->getDataGenerator();
2898 if ($isadminevent) {
2899 $this->setAdminUser();
2902 $user = $generator->create_user();
2903 $this->setUser($user);
2905 $userevent = $this->create_calendar_event('user event', $user->id
, 'user', 0, time());
2908 $this->setAdminUser();
2910 $writer = $generator->create_user();
2911 if ($writerrolename && $writerrolecontext) {
2912 $managerroleid = $DB->get_field('role', 'id', ['shortname' => $writerrolename]);
2913 role_assign($managerroleid, $writer->id
, $writerrolecontext->id
);
2915 $this->setUser($writer);
2918 if ($expectexception) {
2919 $this->expectException(\moodle_exception
::class);
2922 ['eventid' => $userevent->id
, 'repeat' => 0]
2924 core_calendar_external
::delete_calendar_events($events);
2928 * Test the behavior of editing other users' user events
2930 * @dataProvider test_edit_or_delete_other_users_events_data_provider
2931 * @covers \core_calendar_external::submit_create_update_form
2932 * @param bool $isadmin Whether the current user is admin.
2933 * @param bool $isadminevent Whether it's an admin event or not.
2934 * @param stdClass|null $writerrolecontext The reader role context.
2935 * @param string|null $writerrolename The role name.
2936 * @param bool $expectexception Whether the test should throw an exception or not.
2938 public function test_edit_other_users_events(bool $isadmin, bool $isadminevent,
2939 ?\stdClass
$writerrolecontext, ?
string $writerrolename, bool $expectexception) {
2942 $this->resetAfterTest();
2944 $generator = $this->getDataGenerator();
2945 if ($isadminevent) {
2946 $this->setAdminUser();
2949 $user = $generator->create_user();
2954 'userid' => $user->id
,
2958 'eventtype' => 'user',
2972 'location' => 'Test',
2975 $formdata = \core_calendar\local\event\forms\create
::mock_generate_submit_keys($formdata);
2977 $querystring = http_build_query($formdata, '', '&');
2980 $this->setAdminUser();
2982 $writer = $generator->create_user();
2983 if ($writerrolename && $writerrolecontext) {
2984 $managerroleid = $DB->get_field('role', 'id', ['shortname' => $writerrolename]);
2985 role_assign($managerroleid, $writer->id
, $writerrolecontext->id
);
2987 $this->setUser($writer);
2989 $USER->ignoresesskey
= true;
2991 if ($expectexception) {
2992 $this->expectException(\moodle_exception
::class);
2994 core_calendar_external
::submit_create_update_form($querystring);
2998 * A user should not be able load the calendar events for a category they cannot see.
3000 public function test_get_calendar_events_hidden_category() {
3002 $this->resetAfterTest(true);
3003 $this->setAdminUser();
3005 $generator = $this->getDataGenerator();
3006 $user1 = $generator->create_user();
3007 $category = $generator->create_category(['visible' => 0]);
3008 $name = 'Category Event (category: ' . $category->id
. ')';
3009 $record = new \
stdClass();
3010 $record->categoryid
= $category->id
;
3011 $categoryevent = $this->create_calendar_event($name, $USER->id
, 'category', 0, time(), $record);
3014 'eventids' => [$categoryevent->id
]
3017 // Admin can load the category event.
3018 $data = \external_api
::clean_returnvalue(
3019 core_calendar_external
::get_calendar_events_returns(),
3020 core_calendar_external
::get_calendar_events($events, $options)
3022 $this->assertEquals($data['events'][0]['id'], $categoryevent->id
);
3023 // User with no special permission to see hidden categories will not see the event.
3024 $this->setUser($user1);
3025 $data = \external_api
::clean_returnvalue(
3026 core_calendar_external
::get_calendar_events_returns(),
3027 core_calendar_external
::get_calendar_events($events, $options)
3029 $this->assertCount(0, $data['events']);
3030 $this->assertEquals('nopermissions', $data['warnings'][0]['warningcode']);
3034 * Test get_calendar_access_information for admins.
3036 public function test_get_calendar_access_information_for_admins() {
3038 $this->resetAfterTest(true);
3039 $this->setAdminUser();
3041 $CFG->calendar_adminseesall
= 1;
3043 $data = \external_api
::clean_returnvalue(
3044 core_calendar_external
::get_calendar_access_information_returns(),
3045 core_calendar_external
::get_calendar_access_information()
3047 $this->assertTrue($data['canmanageownentries']);
3048 $this->assertTrue($data['canmanagegroupentries']);
3049 $this->assertTrue($data['canmanageentries']);
3053 * Test get_calendar_access_information for authenticated users.
3055 public function test_get_calendar_access_information_for_authenticated_users() {
3056 $this->resetAfterTest(true);
3057 $this->setUser($this->getDataGenerator()->create_user());
3059 $data = \external_api
::clean_returnvalue(
3060 core_calendar_external
::get_calendar_access_information_returns(),
3061 core_calendar_external
::get_calendar_access_information()
3063 $this->assertTrue($data['canmanageownentries']);
3064 $this->assertFalse($data['canmanagegroupentries']);
3065 $this->assertFalse($data['canmanageentries']);
3069 * Test get_calendar_access_information for student users.
3071 public function test_get_calendar_access_information_for_student_users() {
3073 $this->resetAfterTest(true);
3075 $user = $this->getDataGenerator()->create_user();
3076 $course = $this->getDataGenerator()->create_course();
3077 $role = $DB->get_record('role', array('shortname' => 'student'));
3078 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
3080 $this->setUser($user);
3082 $data = \external_api
::clean_returnvalue(
3083 core_calendar_external
::get_calendar_access_information_returns(),
3084 core_calendar_external
::get_calendar_access_information($course->id
)
3086 $this->assertTrue($data['canmanageownentries']);
3087 $this->assertFalse($data['canmanagegroupentries']);
3088 $this->assertFalse($data['canmanageentries']);
3092 * Test get_calendar_access_information for teacher users.
3094 public function test_get_calendar_access_information_for_teacher_users() {
3096 $this->resetAfterTest(true);
3098 $user = $this->getDataGenerator()->create_user();
3099 $course = $this->getDataGenerator()->create_course(['groupmode' => 1]);
3100 $role = $DB->get_record('role', array('shortname' => 'editingteacher'));
3101 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
3102 $this->getDataGenerator()->create_group(['courseid' => $course->id
]);
3104 $this->setUser($user);
3106 $data = \external_api
::clean_returnvalue(
3107 core_calendar_external
::get_calendar_access_information_returns(),
3108 core_calendar_external
::get_calendar_access_information($course->id
)
3110 $this->assertTrue($data['canmanageownentries']);
3111 $this->assertTrue($data['canmanagegroupentries']);
3112 $this->assertTrue($data['canmanageentries']);
3116 * Test get_allowed_event_types for admins.
3118 public function test_get_allowed_event_types_for_admins() {
3120 $this->resetAfterTest(true);
3121 $this->setAdminUser();
3122 $CFG->calendar_adminseesall
= 1;
3123 $data = \external_api
::clean_returnvalue(
3124 core_calendar_external
::get_allowed_event_types_returns(),
3125 core_calendar_external
::get_allowed_event_types()
3127 $this->assertEquals(['user', 'site', 'course', 'category'], $data['allowedeventtypes']);
3130 * Test get_allowed_event_types for authenticated users.
3132 public function test_get_allowed_event_types_for_authenticated_users() {
3133 $this->resetAfterTest(true);
3134 $this->setUser($this->getDataGenerator()->create_user());
3135 $data = \external_api
::clean_returnvalue(
3136 core_calendar_external
::get_allowed_event_types_returns(),
3137 core_calendar_external
::get_allowed_event_types()
3139 $this->assertEquals(['user'], $data['allowedeventtypes']);
3142 * Test get_allowed_event_types for student users.
3144 public function test_get_allowed_event_types_for_student_users() {
3146 $this->resetAfterTest(true);
3147 $user = $this->getDataGenerator()->create_user();
3148 $course = $this->getDataGenerator()->create_course();
3149 $role = $DB->get_record('role', array('shortname' => 'student'));
3150 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
3151 $this->setUser($user);
3152 $data = \external_api
::clean_returnvalue(
3153 core_calendar_external
::get_allowed_event_types_returns(),
3154 core_calendar_external
::get_allowed_event_types($course->id
)
3156 $this->assertEquals(['user'], $data['allowedeventtypes']);
3159 * Test get_allowed_event_types for teacher users.
3161 public function test_get_allowed_event_types_for_teacher_users() {
3163 $this->resetAfterTest(true);
3164 $user = $this->getDataGenerator()->create_user();
3165 $course = $this->getDataGenerator()->create_course(['groupmode' => 1]);
3166 $role = $DB->get_record('role', array('shortname' => 'editingteacher'));
3167 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $role->id
);
3168 $this->getDataGenerator()->create_group(['courseid' => $course->id
]);
3169 $this->setUser($user);
3170 $data = \external_api
::clean_returnvalue(
3171 core_calendar_external
::get_allowed_event_types_returns(),
3172 core_calendar_external
::get_allowed_event_types($course->id
)
3174 $this->assertEquals(['user', 'course', 'group'], $data['allowedeventtypes']);
3178 * Test get_timestamps with string keys, with and without optional hour/minute values.
3180 public function test_get_timestamps_string_keys() {
3181 $this->resetAfterTest(true);
3182 $this->setAdminUser();
3184 $time1 = new \
DateTime('2018-12-30 00:00:00');
3185 $time2 = new \
DateTime('2019-03-27 23:59:00');
3190 'year' => $time1->format('Y'),
3191 'month' => $time1->format('m'),
3192 'day' => $time1->format('d'),
3196 'year' => $time2->format('Y'),
3197 'month' => (int) $time2->format('m'),
3198 'day' => $time2->format('d'),
3199 'hour' => $time2->format('H'),
3200 'minute' => $time2->format('i'),
3204 $expectedtimestamps = [
3205 'from' => $time1->getTimestamp(),
3206 'to' => $time2->getTimestamp(),
3209 $result = core_calendar_external
::get_timestamps($dates);
3211 $this->assertEquals(['timestamps'], array_keys($result));
3212 $this->assertEquals(2, count($result['timestamps']));
3214 foreach ($result['timestamps'] as $data) {
3215 $this->assertTrue(in_array($data['key'], ['from', 'to']));
3216 $this->assertEquals($expectedtimestamps[$data['key']], $data['timestamp']);
3221 * Test get_timestamps with no keys specified, with and without optional hour/minute values.
3223 public function test_get_timestamps_no_keys() {
3224 $this->resetAfterTest(true);
3225 $this->setAdminUser();
3227 $time1 = new \
DateTime('2018-12-30 00:00:00');
3228 $time2 = new \
DateTime('2019-03-27 23:59:00');
3232 'year' => $time1->format('Y'),
3233 'month' => $time1->format('m'),
3234 'day' => $time1->format('d'),
3237 'year' => $time2->format('Y'),
3238 'month' => (int) $time2->format('m'),
3239 'day' => $time2->format('d'),
3240 'hour' => $time2->format('H'),
3241 'minute' => $time2->format('i'),
3245 $expectedtimestamps = [
3246 0 => $time1->getTimestamp(),
3247 1 => $time2->getTimestamp(),
3250 $result = core_calendar_external
::get_timestamps($dates);
3252 $this->assertEquals(['timestamps'], array_keys($result));
3253 $this->assertEquals(2, count($result['timestamps']));
3255 foreach ($result['timestamps'] as $data) {
3256 $this->assertEquals($expectedtimestamps[$data['key']], $data['timestamp']);