Merge branch 'MDL-76073-master' of https://github.com/marinaglancy/moodle
[moodle.git] / calendar / tests / externallib_test.php
blobfebd9a484cc146cfe56001331276140c013c3415
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
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();
24 global $CFG;
26 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
28 /**
29 * External course functions unit tests
31 * @package core_calendar
32 * @category external
33 * @copyright 2012 Ankit Agarwal
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 * @since Moodle 2.5
37 class externallib_test extends externallib_advanced_testcase {
39 /**
40 * Tests set up
42 protected function setUp(): void {
43 global $CFG;
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;
57 * @since Moodle 2.5
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");
64 if (!empty($prop)) {
65 if (is_array($prop)) {
66 $prop = (object)$prop;
68 } else {
69 $prop = new \stdClass();
71 $prop->name = $name;
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)) {
85 $prop->timesort = 0;
87 if (empty($prop->type)) {
88 $prop->type = CALENDAR_EVENT_TYPE_STANDARD;
90 if (empty($prop->repeats)) {
91 $prop->repeat = 0;
92 } else {
93 $prop->repeat = 1;
95 if (empty($prop->userid)) {
96 if (!empty($userid)) {
97 $prop->userid = $userid;
98 } else {
99 $prop->userid = 0;
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.
106 $prop->courseid = 0;
107 } else {
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);
122 $priority = 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 () {
137 global $DB, $USER;
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() {
165 global $DB, $USER;
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.
191 $events = array(
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);
221 // Remove all caps.
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);
229 $events = array(
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);
238 $events = array(
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);
247 $events = array(
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);
256 $events = array(
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();
280 $events = array(
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() {
294 global $DB, $USER;
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);
326 $filerecord = array(
327 'contextid' => $usercontext->id,
328 'component' => 'user',
329 'filearea' => 'draft',
330 'itemid' => $draftidfile,
331 'filepath' => '/',
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'])) {
379 $withdescription++;
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);
484 // Expect one less.
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() {
551 global $USER;
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.
602 $events = array (
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;
622 $events = array (
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
665 * be return.
667 * If there are no events on or after the given time then an empty result set should
668 * be returned.
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);
680 $params = [
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(),
699 $result
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(),
714 $result
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(),
726 $result
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
745 * returned.
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);
757 $params = [
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(),
776 $result
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(),
791 $result
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(),
804 $result
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();
835 $params = [
836 'type' => CALENDAR_EVENT_TYPE_ACTION,
837 'modulename' => 'assign',
838 'instance' => $moduleinstance->id,
841 $now = time();
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
888 * returned.
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);
900 $params = [
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(),
919 $result
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(),
934 $result
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
948 * returned.
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);
960 $params = [
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(),
979 $result
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(),
992 $result
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(),
1005 $result
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]}'
1061 // Enrol.
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
1095 * be returned.
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]);
1104 $records = [];
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),
1116 $user->id,
1117 'user',
1121 'type' => CALENDAR_EVENT_TYPE_ACTION,
1122 'courseid' => $courseid,
1123 'timesort' => $i,
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(),
1133 $result
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(),
1146 $result
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
1159 * returned.
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]);
1168 $records = [];
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),
1180 $user->id,
1181 'user',
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(),
1197 $result
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(),
1210 $result
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
1220 * (inclusive).
1222 * If there are no events in the given time range then an empty result set should be
1223 * returned.
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]);
1232 $records = [];
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),
1244 $user->id,
1245 'user',
1249 'type' => CALENDAR_EVENT_TYPE_ACTION,
1250 'courseid' => $courseid,
1251 'timesort' => $i,
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(),
1261 $result
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(),
1274 $result
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
1288 * returned.
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]);
1297 $records = [];
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),
1309 $user->id,
1310 'user',
1314 'type' => CALENDAR_EVENT_TYPE_ACTION,
1315 'courseid' => $courseid,
1316 'timesort' => $i,
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(),
1327 $result
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(),
1339 $result
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(),
1351 $result
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() {
1362 // Generate data.
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]);
1368 // Enrol.
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),
1376 $user->id,
1377 'user',
1381 'type' => CALENDAR_EVENT_TYPE_ACTION,
1382 'courseid' => $course->id,
1383 'timesort' => $i,
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(),
1394 $result
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(),
1403 $result
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(),
1413 $result
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]);
1436 $records = [];
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++) {
1454 if ($i < 3) {
1455 $courseid = $course1->id;
1456 $instance = $instance1->id;
1457 } else if ($i < 6) {
1458 $courseid = $course2->id;
1459 $instance = $instance2->id;
1460 } else {
1461 $courseid = $course3->id;
1462 $instance = $instance3->id;
1465 $records[] = $this->create_calendar_event(
1466 sprintf('Event %d', $i),
1467 $user->id,
1468 'user',
1472 'type' => CALENDAR_EVENT_TYPE_ACTION,
1473 'courseid' => $courseid,
1474 'timesort' => $i,
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(),
1484 $result
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(),
1493 $result
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(),
1503 $result
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(),
1515 $result
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(),
1531 $result
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(),
1546 $result
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() {
1561 // Generate data.
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++) {
1588 if ($i < 3) {
1589 $courseid = $course1->id;
1590 $instance = $instance1->id;
1591 } else if ($i < 6) {
1592 $courseid = $course2->id;
1593 $instance = $instance2->id;
1594 } else {
1595 $courseid = $course3->id;
1596 $instance = $instance3->id;
1599 $records[] = $this->create_calendar_event(
1600 sprintf('Event %d', $i),
1601 $user->id,
1602 'user',
1606 'type' => CALENDAR_EVENT_TYPE_ACTION,
1607 'courseid' => $courseid,
1608 'timesort' => $i,
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(),
1620 $result
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(),
1633 $result
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(),
1648 $result
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);
1674 $params = [];
1675 foreach ($events as $event) {
1676 $params[] = [
1677 'eventid' => $event->id,
1678 'repeat' => false
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(
1706 'Test event',
1707 $user->id,
1708 'user',
1710 null,
1712 'courseid' => 0,
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(),
1720 $result
1723 $this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);
1727 * A user should not be able to edit an event that they don't have
1728 * capabilities for.
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(
1746 'Test event',
1747 $user->id,
1748 'user',
1750 null,
1752 'courseid' => 0,
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(),
1762 $result
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(
1788 'Test event',
1789 $user->id,
1790 'user',
1792 null,
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(),
1806 $result
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);
1820 $formdata = [
1821 'id' => 0,
1822 'userid' => $user->id,
1823 'modulename' => '',
1824 'instance' => 0,
1825 'visible' => 1,
1826 'name' => 'Test',
1827 'timestart' => [
1828 'day' => $timestart->format('j'),
1829 'month' => $timestart->format('n'),
1830 'year' => $timestart->format('Y'),
1831 'hour' => $timestart->format('G'),
1832 'minute' => 0,
1834 'eventtype' => 'user',
1835 'description' => [
1836 'text' => '',
1837 'format' => 1,
1839 'location' => 'Test',
1840 'duration' => 1,
1841 'timedurationuntil' => [
1842 'day' => $timedurationuntil->format('j'),
1843 'month' => $timedurationuntil->format('n'),
1844 'year' => $timedurationuntil->format('Y'),
1845 'hour' => $timedurationuntil->format('G'),
1846 'minute' => 0,
1850 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1852 $querystring = http_build_query($formdata, '', '&amp;');
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);
1878 $formdata = [
1879 'id' => 0,
1880 'userid' => $user->id,
1881 'modulename' => '',
1882 'instance' => 0,
1883 'visible' => 1,
1884 'name' => 'Test',
1885 'timestart' => [
1886 'day' => $timestart->format('j'),
1887 'month' => $timestart->format('n'),
1888 'year' => $timestart->format('Y'),
1889 'hour' => $timestart->format('G'),
1890 'minute' => 0,
1892 'eventtype' => 'user',
1893 'description' => [
1894 'text' => '',
1895 'format' => 1,
1896 'itemid' => 0
1898 'location' => 'Test',
1899 'duration' => 1,
1900 'timedurationuntil' => [
1901 'day' => $timedurationuntil->format('j'),
1902 'month' => $timedurationuntil->format('n'),
1903 'year' => $timedurationuntil->format('Y'),
1904 'hour' => $timedurationuntil->format('G'),
1905 'minute' => 0,
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);
1943 $formdata = [
1944 'id' => 0,
1945 'userid' => $user->id,
1946 'modulename' => '',
1947 'instance' => 0,
1948 'visible' => 1,
1949 'name' => 'Test',
1950 'timestart' => [
1951 'day' => $timestart->format('j'),
1952 'month' => $timestart->format('n'),
1953 'year' => $timestart->format('Y'),
1954 'hour' => $timestart->format('G'),
1955 'minute' => 0,
1957 'eventtype' => 'user',
1958 'description' => [
1959 'text' => '',
1960 'format' => 1,
1962 'location' => 'Test',
1963 'duration' => 1,
1964 'timedurationuntil' => [
1965 'day' => $timedurationuntil->format('j'),
1966 'month' => $timedurationuntil->format('n'),
1967 'year' => $timedurationuntil->format('Y'),
1968 'hour' => $timedurationuntil->format('G'),
1969 'minute' => 0,
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);
2004 $formdata = [
2005 'id' => 0,
2006 'userid' => $user->id,
2007 'modulename' => '',
2008 'instance' => 0,
2009 'visible' => 1,
2010 'name' => 'Test',
2011 'timestart' => [
2012 'day' => $timestart->format('j'),
2013 'month' => $timestart->format('n'),
2014 'year' => $timestart->format('Y'),
2015 'hour' => $timestart->format('G'),
2016 'minute' => 0,
2018 'eventtype' => 'site',
2019 'description' => [
2020 'text' => '',
2021 'format' => 1,
2022 'itemid' => 0
2024 'location' => 'Test',
2025 'duration' => 1,
2026 'timedurationuntil' => [
2027 'day' => $timedurationuntil->format('j'),
2028 'month' => $timedurationuntil->format('n'),
2029 'year' => $timedurationuntil->format('Y'),
2030 'hour' => $timedurationuntil->format('G'),
2031 'minute' => 0,
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);
2070 $formdata = [
2071 'id' => 0,
2072 'userid' => $user->id,
2073 'modulename' => '',
2074 'instance' => 0,
2075 'visible' => 1,
2076 'name' => 'Test',
2077 'timestart' => [
2078 'day' => $timestart->format('j'),
2079 'month' => $timestart->format('n'),
2080 'year' => $timestart->format('Y'),
2081 'hour' => $timestart->format('G'),
2082 'minute' => 0,
2084 'eventtype' => 'site',
2085 'description' => [
2086 'text' => '',
2087 'format' => 1,
2089 'location' => 'Test',
2090 'duration' => 1,
2091 'timedurationuntil' => [
2092 'day' => $timedurationuntil->format('j'),
2093 'month' => $timedurationuntil->format('n'),
2094 'year' => $timedurationuntil->format('Y'),
2095 'hour' => $timedurationuntil->format('G'),
2096 'minute' => 0,
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);
2133 $formdata = [
2134 'id' => 0,
2135 'userid' => $user->id,
2136 'modulename' => '',
2137 'instance' => 0,
2138 'visible' => 1,
2139 'name' => 'Test',
2140 'timestart' => [
2141 'day' => $timestart->format('j'),
2142 'month' => $timestart->format('n'),
2143 'year' => $timestart->format('Y'),
2144 'hour' => $timestart->format('G'),
2145 'minute' => 0,
2147 'eventtype' => 'course',
2148 'courseid' => $course->id,
2149 'description' => [
2150 'text' => '',
2151 'format' => 1,
2152 'itemid' => 0,
2154 'location' => 'Test',
2155 'duration' => 1,
2156 'timedurationuntil' => [
2157 'day' => $timedurationuntil->format('j'),
2158 'month' => $timedurationuntil->format('n'),
2159 'year' => $timedurationuntil->format('Y'),
2160 'hour' => $timedurationuntil->format('G'),
2161 'minute' => 0,
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);
2203 $formdata = [
2204 'id' => 0,
2205 'userid' => $user->id,
2206 'modulename' => '',
2207 'instance' => 0,
2208 'visible' => 1,
2209 'name' => 'Test',
2210 'timestart' => [
2211 'day' => $timestart->format('j'),
2212 'month' => $timestart->format('n'),
2213 'year' => $timestart->format('Y'),
2214 'hour' => $timestart->format('G'),
2215 'minute' => 0,
2217 'eventtype' => 'course',
2218 'courseid' => $course->id,
2219 'description' => [
2220 'text' => '',
2221 'format' => 1,
2223 'location' => 'Test',
2224 'duration' => 1,
2225 'timedurationuntil' => [
2226 'day' => $timedurationuntil->format('j'),
2227 'month' => $timedurationuntil->format('n'),
2228 'year' => $timedurationuntil->format('Y'),
2229 'hour' => $timedurationuntil->format('G'),
2230 'minute' => 0,
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
2256 * not enrolled in.
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);
2269 $formdata = [
2270 'id' => 0,
2271 'userid' => $user->id,
2272 'modulename' => '',
2273 'instance' => 0,
2274 'visible' => 1,
2275 'name' => 'Test',
2276 'timestart' => [
2277 'day' => $timestart->format('j'),
2278 'month' => $timestart->format('n'),
2279 'year' => $timestart->format('Y'),
2280 'hour' => $timestart->format('G'),
2281 'minute' => 0,
2283 'eventtype' => 'course',
2284 'courseid' => $course2->id, // Not enrolled.
2285 'description' => [
2286 'text' => '',
2287 'format' => 1,
2289 'location' => 'Test',
2290 'duration' => 1,
2291 'timedurationuntil' => [
2292 'day' => $timedurationuntil->format('j'),
2293 'month' => $timedurationuntil->format('n'),
2294 'year' => $timedurationuntil->format('Y'),
2295 'hour' => $timedurationuntil->format('G'),
2296 'minute' => 0,
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);
2335 $formdata = [
2336 'id' => 0,
2337 'userid' => $user->id,
2338 'modulename' => '',
2339 'instance' => 0,
2340 'visible' => 1,
2341 'name' => 'Test',
2342 'timestart' => [
2343 'day' => $timestart->format('j'),
2344 'month' => $timestart->format('n'),
2345 'year' => $timestart->format('Y'),
2346 'hour' => $timestart->format('G'),
2347 'minute' => 0,
2349 'eventtype' => 'group',
2350 'groupid' => $group->id,
2351 'groupcourseid' => $course->id,
2352 'description' => [
2353 'text' => '',
2354 'format' => 1,
2355 'itemid' => 0
2357 'location' => 'Test',
2358 'duration' => 1,
2359 'timedurationuntil' => [
2360 'day' => $timedurationuntil->format('j'),
2361 'month' => $timedurationuntil->format('n'),
2362 'year' => $timedurationuntil->format('Y'),
2363 'hour' => $timedurationuntil->format('G'),
2364 'minute' => 0,
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);
2408 $formdata = [
2409 'id' => 0,
2410 'userid' => $user->id,
2411 'modulename' => '',
2412 'instance' => 0,
2413 'visible' => 1,
2414 'name' => 'Test',
2415 'timestart' => [
2416 'day' => $timestart->format('j'),
2417 'month' => $timestart->format('n'),
2418 'year' => $timestart->format('Y'),
2419 'hour' => $timestart->format('G'),
2420 'minute' => 0,
2422 'eventtype' => 'group',
2423 'groupid' => $group->id,
2424 'groupcourseid' => $course->id,
2425 'description' => [
2426 'text' => '',
2427 'format' => 1,
2428 'itemid' => 0
2430 'location' => 'Test',
2431 'duration' => 1,
2432 'timedurationuntil' => [
2433 'day' => $timedurationuntil->format('j'),
2434 'month' => $timedurationuntil->format('n'),
2435 'year' => $timedurationuntil->format('Y'),
2436 'hour' => $timedurationuntil->format('G'),
2437 'minute' => 0,
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);
2482 $formdata = [
2483 'id' => 0,
2484 'userid' => $user->id,
2485 'modulename' => '',
2486 'instance' => 0,
2487 'visible' => 1,
2488 'name' => 'Test',
2489 'timestart' => [
2490 'day' => $timestart->format('j'),
2491 'month' => $timestart->format('n'),
2492 'year' => $timestart->format('Y'),
2493 'hour' => $timestart->format('G'),
2494 'minute' => 0,
2496 'eventtype' => 'group',
2497 'groupid' => $group->id,
2498 'groupcourseid' => $course->id,
2499 'description' => [
2500 'text' => '',
2501 'format' => 1,
2502 'itemid' => 0
2504 'location' => 'Test',
2505 'duration' => 1,
2506 'timedurationuntil' => [
2507 'day' => $timedurationuntil->format('j'),
2508 'month' => $timedurationuntil->format('n'),
2509 'year' => $timedurationuntil->format('Y'),
2510 'hour' => $timedurationuntil->format('G'),
2511 'minute' => 0,
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);
2556 $formdata = [
2557 'id' => 0,
2558 'userid' => $user->id,
2559 'modulename' => '',
2560 'instance' => 0,
2561 'visible' => 1,
2562 'name' => 'Test',
2563 'timestart' => [
2564 'day' => $timestart->format('j'),
2565 'month' => $timestart->format('n'),
2566 'year' => $timestart->format('Y'),
2567 'hour' => $timestart->format('G'),
2568 'minute' => 0,
2570 'eventtype' => 'group',
2571 'groupid' => $group->id,
2572 'groupcourseid' => $course->id,
2573 'description' => [
2574 'text' => '',
2575 'format' => 1,
2577 'location' => 'Test',
2578 'duration' => 1,
2579 'timedurationuntil' => [
2580 'day' => $timedurationuntil->format('j'),
2581 'month' => $timedurationuntil->format('n'),
2582 'year' => $timedurationuntil->format('Y'),
2583 'hour' => $timedurationuntil->format('G'),
2584 'minute' => 0,
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() {
2613 global $USER;
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() {
2673 global $USER;
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() {
2717 global $USER;
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() {
2757 global $USER;
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.
2796 * @return array
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';
2801 return [
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) {
2824 global $USER, $DB;
2826 $this->resetAfterTest();
2827 $generator = $this->getDataGenerator();
2829 if ($isadminevent) {
2830 $this->setAdminUser();
2831 } else {
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']);
2843 if ($isadmin) {
2844 $this->setAdminUser();
2845 } else {
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.
2867 * @return array
2869 public function test_edit_or_delete_other_users_events_data_provider(): array {
2870 $syscontext = \context_system::instance();
2871 $managerrole = 'manager';
2872 return [
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) {
2893 global $DB, $USER;
2895 $this->resetAfterTest();
2896 $generator = $this->getDataGenerator();
2898 if ($isadminevent) {
2899 $this->setAdminUser();
2900 $user = $USER;
2901 } else {
2902 $user = $generator->create_user();
2903 $this->setUser($user);
2905 $userevent = $this->create_calendar_event('user event', $user->id, 'user', 0, time());
2907 if ($isadmin) {
2908 $this->setAdminUser();
2909 } else {
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);
2921 $events = [
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) {
2940 global $DB, $USER;
2942 $this->resetAfterTest();
2944 $generator = $this->getDataGenerator();
2945 if ($isadminevent) {
2946 $this->setAdminUser();
2947 $user = $USER;
2948 } else {
2949 $user = $generator->create_user();
2952 $formdata = [
2953 'id' => 0,
2954 'userid' => $user->id,
2955 'modulename' => '',
2956 'instance' => 0,
2957 'visible' => 1,
2958 'eventtype' => 'user',
2959 'name' => 'Test',
2960 'timestart' => [
2961 'day' => 1,
2962 'month' => 1,
2963 'year' => 2021,
2964 'hour' => 1,
2965 'minute' => 0,
2967 'description' => [
2968 'text' => 'xxxxx',
2969 'format' => 1,
2970 'itemid' => 0
2972 'location' => 'Test',
2973 'duration' => 0,
2975 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2977 $querystring = http_build_query($formdata, '', '&');
2979 if ($isadmin) {
2980 $this->setAdminUser();
2981 } else {
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() {
3001 global $USER;
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);
3013 $events = [
3014 'eventids' => [$categoryevent->id]
3016 $options = [];
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() {
3037 global $CFG;
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() {
3072 global $DB;
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() {
3095 global $DB;
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() {
3119 global $CFG;
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() {
3145 global $DB;
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() {
3162 global $DB;
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');
3187 $dates = [
3189 'key' => 'from',
3190 'year' => $time1->format('Y'),
3191 'month' => $time1->format('m'),
3192 'day' => $time1->format('d'),
3195 'key' => 'to',
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');
3230 $dates = [
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']);