MDL-60628 calendar: amend web service unit test
[moodle.git] / calendar / tests / externallib_test.php
blob2eb0f3401742edb48945462cafe630a1fc391221
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 /**
18 * External calendar functions unit tests
20 * @package core_calendar
21 * @category external
22 * @copyright 2012 Ankit Agarwal
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
32 /**
33 * External course functions unit tests
35 * @package core_calendar
36 * @category external
37 * @copyright 2012 Ankit Agarwal
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 * @since Moodle 2.5
41 class core_calendar_externallib_testcase extends externallib_advanced_testcase {
43 /**
44 * Tests set up
46 protected function setUp() {
47 global $CFG;
48 require_once($CFG->dirroot . '/calendar/externallib.php');
51 /** Create calendar events or update them
52 * Set $prop->id, if you want to do an update instead of creating an new event
54 * @param string $name Event title
55 * @param int $userid User id
56 * @param string $type Event type
57 * @param int $repeats Number of repeated events to create
58 * @param int $timestart Time stamp of the event start
59 * @param mixed $prop List of event properties as array or object
60 * @return mixed Event object or false;
61 * @since Moodle 2.5
64 public static function create_calendar_event($name, $userid = 0, $type = 'user', $repeats = 0, $timestart = null, $prop = null) {
65 global $CFG, $DB, $SITE;
67 require_once("$CFG->dirroot/calendar/lib.php");
68 if (!empty($prop)) {
69 if (is_array($prop)) {
70 $prop = (object)$prop;
72 } else {
73 $prop = new stdClass();
75 $prop->name = $name;
76 if (empty($prop->eventtype)) {
77 $prop->eventtype = $type;
79 if (empty($prop->repeats)) {
80 $prop->repeats = $repeats;
82 if (empty($prop->timestart)) {
83 $prop->timestart = time();
85 if (empty($prop->timeduration)) {
86 $prop->timeduration = 0;
88 if (empty($prop->timesort)) {
89 $prop->timesort = 0;
91 if (empty($prop->type)) {
92 $prop->type = CALENDAR_EVENT_TYPE_STANDARD;
94 if (empty($prop->repeats)) {
95 $prop->repeat = 0;
96 } else {
97 $prop->repeat = 1;
99 if (empty($prop->userid)) {
100 if (!empty($userid)) {
101 $prop->userid = $userid;
102 } else {
103 $prop->userid = 0;
106 if (!isset($prop->courseid)) {
107 $prop->courseid = $SITE->id;
110 // Determine event priority.
111 if ($prop->courseid == 0 && isset($prop->groupid) && $prop->groupid == 0 && !empty($prop->userid)) {
112 // User override event.
113 $prop->priority = CALENDAR_EVENT_USER_OVERRIDE_PRIORITY;
114 } else if ($prop->courseid != $SITE->id && !empty($prop->groupid)) {
115 // Group override event.
116 $priorityparams = ['courseid' => $prop->courseid, 'groupid' => $prop->groupid];
117 // Group override event with the highest priority.
118 $groupevents = $DB->get_records('event', $priorityparams, 'priority DESC', 'id, priority', 0, 1);
119 $priority = 1;
120 if (!empty($groupevents)) {
121 $event = reset($groupevents);
122 if (!empty($event->priority)) {
123 $priority = $event->priority + 1;
126 $prop->priority = $priority;
129 $event = new calendar_event($prop);
130 return $event->create($prop);
133 public function test_create_calendar_events () {
134 global $DB, $USER;
136 $this->setAdminUser();
137 $this->resetAfterTest();
138 $prevcount = count($DB->get_records("event"));
140 // Create a few events and do asserts.
141 $this->create_calendar_event('test', $USER->id);
142 $where = $DB->sql_compare_text('name') ." = ?";
143 $count = count($DB->get_records_select("event", $where, array('test')));
144 $this->assertEquals(1, $count);
145 $aftercount = count($DB->get_records("event"));
146 $this->assertEquals($prevcount + 1, $aftercount);
148 $this->create_calendar_event('user', $USER->id, 'user', 3);
149 $where = $DB->sql_compare_text('name') ." = ?";
150 $count = count($DB->get_records_select("event", $where, array('user')));
152 $this->assertEquals(3, $count);
153 $aftercount = count($DB->get_records("event"));
154 $this->assertEquals($prevcount + 4, $aftercount);
159 * Test delete_calendar_events
161 * @expectedException moodle_exception
163 public function test_delete_calendar_events() {
164 global $DB, $USER;
166 $this->resetAfterTest(true);
167 $this->setAdminUser();
169 // Create a few stuff to test with.
170 $user = $this->getDataGenerator()->create_user();
171 $course = $this->getDataGenerator()->create_course();
172 $record = new stdClass();
173 $record->courseid = $course->id;
174 $group = $this->getDataGenerator()->create_group($record);
176 $notdeletedcount = $DB->count_records('event');
178 // Let's create a few events.
179 $siteevent = $this->create_calendar_event('site', $USER->id, 'site');
180 $record = new stdClass();
181 $record->courseid = $course->id;
182 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record);
183 $userevent = $this->create_calendar_event('user', $USER->id);
184 $record = new stdClass();
185 $record->courseid = $course->id;
186 $record->groupid = $group->id;
187 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);
189 // Now lets try to delete stuff with proper rights.
190 $events = array(
191 array('eventid' => $siteevent->id, 'repeat' => 0),
192 array('eventid' => $courseevent->id, 'repeat' => 1),
193 array('eventid' => $userevent->id, 'repeat' => 0),
194 array('eventid' => $groupevent->id, 'repeat' => 0)
196 core_calendar_external::delete_calendar_events($events);
198 // Check to see if things were deleted properly.
199 $deletedcount = $DB->count_records('event');
200 $this->assertEquals($notdeletedcount, $deletedcount);
202 // Let's create a few events.
203 $siteevent = $this->create_calendar_event('site', $USER->id, 'site');
204 $record = new stdClass();
205 $record->courseid = $course->id;
206 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 3, time(), $record);
207 $userevent = $this->create_calendar_event('user', $USER->id);
208 $record = new stdClass();
209 $record->courseid = $course->id;
210 $record->groupid = $group->id;
211 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);
213 $this->setuser($user);
214 $sitecontext = context_system::instance();
215 $coursecontext = context_course::instance($course->id);
216 $usercontext = context_user::instance($user->id);
217 $role = $DB->get_record('role', array('shortname' => 'student'));
218 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
220 // Remove all caps.
221 $this->unassignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);
222 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
223 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
224 $this->unassignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id);
226 // Assign proper caps and attempt delete.
227 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);
228 $events = array(
229 array('eventid' => $siteevent->id, 'repeat' => 0),
231 core_calendar_external::delete_calendar_events($events);
232 $deletedcount = $DB->count_records('event');
233 $count = $notdeletedcount+5;
234 $this->assertEquals($count, $deletedcount);
236 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);
237 $events = array(
238 array('eventid' => $courseevent->id, 'repeat' => 0),
240 core_calendar_external::delete_calendar_events($events);
241 $deletedcount = $DB->count_records('event');
242 $count = $notdeletedcount+4;
243 $this->assertEquals($count, $deletedcount);
245 $this->assignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id);
246 $events = array(
247 array('eventid' => $userevent->id, 'repeat' => 0),
249 core_calendar_external::delete_calendar_events($events);
250 $deletedcount = $DB->count_records('event');
251 $count = $notdeletedcount+3;
252 $this->assertEquals($count, $deletedcount);
254 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
255 $events = array(
256 array('eventid' => $groupevent->id, 'repeat' => 0),
258 core_calendar_external::delete_calendar_events($events);
259 $deletedcount = $DB->count_records('event');
260 $count = $notdeletedcount+2;
261 $this->assertEquals($count, $deletedcount);
263 $notdeletedcount = $deletedcount;
265 // Let us try deleting without caps.
267 $siteevent = $this->create_calendar_event('site', $USER->id, 'site');
268 $record = new stdClass();
269 $record->courseid = $course->id;
270 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 3, time(), $record);
271 $userevent = $this->create_calendar_event('user', $USER->id);
272 $record = new stdClass();
273 $record->courseid = $course->id;
274 $record->groupid = $group->id;
275 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);
277 $this->setGuestUser();
279 $events = array(
280 array('eventid' => $siteevent->id, 'repeat' => 0),
281 array('eventid' => $courseevent->id, 'repeat' => 0),
282 array('eventid' => $userevent->id, 'repeat' => 0),
283 array('eventid' => $groupevent->id, 'repeat' => 0)
285 core_calendar_external::delete_calendar_events($events);
289 * Test get_calendar_events
291 public function test_get_calendar_events() {
292 global $DB, $USER;
294 $this->resetAfterTest(true);
295 set_config('calendar_adminseesall', 1);
296 $this->setAdminUser();
298 // Create a few stuff to test with.
299 $user = $this->getDataGenerator()->create_user();
300 $user2 = $this->getDataGenerator()->create_user();
301 $course = $this->getDataGenerator()->create_course();
303 $category = $this->getDataGenerator()->create_category();
305 $category2 = $this->getDataGenerator()->create_category();
306 $category2b = $this->getDataGenerator()->create_category(['parent' => $category2->id]);
307 $course3 = $this->getDataGenerator()->create_course(['category' => $category2b->id]);
309 $role = $DB->get_record('role', array('shortname' => 'student'));
310 $this->getDataGenerator()->enrol_user($user2->id, $course3->id, $role->id);
312 $record = new stdClass();
313 $record->courseid = $course->id;
314 $group = $this->getDataGenerator()->create_group($record);
316 $beforecount = $DB->count_records('event');
318 // Let's create a few events.
319 $siteevent = $this->create_calendar_event('site', $USER->id, 'site');
321 // This event will have description with an inline fake image.
322 $draftidfile = file_get_unused_draft_itemid();
323 $usercontext = context_course::instance($course->id);
324 $filerecord = array(
325 'contextid' => $usercontext->id,
326 'component' => 'user',
327 'filearea' => 'draft',
328 'itemid' => $draftidfile,
329 'filepath' => '/',
330 'filename' => 'fakeimage.png',
332 $fs = get_file_storage();
333 $fs->create_file_from_string($filerecord, 'img contents');
335 $record = new stdClass();
336 $record->courseid = $course->id;
337 $record->groupid = 0;
338 $record->description = array(
339 'format' => FORMAT_HTML,
340 'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">',
341 'itemid' => $draftidfile
343 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record);
345 $record = new stdClass();
346 $record->courseid = 0;
347 $record->groupid = 0;
348 $userevent = $this->create_calendar_event('user', $USER->id, 'user', 0, time(), $record);
350 $record = new stdClass();
351 $record->courseid = $course->id;
352 $record->groupid = $group->id;
353 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);
355 $paramevents = array ('eventids' => array($siteevent->id), 'courseids' => array($course->id),
356 'groupids' => array($group->id), 'categoryids' => array($category->id));
358 $options = array ('siteevents' => true, 'userevents' => true);
359 $events = core_calendar_external::get_calendar_events($paramevents, $options);
360 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
362 // Check to see if we got all events.
363 $this->assertEquals(5, count($events['events']));
364 $this->assertEquals(0, count($events['warnings']));
365 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7*WEEKSECS);
366 $events = core_calendar_external::get_calendar_events($paramevents, $options);
367 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
368 $this->assertEquals(5, count($events['events']));
369 $this->assertEquals(0, count($events['warnings']));
371 // Expect the same URL in the description of two different events (because they are repeated).
372 $coursecontext = context_course::instance($course->id);
373 $expectedurl = "webservice/pluginfile.php/$coursecontext->id/calendar/event_description/$courseevent->id/fakeimage.png";
374 $withdescription = 0;
375 foreach ($events['events'] as $event) {
376 if (!empty($event['description'])) {
377 $withdescription++;
378 $this->assertContains($expectedurl, $event['description']);
381 $this->assertEquals(2, $withdescription);
383 // Let's play around with caps.
385 // Create user event for the user $user.
386 $record = new stdClass();
387 $record->courseid = 0;
388 $record->groupid = 0;
389 $this->create_calendar_event('user', $user->id, 'user', 0, time(), $record);
391 $this->setUser($user);
392 $events = core_calendar_external::get_calendar_events($paramevents, $options);
393 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
394 $this->assertEquals(2, count($events['events'])); // site, user.
395 $this->assertEquals(2, count($events['warnings'])); // course, group.
397 $role = $DB->get_record('role', array('shortname' => 'student'));
398 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
399 $events = core_calendar_external::get_calendar_events($paramevents, $options);
400 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
401 $this->assertEquals(4, count($events['events'])); // site, user, both course events.
402 $this->assertEquals(1, count($events['warnings'])); // group.
404 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS);
405 $events = core_calendar_external::get_calendar_events($paramevents, $options);
406 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
407 $this->assertEquals(3, count($events['events'])); // site, user, one course event.
408 $this->assertEquals(1, count($events['warnings'])); // group.
410 groups_add_member($group, $user);
411 $events = core_calendar_external::get_calendar_events($paramevents, $options);
412 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
413 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
414 $this->assertEquals(0, count($events['warnings']));
416 $paramevents = array ('courseids' => array($course->id), 'groupids' => array($group->id));
417 $events = core_calendar_external::get_calendar_events($paramevents, $options);
418 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
419 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
420 $this->assertEquals(0, count($events['warnings']));
422 $paramevents = array ('groupids' => array($group->id, 23));
423 $events = core_calendar_external::get_calendar_events($paramevents, $options);
424 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
425 $this->assertEquals(3, count($events['events'])); // site, user, group.
426 $this->assertEquals(1, count($events['warnings']));
428 $paramevents = array ('courseids' => array(23));
429 $events = core_calendar_external::get_calendar_events($paramevents, $options);
430 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
431 $this->assertEquals(2, count($events['events'])); // site, user.
432 $this->assertEquals(1, count($events['warnings']));
434 $paramevents = array ();
435 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);
436 $events = core_calendar_external::get_calendar_events($paramevents, $options);
437 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
438 $this->assertEquals(0, count($events['events'])); // nothing returned.
439 $this->assertEquals(0, count($events['warnings']));
441 $paramevents = array ('eventids' => array($siteevent->id, $groupevent->id));
442 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);
443 $events = core_calendar_external::get_calendar_events($paramevents, $options);
444 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
445 $this->assertEquals(2, count($events['events'])); // site, group.
446 $this->assertEquals(0, count($events['warnings']));
448 $paramevents = array ('eventids' => array($siteevent->id));
449 $events = core_calendar_external::get_calendar_events($paramevents, $options);
450 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
451 $this->assertEquals(1, count($events['events'])); // site.
452 $this->assertEquals(0, count($events['warnings']));
454 // Try getting a course event by its id.
455 $paramevents = array ('eventids' => array($courseevent->id));
456 $events = core_calendar_external::get_calendar_events($paramevents, $options);
457 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
458 $this->assertEquals(1, count($events['events']));
459 $this->assertEquals(0, count($events['warnings']));
461 // Now, create an activity event.
462 $this->setAdminUser();
463 $nexttime = time() + DAYSECS;
464 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'duedate' => $nexttime));
466 $this->setUser($user);
467 $paramevents = array ('courseids' => array($course->id));
468 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS);
469 $events = core_calendar_external::get_calendar_events($paramevents, $options);
470 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
472 $this->assertCount(5, $events['events']);
474 // Hide the assignment.
475 set_coursemodule_visible($assign->cmid, 0);
476 // Empty all the caches that may be affected by this change.
477 accesslib_clear_all_caches_for_unit_testing();
478 course_modinfo::clear_instance_cache();
480 $events = core_calendar_external::get_calendar_events($paramevents, $options);
481 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
482 // Expect one less.
483 $this->assertCount(4, $events['events']);
485 // Create some category events.
486 $this->setAdminUser();
487 $record = new stdClass();
488 $record->categoryid = $category->id;
489 $this->create_calendar_event('category a', $USER->id, 'category', 0, time(), $record);
491 $record->categoryid = $category2->id;
492 $this->create_calendar_event('category b', $USER->id, 'category', 0, time(), $record);
494 // Now as student, make sure we get the events of the courses I am enrolled.
495 $this->setUser($user2);
496 $paramevents = array('categoryids' => array($category2b->id));
497 $options = array('timeend' => time() + 7 * WEEKSECS);
498 $events = core_calendar_external::get_calendar_events($paramevents, $options);
499 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
501 // Should be just one, since there's just one category event of the course I am enrolled (course3 - cat2b).
502 $this->assertEquals(1, count($events['events']));
503 $this->assertEquals(0, count($events['warnings']));
505 // Admin can see all category events.
506 $this->setAdminUser();
507 $paramevents = array('categoryids' => array($category->id, $category2->id, $category2b->id));
508 $options = array('timeend' => time() + 7 * WEEKSECS);
509 $events = core_calendar_external::get_calendar_events($paramevents, $options);
510 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
511 $this->assertEquals(2, count($events['events']));
512 $this->assertEquals(0, count($events['warnings']));
516 * Test core_calendar_external::create_calendar_events
518 public function test_core_create_calendar_events() {
519 global $DB, $USER, $SITE;
521 $this->resetAfterTest(true);
522 $this->setAdminUser();
524 // Create a few stuff to test with.
525 $user = $this->getDataGenerator()->create_user();
526 $course = $this->getDataGenerator()->create_course();
527 $record = new stdClass();
528 $record->courseid = $course->id;
529 $group = $this->getDataGenerator()->create_group($record);
531 $prevcount = $DB->count_records('event');
533 // Let's create a few events.
534 $events = array (
535 array('name' => 'site', 'courseid' => $SITE->id, 'eventtype' => 'site'),
536 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),
537 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),
538 array('name' => 'user')
540 $eventsret = core_calendar_external::create_calendar_events($events);
541 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
543 // Check to see if things were created properly.
544 $aftercount = $DB->count_records('event');
545 $this->assertEquals($prevcount + 5, $aftercount);
546 $this->assertEquals(5, count($eventsret['events']));
547 $this->assertEquals(0, count($eventsret['warnings']));
549 $sitecontext = context_system::instance();
550 $coursecontext = context_course::instance($course->id);
552 $this->setUser($user);
553 $prevcount = $aftercount;
554 $events = array (
555 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),
556 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),
557 array('name' => 'user')
559 $role = $DB->get_record('role', array('shortname' => 'student'));
560 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
561 groups_add_member($group, $user);
562 $this->assignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
563 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
564 $eventsret = core_calendar_external::create_calendar_events($events);
565 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
566 // Check to see if things were created properly.
567 $aftercount = $DB->count_records('event');
568 $this->assertEquals($prevcount + 4, $aftercount);
569 $this->assertEquals(4, count($eventsret['events']));
570 $this->assertEquals(0, count($eventsret['warnings']));
572 // Check to see nothing was created without proper permission.
573 $this->setGuestUser();
574 $prevcount = $DB->count_records('event');
575 $eventsret = core_calendar_external::create_calendar_events($events);
576 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
577 $aftercount = $DB->count_records('event');
578 $this->assertEquals($prevcount, $aftercount);
579 $this->assertEquals(0, count($eventsret['events']));
580 $this->assertEquals(3, count($eventsret['warnings']));
582 $this->setUser($user);
583 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
584 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
585 $prevcount = $DB->count_records('event');
586 $eventsret = core_calendar_external::create_calendar_events($events);
587 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
588 $aftercount = $DB->count_records('event');
589 $this->assertEquals($prevcount + 1, $aftercount); // User event.
590 $this->assertEquals(1, count($eventsret['events']));
591 $this->assertEquals(2, count($eventsret['warnings']));
595 * Requesting calendar events from a given time should return all events with a sort
596 * time at or after the requested time. All events prior to that time should not
597 * be return.
599 * If there are no events on or after the given time then an empty result set should
600 * be returned.
602 public function test_get_calendar_action_events_by_timesort_after_time() {
603 $user = $this->getDataGenerator()->create_user();
604 $course = $this->getDataGenerator()->create_course();
605 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
606 $moduleinstance = $generator->create_instance(['course' => $course->id]);
608 $this->getDataGenerator()->enrol_user($user->id, $course->id);
609 $this->resetAfterTest(true);
610 $this->setUser($user);
612 $params = [
613 'type' => CALENDAR_EVENT_TYPE_ACTION,
614 'modulename' => 'assign',
615 'instance' => $moduleinstance->id,
616 'courseid' => $course->id,
619 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
620 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
621 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
622 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
623 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
624 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
625 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
626 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
628 $result = core_calendar_external::get_calendar_action_events_by_timesort(5);
629 $result = external_api::clean_returnvalue(
630 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
631 $result
633 $events = $result['events'];
635 $this->assertCount(4, $events);
636 $this->assertEquals('Event 5', $events[0]['name']);
637 $this->assertEquals('Event 6', $events[1]['name']);
638 $this->assertEquals('Event 7', $events[2]['name']);
639 $this->assertEquals('Event 8', $events[3]['name']);
640 $this->assertEquals($event5->id, $result['firstid']);
641 $this->assertEquals($event8->id, $result['lastid']);
643 $result = core_calendar_external::get_calendar_action_events_by_timesort(9);
644 $result = external_api::clean_returnvalue(
645 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
646 $result
649 $this->assertEmpty($result['events']);
650 $this->assertNull($result['firstid']);
651 $this->assertNull($result['lastid']);
655 * Requesting calendar events before a given time should return all events with a sort
656 * time at or before the requested time (inclusive). All events after that time
657 * should not be returned.
659 * If there are no events before the given time then an empty result set should be
660 * returned.
662 public function test_get_calendar_action_events_by_timesort_before_time() {
663 $user = $this->getDataGenerator()->create_user();
664 $course = $this->getDataGenerator()->create_course();
665 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
666 $moduleinstance = $generator->create_instance(['course' => $course->id]);
668 $this->getDataGenerator()->enrol_user($user->id, $course->id);
669 $this->resetAfterTest(true);
670 $this->setUser($user);
672 $params = [
673 'type' => CALENDAR_EVENT_TYPE_ACTION,
674 'modulename' => 'assign',
675 'instance' => $moduleinstance->id,
676 'courseid' => $course->id,
679 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
680 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
681 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
682 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
683 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
684 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
685 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
686 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 9]));
688 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5);
689 $result = external_api::clean_returnvalue(
690 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
691 $result
693 $events = $result['events'];
695 $this->assertCount(4, $events);
696 $this->assertEquals('Event 1', $events[0]['name']);
697 $this->assertEquals('Event 2', $events[1]['name']);
698 $this->assertEquals('Event 3', $events[2]['name']);
699 $this->assertEquals('Event 4', $events[3]['name']);
700 $this->assertEquals($event1->id, $result['firstid']);
701 $this->assertEquals($event4->id, $result['lastid']);
703 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 1);
704 $result = external_api::clean_returnvalue(
705 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
706 $result
709 $this->assertEmpty($result['events']);
710 $this->assertNull($result['firstid']);
711 $this->assertNull($result['lastid']);
715 * Test retrieving event that was overridden for a user
717 public function test_get_calendar_events_override() {
718 $user = $this->getDataGenerator()->create_user();
719 $user2 = $this->getDataGenerator()->create_user();
720 $teacher = $this->getDataGenerator()->create_user();
721 $anotheruser = $this->getDataGenerator()->create_user();
722 $course = $this->getDataGenerator()->create_course();
723 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
724 $moduleinstance = $generator->create_instance(['course' => $course->id]);
726 $this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
727 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
728 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
729 $this->resetAfterTest(true);
730 $this->setAdminUser();
732 $params = [
733 'type' => CALENDAR_EVENT_TYPE_ACTION,
734 'modulename' => 'assign',
735 'instance' => $moduleinstance->id,
738 $now = time();
739 // Create two events - one for everybody in the course and one only for the first student.
740 $event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS, $params + ['courseid' => $course->id]);
741 $event2 = $this->create_calendar_event('User event', $user->id, 'due', 0, $now + 2*DAYSECS, $params + ['courseid' => 0]);
743 // Retrieve course events for the second student - only one "Base event" is returned.
744 $this->setUser($user2);
745 $paramevents = array('courseids' => array($course->id));
746 $options = array ('siteevents' => true, 'userevents' => true);
747 $events = core_calendar_external::get_calendar_events($paramevents, $options);
748 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
749 $this->assertEquals(1, count($events['events']));
750 $this->assertEquals(0, count($events['warnings']));
751 $this->assertEquals('Base event', $events['events'][0]['name']);
753 // Retrieve events for the first student - both events are returned.
754 $this->setUser($user);
755 $events = core_calendar_external::get_calendar_events($paramevents, $options);
756 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
757 $this->assertEquals(2, count($events['events']));
758 $this->assertEquals(0, count($events['warnings']));
759 $this->assertEquals('Base event', $events['events'][0]['name']);
760 $this->assertEquals('User event', $events['events'][1]['name']);
762 // Retrieve events by id as a teacher, 'User event' should be returned since teacher has access to this course.
763 $this->setUser($teacher);
764 $paramevents = ['eventids' => [$event2->id]];
765 $events = core_calendar_external::get_calendar_events($paramevents, $options);
766 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
767 $this->assertEquals(1, count($events['events']));
768 $this->assertEquals(0, count($events['warnings']));
769 $this->assertEquals('User event', $events['events'][0]['name']);
771 // Retrieve events by id as another user, nothing should be returned.
772 $this->setUser($anotheruser);
773 $paramevents = ['eventids' => [$event2->id, $event1->id]];
774 $events = core_calendar_external::get_calendar_events($paramevents, $options);
775 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
776 $this->assertEquals(0, count($events['events']));
777 $this->assertEquals(0, count($events['warnings']));
781 * Requesting calendar events within a given time range should return all events with
782 * a sort time between the lower and upper time bound (inclusive).
784 * If there are no events in the given time range then an empty result set should be
785 * returned.
787 public function test_get_calendar_action_events_by_timesort_time_range() {
788 $user = $this->getDataGenerator()->create_user();
789 $course = $this->getDataGenerator()->create_course();
790 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
791 $moduleinstance = $generator->create_instance(['course' => $course->id]);
793 $this->getDataGenerator()->enrol_user($user->id, $course->id);
794 $this->resetAfterTest(true);
795 $this->setUser($user);
797 $params = [
798 'type' => CALENDAR_EVENT_TYPE_ACTION,
799 'modulename' => 'assign',
800 'instance' => $moduleinstance->id,
801 'courseid' => $course->id,
804 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
805 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
806 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
807 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
808 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
809 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
810 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
811 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
813 $result = core_calendar_external::get_calendar_action_events_by_timesort(3, 6);
814 $result = external_api::clean_returnvalue(
815 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
816 $result
818 $events = $result['events'];
820 $this->assertCount(4, $events);
821 $this->assertEquals('Event 3', $events[0]['name']);
822 $this->assertEquals('Event 4', $events[1]['name']);
823 $this->assertEquals('Event 5', $events[2]['name']);
824 $this->assertEquals('Event 6', $events[3]['name']);
825 $this->assertEquals($event3->id, $result['firstid']);
826 $this->assertEquals($event6->id, $result['lastid']);
828 $result = core_calendar_external::get_calendar_action_events_by_timesort(10, 15);
829 $result = external_api::clean_returnvalue(
830 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
831 $result
834 $this->assertEmpty($result['events']);
835 $this->assertNull($result['firstid']);
836 $this->assertNull($result['lastid']);
840 * Requesting calendar events within a given time range and a limit and offset should return
841 * the number of events up to the given limit value that have a sort time between the lower
842 * and uppper time bound (inclusive) where the result set is shifted by the offset value.
844 * If there are no events in the given time range then an empty result set should be
845 * returned.
847 public function test_get_calendar_action_events_by_timesort_time_limit_offset() {
848 $user = $this->getDataGenerator()->create_user();
849 $course = $this->getDataGenerator()->create_course();
850 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
851 $moduleinstance = $generator->create_instance(['course' => $course->id]);
853 $this->getDataGenerator()->enrol_user($user->id, $course->id);
854 $this->resetAfterTest(true);
855 $this->setUser($user);
857 $params = [
858 'type' => CALENDAR_EVENT_TYPE_ACTION,
859 'modulename' => 'assign',
860 'instance' => $moduleinstance->id,
861 'courseid' => $course->id,
864 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
865 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
866 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
867 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
868 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
869 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
870 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
871 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
873 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event3->id, 2);
874 $result = external_api::clean_returnvalue(
875 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
876 $result
878 $events = $result['events'];
880 $this->assertCount(2, $events);
881 $this->assertEquals('Event 4', $events[0]['name']);
882 $this->assertEquals('Event 5', $events[1]['name']);
883 $this->assertEquals($event4->id, $result['firstid']);
884 $this->assertEquals($event5->id, $result['lastid']);
886 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event5->id, 2);
887 $result = external_api::clean_returnvalue(
888 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
889 $result
891 $events = $result['events'];
893 $this->assertCount(2, $events);
894 $this->assertEquals('Event 6', $events[0]['name']);
895 $this->assertEquals('Event 7', $events[1]['name']);
896 $this->assertEquals($event6->id, $result['firstid']);
897 $this->assertEquals($event7->id, $result['lastid']);
899 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event7->id, 2);
900 $result = external_api::clean_returnvalue(
901 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
902 $result
905 $this->assertEmpty($result['events']);
906 $this->assertNull($result['firstid']);
907 $this->assertNull($result['lastid']);
911 * Requesting calendar events from a given course and time should return all
912 * events with a sort time at or after the requested time. All events prior
913 * to that time should not be return.
915 * If there are no events on or after the given time then an empty result set should
916 * be returned.
918 public function test_get_calendar_action_events_by_course_after_time() {
919 $user = $this->getDataGenerator()->create_user();
920 $course1 = $this->getDataGenerator()->create_course();
921 $course2 = $this->getDataGenerator()->create_course();
922 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
923 $instance1 = $generator->create_instance(['course' => $course1->id]);
924 $instance2 = $generator->create_instance(['course' => $course2->id]);
925 $records = [];
927 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
928 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
929 $this->resetAfterTest(true);
930 $this->setUser($user);
932 for ($i = 1; $i < 19; $i++) {
933 $courseid = ($i < 9) ? $course1->id : $course2->id;
934 $instance = ($i < 9) ? $instance1->id : $instance2->id;
935 $records[] = $this->create_calendar_event(
936 sprintf('Event %d', $i),
937 $user->id,
938 'user',
942 'type' => CALENDAR_EVENT_TYPE_ACTION,
943 'courseid' => $courseid,
944 'timesort' => $i,
945 'modulename' => 'assign',
946 'instance' => $instance,
951 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 5);
952 $result = external_api::clean_returnvalue(
953 core_calendar_external::get_calendar_action_events_by_course_returns(),
954 $result
956 $result = $result['events'];
958 $this->assertCount(4, $result);
959 $this->assertEquals('Event 5', $result[0]['name']);
960 $this->assertEquals('Event 6', $result[1]['name']);
961 $this->assertEquals('Event 7', $result[2]['name']);
962 $this->assertEquals('Event 8', $result[3]['name']);
964 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 9);
965 $result = external_api::clean_returnvalue(
966 core_calendar_external::get_calendar_action_events_by_course_returns(),
967 $result
969 $result = $result['events'];
971 $this->assertEmpty($result);
975 * Requesting calendar events for a course and before a given time should return
976 * all events with a sort time at or before the requested time (inclusive). All
977 * events after that time should not be returned.
979 * If there are no events before the given time then an empty result set should be
980 * returned.
982 public function test_get_calendar_action_events_by_course_before_time() {
983 $user = $this->getDataGenerator()->create_user();
984 $course1 = $this->getDataGenerator()->create_course();
985 $course2 = $this->getDataGenerator()->create_course();
986 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
987 $instance1 = $generator->create_instance(['course' => $course1->id]);
988 $instance2 = $generator->create_instance(['course' => $course2->id]);
989 $records = [];
991 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
992 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
993 $this->resetAfterTest(true);
994 $this->setUser($user);
996 for ($i = 1; $i < 19; $i++) {
997 $courseid = ($i < 9) ? $course1->id : $course2->id;
998 $instance = ($i < 9) ? $instance1->id : $instance2->id;
999 $records[] = $this->create_calendar_event(
1000 sprintf('Event %d', $i),
1001 $user->id,
1002 'user',
1006 'type' => CALENDAR_EVENT_TYPE_ACTION,
1007 'courseid' => $courseid,
1008 'timesort' => $i + 1,
1009 'modulename' => 'assign',
1010 'instance' => $instance,
1015 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 5);
1016 $result = external_api::clean_returnvalue(
1017 core_calendar_external::get_calendar_action_events_by_course_returns(),
1018 $result
1020 $result = $result['events'];
1022 $this->assertCount(4, $result);
1023 $this->assertEquals('Event 1', $result[0]['name']);
1024 $this->assertEquals('Event 2', $result[1]['name']);
1025 $this->assertEquals('Event 3', $result[2]['name']);
1026 $this->assertEquals('Event 4', $result[3]['name']);
1028 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 1);
1029 $result = external_api::clean_returnvalue(
1030 core_calendar_external::get_calendar_action_events_by_course_returns(),
1031 $result
1033 $result = $result['events'];
1035 $this->assertEmpty($result);
1039 * Requesting calendar events for a course and within a given time range should
1040 * return all events with a sort time between the lower and upper time bound
1041 * (inclusive).
1043 * If there are no events in the given time range then an empty result set should be
1044 * returned.
1046 public function test_get_calendar_action_events_by_course_time_range() {
1047 $user = $this->getDataGenerator()->create_user();
1048 $course1 = $this->getDataGenerator()->create_course();
1049 $course2 = $this->getDataGenerator()->create_course();
1050 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1051 $instance1 = $generator->create_instance(['course' => $course1->id]);
1052 $instance2 = $generator->create_instance(['course' => $course2->id]);
1053 $records = [];
1055 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1056 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1057 $this->resetAfterTest(true);
1058 $this->setUser($user);
1060 for ($i = 1; $i < 19; $i++) {
1061 $courseid = ($i < 9) ? $course1->id : $course2->id;
1062 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1063 $records[] = $this->create_calendar_event(
1064 sprintf('Event %d', $i),
1065 $user->id,
1066 'user',
1070 'type' => CALENDAR_EVENT_TYPE_ACTION,
1071 'courseid' => $courseid,
1072 'timesort' => $i,
1073 'modulename' => 'assign',
1074 'instance' => $instance,
1079 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 3, 6);
1080 $result = external_api::clean_returnvalue(
1081 core_calendar_external::get_calendar_action_events_by_course_returns(),
1082 $result
1084 $result = $result['events'];
1086 $this->assertCount(4, $result);
1087 $this->assertEquals('Event 3', $result[0]['name']);
1088 $this->assertEquals('Event 4', $result[1]['name']);
1089 $this->assertEquals('Event 5', $result[2]['name']);
1090 $this->assertEquals('Event 6', $result[3]['name']);
1092 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 10, 15);
1093 $result = external_api::clean_returnvalue(
1094 core_calendar_external::get_calendar_action_events_by_course_returns(),
1095 $result
1097 $result = $result['events'];
1099 $this->assertEmpty($result);
1103 * Requesting calendar events for a course and within a given time range and a limit
1104 * and offset should return the number of events up to the given limit value that have
1105 * a sort time between the lower and uppper time bound (inclusive) where the result
1106 * set is shifted by the offset value.
1108 * If there are no events in the given time range then an empty result set should be
1109 * returned.
1111 public function test_get_calendar_action_events_by_course_time_limit_offset() {
1112 $user = $this->getDataGenerator()->create_user();
1113 $course1 = $this->getDataGenerator()->create_course();
1114 $course2 = $this->getDataGenerator()->create_course();
1115 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1116 $instance1 = $generator->create_instance(['course' => $course1->id]);
1117 $instance2 = $generator->create_instance(['course' => $course2->id]);
1118 $records = [];
1120 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1121 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1122 $this->resetAfterTest(true);
1123 $this->setUser($user);
1125 for ($i = 1; $i < 19; $i++) {
1126 $courseid = ($i < 9) ? $course1->id : $course2->id;
1127 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1128 $records[] = $this->create_calendar_event(
1129 sprintf('Event %d', $i),
1130 $user->id,
1131 'user',
1135 'type' => CALENDAR_EVENT_TYPE_ACTION,
1136 'courseid' => $courseid,
1137 'timesort' => $i,
1138 'modulename' => 'assign',
1139 'instance' => $instance,
1144 $result = core_calendar_external::get_calendar_action_events_by_course(
1145 $course1->id, 2, 7, $records[2]->id, 2);
1146 $result = external_api::clean_returnvalue(
1147 core_calendar_external::get_calendar_action_events_by_course_returns(),
1148 $result
1150 $result = $result['events'];
1152 $this->assertCount(2, $result);
1153 $this->assertEquals('Event 4', $result[0]['name']);
1154 $this->assertEquals('Event 5', $result[1]['name']);
1156 $result = core_calendar_external::get_calendar_action_events_by_course(
1157 $course1->id, 2, 7, $records[4]->id, 2);
1158 $result = external_api::clean_returnvalue(
1159 core_calendar_external::get_calendar_action_events_by_course_returns(),
1160 $result
1162 $result = $result['events'];
1164 $this->assertCount(2, $result);
1165 $this->assertEquals('Event 6', $result[0]['name']);
1166 $this->assertEquals('Event 7', $result[1]['name']);
1168 $result = core_calendar_external::get_calendar_action_events_by_course(
1169 $course1->id, 2, 7, $records[6]->id, 2);
1170 $result = external_api::clean_returnvalue(
1171 core_calendar_external::get_calendar_action_events_by_course_returns(),
1172 $result
1174 $result = $result['events'];
1176 $this->assertEmpty($result);
1180 * Test that get_action_events_by_courses will return a list of events for each
1181 * course you provided as long as the user is enrolled in the course.
1183 public function test_get_action_events_by_courses() {
1184 $user = $this->getDataGenerator()->create_user();
1185 $course1 = $this->getDataGenerator()->create_course();
1186 $course2 = $this->getDataGenerator()->create_course();
1187 $course3 = $this->getDataGenerator()->create_course();
1188 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1189 $instance1 = $generator->create_instance(['course' => $course1->id]);
1190 $instance2 = $generator->create_instance(['course' => $course2->id]);
1191 $instance3 = $generator->create_instance(['course' => $course3->id]);
1192 $records = [];
1193 $mapresult = function($result) {
1194 $groupedbycourse = [];
1195 foreach ($result['groupedbycourse'] as $group) {
1196 $events = $group['events'];
1197 $courseid = $group['courseid'];
1198 $groupedbycourse[$courseid] = $events;
1201 return $groupedbycourse;
1204 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1205 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1206 $this->resetAfterTest(true);
1207 $this->setUser($user);
1209 for ($i = 1; $i < 10; $i++) {
1210 if ($i < 3) {
1211 $courseid = $course1->id;
1212 $instance = $instance1->id;
1213 } else if ($i < 6) {
1214 $courseid = $course2->id;
1215 $instance = $instance2->id;
1216 } else {
1217 $courseid = $course3->id;
1218 $instance = $instance3->id;
1221 $records[] = $this->create_calendar_event(
1222 sprintf('Event %d', $i),
1223 $user->id,
1224 'user',
1228 'type' => CALENDAR_EVENT_TYPE_ACTION,
1229 'courseid' => $courseid,
1230 'timesort' => $i,
1231 'modulename' => 'assign',
1232 'instance' => $instance,
1237 $result = core_calendar_external::get_calendar_action_events_by_courses([], 1);
1238 $result = external_api::clean_returnvalue(
1239 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1240 $result
1242 $result = $result['groupedbycourse'];
1244 $this->assertEmpty($result);
1246 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 3);
1247 $result = external_api::clean_returnvalue(
1248 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1249 $result
1252 $groupedbycourse = $mapresult($result);
1254 $this->assertEmpty($groupedbycourse[$course1->id]);
1256 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 1);
1257 $result = external_api::clean_returnvalue(
1258 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1259 $result
1261 $groupedbycourse = $mapresult($result);
1263 $this->assertCount(2, $groupedbycourse[$course1->id]);
1264 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1265 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);
1267 $result = core_calendar_external::get_calendar_action_events_by_courses(
1268 [$course1->id, $course2->id], 1);
1269 $result = external_api::clean_returnvalue(
1270 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1271 $result
1273 $groupedbycourse = $mapresult($result);
1275 $this->assertCount(2, $groupedbycourse[$course1->id]);
1276 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1277 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);
1278 $this->assertCount(3, $groupedbycourse[$course2->id]);
1279 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1280 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);
1281 $this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']);
1283 $result = core_calendar_external::get_calendar_action_events_by_courses(
1284 [$course1->id, $course2->id], 2, 4);
1285 $result = external_api::clean_returnvalue(
1286 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1287 $result
1289 $groupedbycourse = $mapresult($result);
1291 $this->assertCount(2, $groupedbycourse);
1292 $this->assertCount(1, $groupedbycourse[$course1->id]);
1293 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][0]['name']);
1294 $this->assertCount(2, $groupedbycourse[$course2->id]);
1295 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1296 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);
1298 $result = core_calendar_external::get_calendar_action_events_by_courses(
1299 [$course1->id, $course2->id], 1, null, 1);
1300 $result = external_api::clean_returnvalue(
1301 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1302 $result
1304 $groupedbycourse = $mapresult($result);
1306 $this->assertCount(2, $groupedbycourse);
1307 $this->assertCount(1, $groupedbycourse[$course1->id]);
1308 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1309 $this->assertCount(1, $groupedbycourse[$course2->id]);
1310 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1314 * Test for deleting module events.
1316 public function test_delete_calendar_events_for_modules() {
1317 $this->resetAfterTest();
1318 $this->setAdminUser();
1319 $course = $this->getDataGenerator()->create_course();
1320 $nexttime = time() + DAYSECS;
1321 $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'duedate' => $nexttime]);
1322 $events = calendar_get_events(time(), $nexttime, true, true, true);
1323 $this->assertCount(1, $events);
1324 $params = [];
1325 foreach ($events as $event) {
1326 $params[] = [
1327 'eventid' => $event->id,
1328 'repeat' => false
1332 $this->expectException('moodle_exception');
1333 core_calendar_external::delete_calendar_events($params);
1337 * Updating the event start day should change the date value but leave
1338 * the time of day unchanged.
1340 public function test_update_event_start_day() {
1341 $generator = $this->getDataGenerator();
1342 $user = $generator->create_user();
1343 $roleid = $generator->create_role();
1344 $context = \context_system::instance();
1345 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1346 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1347 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1349 $generator->role_assign($roleid, $user->id, $context->id);
1350 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1352 $this->setUser($user);
1353 $this->resetAfterTest(true);
1355 $event = $this->create_calendar_event(
1356 'Test event',
1357 $user->id,
1358 'user',
1360 null,
1362 'courseid' => 0,
1363 'timestart' => $originalstarttime->getTimestamp()
1367 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
1368 $result = external_api::clean_returnvalue(
1369 core_calendar_external::update_event_start_day_returns(),
1370 $result
1373 $this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);
1377 * A user should not be able to edit an event that they don't have
1378 * capabilities for.
1380 public function test_update_event_start_day_no_permission() {
1381 $generator = $this->getDataGenerator();
1382 $user = $generator->create_user();
1383 $roleid = $generator->create_role();
1384 $context = \context_system::instance();
1385 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1386 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1387 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1389 $generator->role_assign($roleid, $user->id, $context->id);
1390 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1392 $this->setUser($user);
1393 $this->resetAfterTest(true);
1395 $event = $this->create_calendar_event(
1396 'Test event',
1397 $user->id,
1398 'user',
1400 null,
1402 'courseid' => 0,
1403 'timestart' => $originalstarttime->getTimestamp()
1407 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1408 $this->expectException('moodle_exception');
1409 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
1410 $result = external_api::clean_returnvalue(
1411 core_calendar_external::update_event_start_day_returns(),
1412 $result
1417 * A user should not be able to update a module event.
1419 public function test_update_event_start_day_module_event() {
1420 $generator = $this->getDataGenerator();
1421 $user = $generator->create_user();
1422 $course = $generator->create_course();
1423 $plugingenerator = $generator->get_plugin_generator('mod_assign');
1424 $moduleinstance = $plugingenerator->create_instance(['course' => $course->id]);
1425 $roleid = $generator->create_role();
1426 $context = \context_course::instance($course->id);
1427 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1428 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
1429 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1431 $generator->role_assign($roleid, $user->id, $context->id);
1432 $generator->enrol_user($user->id, $course->id);
1434 $this->setUser($user);
1435 $this->resetAfterTest(true);
1437 $event = $this->create_calendar_event(
1438 'Test event',
1439 $user->id,
1440 'user',
1442 null,
1444 'modulename' => 'assign',
1445 'instance' => $moduleinstance->id,
1446 'courseid' => $course->id,
1447 'timestart' => $originalstarttime->getTimestamp()
1451 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1452 $this->expectException('moodle_exception');
1453 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
1454 $result = external_api::clean_returnvalue(
1455 core_calendar_external::update_event_start_day_returns(),
1456 $result
1461 * Submit a request where the time duration until is earlier than the time
1462 * start in order to get a validation error from the server.
1464 public function test_submit_create_update_form_validation_error() {
1465 $user = $this->getDataGenerator()->create_user();
1466 $timestart = new DateTime();
1467 $interval = new DateInterval("P1D"); // One day.
1468 $timedurationuntil = new DateTime();
1469 $timedurationuntil->sub($interval);
1470 $formdata = [
1471 'id' => 0,
1472 'userid' => $user->id,
1473 'modulename' => '',
1474 'instance' => 0,
1475 'visible' => 1,
1476 'name' => 'Test',
1477 'timestart' => [
1478 'day' => $timestart->format('j'),
1479 'month' => $timestart->format('n'),
1480 'year' => $timestart->format('Y'),
1481 'hour' => $timestart->format('G'),
1482 'minute' => 0,
1484 'eventtype' => 'user',
1485 'description' => [
1486 'text' => '',
1487 'format' => 1,
1489 'duration' => 1,
1490 'timedurationuntil' => [
1491 'day' => $timedurationuntil->format('j'),
1492 'month' => $timedurationuntil->format('n'),
1493 'year' => $timedurationuntil->format('Y'),
1494 'hour' => $timedurationuntil->format('G'),
1495 'minute' => 0,
1499 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1501 $querystring = http_build_query($formdata, '', '&amp;');
1503 $this->resetAfterTest(true);
1504 $this->setUser($user);
1506 $result = external_api::clean_returnvalue(
1507 core_calendar_external::submit_create_update_form_returns(),
1508 core_calendar_external::submit_create_update_form($querystring)
1511 $this->assertTrue($result['validationerror']);
1515 * A user with the moodle/calendar:manageownentries capability at the
1516 * system context should be able to create a user event.
1518 public function test_submit_create_update_form_create_user_event() {
1519 $generator = $this->getDataGenerator();
1520 $user = $generator->create_user();
1521 $roleid = $generator->create_role();
1522 $context = \context_system::instance();
1523 $timestart = new DateTime();
1524 $interval = new DateInterval("P1D"); // One day.
1525 $timedurationuntil = new DateTime();
1526 $timedurationuntil->add($interval);
1527 $formdata = [
1528 'id' => 0,
1529 'userid' => $user->id,
1530 'modulename' => '',
1531 'instance' => 0,
1532 'visible' => 1,
1533 'name' => 'Test',
1534 'timestart' => [
1535 'day' => $timestart->format('j'),
1536 'month' => $timestart->format('n'),
1537 'year' => $timestart->format('Y'),
1538 'hour' => $timestart->format('G'),
1539 'minute' => 0,
1541 'eventtype' => 'user',
1542 'description' => [
1543 'text' => '',
1544 'format' => 1,
1545 'itemid' => 0
1547 'duration' => 1,
1548 'timedurationuntil' => [
1549 'day' => $timedurationuntil->format('j'),
1550 'month' => $timedurationuntil->format('n'),
1551 'year' => $timedurationuntil->format('Y'),
1552 'hour' => $timedurationuntil->format('G'),
1553 'minute' => 0,
1557 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1558 $querystring = http_build_query($formdata, '', '&');
1560 $generator->role_assign($roleid, $user->id, $context->id);
1561 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1563 $user->ignoresesskey = true;
1564 $this->resetAfterTest(true);
1565 $this->setUser($user);
1567 $result = external_api::clean_returnvalue(
1568 core_calendar_external::submit_create_update_form_returns(),
1569 core_calendar_external::submit_create_update_form($querystring)
1572 $event = $result['event'];
1573 $this->assertEquals($user->id, $event['userid']);
1574 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1575 $this->assertEquals($formdata['name'], $event['name']);
1579 * A user without the moodle/calendar:manageownentries capability at the
1580 * system context should not be able to create a user event.
1582 public function test_submit_create_update_form_create_user_event_no_permission() {
1583 $generator = $this->getDataGenerator();
1584 $user = $generator->create_user();
1585 $roleid = $generator->create_role();
1586 $context = \context_system::instance();
1587 $timestart = new DateTime();
1588 $interval = new DateInterval("P1D"); // One day.
1589 $timedurationuntil = new DateTime();
1590 $timedurationuntil->add($interval);
1591 $formdata = [
1592 'id' => 0,
1593 'userid' => $user->id,
1594 'modulename' => '',
1595 'instance' => 0,
1596 'visible' => 1,
1597 'name' => 'Test',
1598 'timestart' => [
1599 'day' => $timestart->format('j'),
1600 'month' => $timestart->format('n'),
1601 'year' => $timestart->format('Y'),
1602 'hour' => $timestart->format('G'),
1603 'minute' => 0,
1605 'eventtype' => 'user',
1606 'description' => [
1607 'text' => '',
1608 'format' => 1,
1610 'duration' => 1,
1611 'timedurationuntil' => [
1612 'day' => $timedurationuntil->format('j'),
1613 'month' => $timedurationuntil->format('n'),
1614 'year' => $timedurationuntil->format('Y'),
1615 'hour' => $timedurationuntil->format('G'),
1616 'minute' => 0,
1620 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1621 $querystring = http_build_query($formdata, '', '&');
1623 $generator->role_assign($roleid, $user->id, $context->id);
1624 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1626 $user->ignoresesskey = true;
1627 $this->resetAfterTest(true);
1628 $this->setUser($user);
1630 $this->expectException('moodle_exception');
1632 external_api::clean_returnvalue(
1633 core_calendar_external::submit_create_update_form_returns(),
1634 core_calendar_external::submit_create_update_form($querystring)
1639 * A user with the moodle/calendar:manageentries capability at the
1640 * site course context should be able to create a site event.
1642 public function test_submit_create_update_form_create_site_event() {
1643 $generator = $this->getDataGenerator();
1644 $user = $generator->create_user();
1645 $context = context_system::instance();
1646 $roleid = $generator->create_role();
1647 $timestart = new DateTime();
1648 $interval = new DateInterval("P1D"); // One day.
1649 $timedurationuntil = new DateTime();
1650 $timedurationuntil->add($interval);
1651 $formdata = [
1652 'id' => 0,
1653 'userid' => $user->id,
1654 'modulename' => '',
1655 'instance' => 0,
1656 'visible' => 1,
1657 'name' => 'Test',
1658 'timestart' => [
1659 'day' => $timestart->format('j'),
1660 'month' => $timestart->format('n'),
1661 'year' => $timestart->format('Y'),
1662 'hour' => $timestart->format('G'),
1663 'minute' => 0,
1665 'eventtype' => 'site',
1666 'description' => [
1667 'text' => '',
1668 'format' => 1,
1669 'itemid' => 0
1671 'duration' => 1,
1672 'timedurationuntil' => [
1673 'day' => $timedurationuntil->format('j'),
1674 'month' => $timedurationuntil->format('n'),
1675 'year' => $timedurationuntil->format('Y'),
1676 'hour' => $timedurationuntil->format('G'),
1677 'minute' => 0,
1681 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1682 $querystring = http_build_query($formdata, '', '&');
1684 $generator->role_assign($roleid, $user->id, $context->id);
1686 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1688 $user->ignoresesskey = true;
1689 $this->resetAfterTest(true);
1690 $this->setUser($user);
1692 $result = external_api::clean_returnvalue(
1693 core_calendar_external::submit_create_update_form_returns(),
1694 core_calendar_external::submit_create_update_form($querystring)
1697 $event = $result['event'];
1698 $this->assertEquals($user->id, $event['userid']);
1699 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1700 $this->assertEquals($formdata['name'], $event['name']);
1704 * A user without the moodle/calendar:manageentries capability at the
1705 * site course context should not be able to create a site event.
1707 public function test_submit_create_update_form_create_site_event_no_permission() {
1708 $generator = $this->getDataGenerator();
1709 $user = $generator->create_user();
1710 $context = context_course::instance(SITEID);
1711 $roleid = $generator->create_role();
1712 $timestart = new DateTime();
1713 $interval = new DateInterval("P1D"); // One day.
1714 $timedurationuntil = new DateTime();
1715 $timedurationuntil->add($interval);
1716 $formdata = [
1717 'id' => 0,
1718 'userid' => $user->id,
1719 'modulename' => '',
1720 'instance' => 0,
1721 'visible' => 1,
1722 'name' => 'Test',
1723 'timestart' => [
1724 'day' => $timestart->format('j'),
1725 'month' => $timestart->format('n'),
1726 'year' => $timestart->format('Y'),
1727 'hour' => $timestart->format('G'),
1728 'minute' => 0,
1730 'eventtype' => 'site',
1731 'description' => [
1732 'text' => '',
1733 'format' => 1,
1735 'duration' => 1,
1736 'timedurationuntil' => [
1737 'day' => $timedurationuntil->format('j'),
1738 'month' => $timedurationuntil->format('n'),
1739 'year' => $timedurationuntil->format('Y'),
1740 'hour' => $timedurationuntil->format('G'),
1741 'minute' => 0,
1745 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1746 $querystring = http_build_query($formdata, '', '&');
1748 $generator->role_assign($roleid, $user->id, $context->id);
1750 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
1752 $user->ignoresesskey = true;
1753 $this->resetAfterTest(true);
1754 $this->setUser($user);
1756 $result = external_api::clean_returnvalue(
1757 core_calendar_external::submit_create_update_form_returns(),
1758 core_calendar_external::submit_create_update_form($querystring)
1761 $this->assertTrue($result['validationerror']);
1765 * A user that has the moodle/calendar:manageentries in a course that they
1766 * are enrolled in should be able to create a course event in that course.
1768 public function test_submit_create_update_form_create_course_event() {
1769 $generator = $this->getDataGenerator();
1770 $user = $generator->create_user();
1771 $course = $generator->create_course();
1772 $context = context_course::instance($course->id);
1773 $roleid = $generator->create_role();
1774 $timestart = new DateTime();
1775 $interval = new DateInterval("P1D"); // One day.
1776 $timedurationuntil = new DateTime();
1777 $timedurationuntil->add($interval);
1778 $formdata = [
1779 'id' => 0,
1780 'userid' => $user->id,
1781 'modulename' => '',
1782 'instance' => 0,
1783 'visible' => 1,
1784 'name' => 'Test',
1785 'timestart' => [
1786 'day' => $timestart->format('j'),
1787 'month' => $timestart->format('n'),
1788 'year' => $timestart->format('Y'),
1789 'hour' => $timestart->format('G'),
1790 'minute' => 0,
1792 'eventtype' => 'course',
1793 'courseid' => $course->id,
1794 'description' => [
1795 'text' => '',
1796 'format' => 1,
1797 'itemid' => 0,
1799 'duration' => 1,
1800 'timedurationuntil' => [
1801 'day' => $timedurationuntil->format('j'),
1802 'month' => $timedurationuntil->format('n'),
1803 'year' => $timedurationuntil->format('Y'),
1804 'hour' => $timedurationuntil->format('G'),
1805 'minute' => 0,
1809 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1810 $querystring = http_build_query($formdata, '', '&');
1812 $generator->enrol_user($user->id, $course->id, 'student');
1813 $generator->role_assign($roleid, $user->id, $context->id);
1815 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1817 $user->ignoresesskey = true;
1818 $this->resetAfterTest(true);
1819 $this->setUser($user);
1821 $result = external_api::clean_returnvalue(
1822 core_calendar_external::submit_create_update_form_returns(),
1823 core_calendar_external::submit_create_update_form($querystring)
1826 $event = $result['event'];
1827 $this->assertEquals($user->id, $event['userid']);
1828 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1829 $this->assertEquals($formdata['name'], $event['name']);
1830 $this->assertEquals($formdata['courseid'], $event['course']['id']);
1834 * A user without the moodle/calendar:manageentries capability in a course
1835 * that they are enrolled in should not be able to create a course event in that course.
1837 public function test_submit_create_update_form_create_course_event_no_permission() {
1838 $generator = $this->getDataGenerator();
1839 $user = $generator->create_user();
1840 $course = $generator->create_course();
1841 $context = context_course::instance($course->id);
1842 $roleid = $generator->create_role();
1843 $timestart = new DateTime();
1844 $interval = new DateInterval("P1D"); // One day.
1845 $timedurationuntil = new DateTime();
1846 $timedurationuntil->add($interval);
1847 $formdata = [
1848 'id' => 0,
1849 'userid' => $user->id,
1850 'modulename' => '',
1851 'instance' => 0,
1852 'visible' => 1,
1853 'name' => 'Test',
1854 'timestart' => [
1855 'day' => $timestart->format('j'),
1856 'month' => $timestart->format('n'),
1857 'year' => $timestart->format('Y'),
1858 'hour' => $timestart->format('G'),
1859 'minute' => 0,
1861 'eventtype' => 'course',
1862 'courseid' => $course->id,
1863 'description' => [
1864 'text' => '',
1865 'format' => 1,
1867 'duration' => 1,
1868 'timedurationuntil' => [
1869 'day' => $timedurationuntil->format('j'),
1870 'month' => $timedurationuntil->format('n'),
1871 'year' => $timedurationuntil->format('Y'),
1872 'hour' => $timedurationuntil->format('G'),
1873 'minute' => 0,
1877 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1878 $querystring = http_build_query($formdata, '', '&');
1880 $generator->enrol_user($user->id, $course->id, 'student');
1881 $generator->role_assign($roleid, $user->id, $context->id);
1883 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
1885 $user->ignoresesskey = true;
1886 $this->resetAfterTest(true);
1887 $this->setUser($user);
1889 $result = external_api::clean_returnvalue(
1890 core_calendar_external::submit_create_update_form_returns(),
1891 core_calendar_external::submit_create_update_form($querystring)
1894 $this->assertTrue($result['validationerror']);
1898 * A user should not be able to create an event for a course that they are
1899 * not enrolled in.
1901 public function test_submit_create_update_form_create_course_event_not_enrolled() {
1902 $generator = $this->getDataGenerator();
1903 $user = $generator->create_user();
1904 $course = $generator->create_course();
1905 $course2 = $generator->create_course();
1906 $context = context_course::instance($course->id);
1907 $roleid = $generator->create_role();
1908 $timestart = new DateTime();
1909 $interval = new DateInterval("P1D"); // One day.
1910 $timedurationuntil = new DateTime();
1911 $timedurationuntil->add($interval);
1912 $formdata = [
1913 'id' => 0,
1914 'userid' => $user->id,
1915 'modulename' => '',
1916 'instance' => 0,
1917 'visible' => 1,
1918 'name' => 'Test',
1919 'timestart' => [
1920 'day' => $timestart->format('j'),
1921 'month' => $timestart->format('n'),
1922 'year' => $timestart->format('Y'),
1923 'hour' => $timestart->format('G'),
1924 'minute' => 0,
1926 'eventtype' => 'course',
1927 'courseid' => $course2->id, // Not enrolled.
1928 'description' => [
1929 'text' => '',
1930 'format' => 1,
1932 'duration' => 1,
1933 'timedurationuntil' => [
1934 'day' => $timedurationuntil->format('j'),
1935 'month' => $timedurationuntil->format('n'),
1936 'year' => $timedurationuntil->format('Y'),
1937 'hour' => $timedurationuntil->format('G'),
1938 'minute' => 0,
1942 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1943 $querystring = http_build_query($formdata, '', '&');
1945 $generator->enrol_user($user->id, $course->id, 'student');
1946 $generator->role_assign($roleid, $user->id, $context->id);
1948 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1950 $user->ignoresesskey = true;
1951 $this->resetAfterTest(true);
1952 $this->setUser($user);
1954 $this->expectException('moodle_exception');
1956 external_api::clean_returnvalue(
1957 core_calendar_external::submit_create_update_form_returns(),
1958 core_calendar_external::submit_create_update_form($querystring)
1963 * A user should be able to create an event for a group that they are a member of in
1964 * a course in which they are enrolled and have the moodle/calendar:manageentries capability.
1966 public function test_submit_create_update_form_create_group_event_group_member_manage_course() {
1967 $generator = $this->getDataGenerator();
1968 $user = $generator->create_user();
1969 $course = $generator->create_course();
1970 $group = $generator->create_group(array('courseid' => $course->id));
1971 $context = context_course::instance($course->id);
1972 $roleid = $generator->create_role();
1973 $timestart = new DateTime();
1974 $interval = new DateInterval("P1D"); // One day.
1975 $timedurationuntil = new DateTime();
1976 $timedurationuntil->add($interval);
1977 $formdata = [
1978 'id' => 0,
1979 'userid' => $user->id,
1980 'modulename' => '',
1981 'instance' => 0,
1982 'visible' => 1,
1983 'name' => 'Test',
1984 'timestart' => [
1985 'day' => $timestart->format('j'),
1986 'month' => $timestart->format('n'),
1987 'year' => $timestart->format('Y'),
1988 'hour' => $timestart->format('G'),
1989 'minute' => 0,
1991 'eventtype' => 'group',
1992 'groupid' => "{$course->id}-{$group->id}", // The form format.
1993 'groupcourseid' => $course->id,
1994 'description' => [
1995 'text' => '',
1996 'format' => 1,
1997 'itemid' => 0
1999 'duration' => 1,
2000 'timedurationuntil' => [
2001 'day' => $timedurationuntil->format('j'),
2002 'month' => $timedurationuntil->format('n'),
2003 'year' => $timedurationuntil->format('Y'),
2004 'hour' => $timedurationuntil->format('G'),
2005 'minute' => 0,
2009 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2010 $querystring = http_build_query($formdata, '', '&');
2012 $generator->enrol_user($user->id, $course->id, 'student');
2013 $generator->role_assign($roleid, $user->id, $context->id);
2014 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
2016 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2018 $user->ignoresesskey = true;
2019 $this->resetAfterTest(true);
2020 $this->setUser($user);
2022 $result = external_api::clean_returnvalue(
2023 core_calendar_external::submit_create_update_form_returns(),
2024 core_calendar_external::submit_create_update_form($querystring)
2027 $event = $result['event'];
2028 $this->assertEquals($user->id, $event['userid']);
2029 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2030 $this->assertEquals($formdata['name'], $event['name']);
2031 $this->assertEquals($group->id, $event['groupid']);
2035 * A user should be able to create an event for a group that they are a member of in
2036 * a course in which they are enrolled and have the moodle/calendar:managegroupentries capability.
2038 public function test_submit_create_update_form_create_group_event_group_member_manage_group_entries() {
2039 $generator = $this->getDataGenerator();
2040 $user = $generator->create_user();
2041 $course = $generator->create_course();
2042 $group = $generator->create_group(array('courseid' => $course->id));
2043 $context = context_course::instance($course->id);
2044 $roleid = $generator->create_role();
2045 $timestart = new DateTime();
2046 $interval = new DateInterval("P1D"); // One day.
2047 $timedurationuntil = new DateTime();
2048 $timedurationuntil->add($interval);
2049 $formdata = [
2050 'id' => 0,
2051 'userid' => $user->id,
2052 'modulename' => '',
2053 'instance' => 0,
2054 'visible' => 1,
2055 'name' => 'Test',
2056 'timestart' => [
2057 'day' => $timestart->format('j'),
2058 'month' => $timestart->format('n'),
2059 'year' => $timestart->format('Y'),
2060 'hour' => $timestart->format('G'),
2061 'minute' => 0,
2063 'eventtype' => 'group',
2064 'groupid' => "{$course->id}-{$group->id}", // The form format.
2065 'groupcourseid' => $course->id,
2066 'description' => [
2067 'text' => '',
2068 'format' => 1,
2069 'itemid' => 0
2071 'duration' => 1,
2072 'timedurationuntil' => [
2073 'day' => $timedurationuntil->format('j'),
2074 'month' => $timedurationuntil->format('n'),
2075 'year' => $timedurationuntil->format('Y'),
2076 'hour' => $timedurationuntil->format('G'),
2077 'minute' => 0,
2081 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2082 $querystring = http_build_query($formdata, '', '&');
2084 $generator->enrol_user($user->id, $course->id, 'student');
2085 $generator->role_assign($roleid, $user->id, $context->id);
2086 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
2088 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
2089 assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
2091 $user->ignoresesskey = true;
2092 $this->resetAfterTest(true);
2093 $this->setUser($user);
2095 $result = external_api::clean_returnvalue(
2096 core_calendar_external::submit_create_update_form_returns(),
2097 core_calendar_external::submit_create_update_form($querystring)
2100 $event = $result['event'];
2101 $this->assertEquals($user->id, $event['userid']);
2102 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2103 $this->assertEquals($formdata['name'], $event['name']);
2104 $this->assertEquals($group->id, $event['groupid']);
2108 * A user should be able to create an event for any group in a course in which
2109 * they are enrolled and have the moodle/site:accessallgroups capability.
2111 public function test_submit_create_update_form_create_group_event_access_all_groups() {
2112 $generator = $this->getDataGenerator();
2113 $user = $generator->create_user();
2114 $course = $generator->create_course();
2115 $group = $generator->create_group(array('courseid' => $course->id));
2116 $context = context_course::instance($course->id);
2117 $roleid = $generator->create_role();
2118 $timestart = new DateTime();
2119 $interval = new DateInterval("P1D"); // One day.
2120 $timedurationuntil = new DateTime();
2121 $timedurationuntil->add($interval);
2122 $formdata = [
2123 'id' => 0,
2124 'userid' => $user->id,
2125 'modulename' => '',
2126 'instance' => 0,
2127 'visible' => 1,
2128 'name' => 'Test',
2129 'timestart' => [
2130 'day' => $timestart->format('j'),
2131 'month' => $timestart->format('n'),
2132 'year' => $timestart->format('Y'),
2133 'hour' => $timestart->format('G'),
2134 'minute' => 0,
2136 'eventtype' => 'group',
2137 'groupid' => "{$course->id}-{$group->id}", // The form format.
2138 'groupcourseid' => $course->id,
2139 'description' => [
2140 'text' => '',
2141 'format' => 1,
2142 'itemid' => 0
2144 'duration' => 1,
2145 'timedurationuntil' => [
2146 'day' => $timedurationuntil->format('j'),
2147 'month' => $timedurationuntil->format('n'),
2148 'year' => $timedurationuntil->format('Y'),
2149 'hour' => $timedurationuntil->format('G'),
2150 'minute' => 0,
2154 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2155 $querystring = http_build_query($formdata, '', '&');
2157 $generator->enrol_user($user->id, $course->id, 'student');
2158 $generator->role_assign($roleid, $user->id, $context->id);
2160 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2161 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
2163 $user->ignoresesskey = true;
2164 $this->resetAfterTest(true);
2165 $this->setUser($user);
2167 $result = external_api::clean_returnvalue(
2168 core_calendar_external::submit_create_update_form_returns(),
2169 core_calendar_external::submit_create_update_form($querystring)
2172 $event = $result['event'];
2173 $this->assertEquals($user->id, $event['userid']);
2174 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2175 $this->assertEquals($formdata['name'], $event['name']);
2176 $this->assertEquals($group->id, $event['groupid']);
2180 * A user should not be able to create an event for any group that they are not a
2181 * member of in a course in which they are enrolled but don't have the
2182 * moodle/site:accessallgroups capability.
2184 public function test_submit_create_update_form_create_group_event_non_member_no_permission() {
2185 $generator = $this->getDataGenerator();
2186 $user = $generator->create_user();
2187 $course = $generator->create_course();
2188 $group = $generator->create_group(array('courseid' => $course->id));
2189 $context = context_course::instance($course->id);
2190 $roleid = $generator->create_role();
2191 $timestart = new DateTime();
2192 $interval = new DateInterval("P1D"); // One day.
2193 $timedurationuntil = new DateTime();
2194 $timedurationuntil->add($interval);
2195 $formdata = [
2196 'id' => 0,
2197 'userid' => $user->id,
2198 'modulename' => '',
2199 'instance' => 0,
2200 'visible' => 1,
2201 'name' => 'Test',
2202 'timestart' => [
2203 'day' => $timestart->format('j'),
2204 'month' => $timestart->format('n'),
2205 'year' => $timestart->format('Y'),
2206 'hour' => $timestart->format('G'),
2207 'minute' => 0,
2209 'eventtype' => 'group',
2210 'groupid' => "{$course->id}-{$group->id}", // The form format.
2211 'groupcourseid' => $course->id,
2212 'description' => [
2213 'text' => '',
2214 'format' => 1,
2216 'duration' => 1,
2217 'timedurationuntil' => [
2218 'day' => $timedurationuntil->format('j'),
2219 'month' => $timedurationuntil->format('n'),
2220 'year' => $timedurationuntil->format('Y'),
2221 'hour' => $timedurationuntil->format('G'),
2222 'minute' => 0,
2226 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2227 $querystring = http_build_query($formdata, '', '&');
2229 $generator->enrol_user($user->id, $course->id, 'student');
2230 $generator->role_assign($roleid, $user->id, $context->id);
2232 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2233 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
2235 $user->ignoresesskey = true;
2236 $this->resetAfterTest(true);
2237 $this->setUser($user);
2239 $result = external_api::clean_returnvalue(
2240 core_calendar_external::submit_create_update_form_returns(),
2241 core_calendar_external::submit_create_update_form($querystring)
2244 $this->assertTrue($result['validationerror']);
2248 * A user should not be able load the calendar monthly view for a course they cannot access.
2250 public function test_get_calendar_monthly_view_no_course_permission() {
2251 global $USER;
2252 $this->resetAfterTest(true);
2253 $this->setAdminUser();
2255 $generator = $this->getDataGenerator();
2256 $user1 = $generator->create_user();
2257 $user2 = $generator->create_user();
2258 $course = $generator->create_course();
2259 $generator->enrol_user($user1->id, $course->id, 'student');
2260 $name = 'Course Event (course' . $course->id . ')';
2261 $record = new stdClass();
2262 $record->courseid = $course->id;
2263 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2265 $timestart = new DateTime();
2266 // Admin can load the course.
2267 $data = external_api::clean_returnvalue(
2268 core_calendar_external::get_calendar_monthly_view_returns(),
2269 core_calendar_external::get_calendar_monthly_view($timestart->format('n'), $timestart->format('Y'),
2270 $course->id, null, false)
2272 $this->assertEquals($data['courseid'], $course->id);
2273 // User enrolled in the course can load the course calendar.
2274 $this->setUser($user1);
2275 $data = external_api::clean_returnvalue(
2276 core_calendar_external::get_calendar_monthly_view_returns(),
2277 core_calendar_external::get_calendar_monthly_view($timestart->format('n'), $timestart->format('Y'),
2278 $course->id, null, false)
2280 $this->assertEquals($data['courseid'], $course->id);
2281 // User not enrolled in the course cannot load the course calendar.
2282 $this->setUser($user2);
2283 $this->expectException('require_login_exception');
2284 $data = external_api::clean_returnvalue(
2285 core_calendar_external::get_calendar_monthly_view_returns(),
2286 core_calendar_external::get_calendar_monthly_view($timestart->format('n'), $timestart->format('Y'),
2287 $course->id, null, false)
2292 * A user should not be able load the calendar day view for a course they cannot access.
2294 public function test_get_calendar_day_view_no_course_permission() {
2295 global $USER;
2296 $this->resetAfterTest(true);
2297 $this->setAdminUser();
2299 $generator = $this->getDataGenerator();
2300 $user1 = $generator->create_user();
2301 $user2 = $generator->create_user();
2302 $course = $generator->create_course();
2303 $generator->enrol_user($user1->id, $course->id, 'student');
2304 $name = 'Course Event (course' . $course->id . ')';
2305 $record = new stdClass();
2306 $record->courseid = $course->id;
2307 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2309 $timestart = new DateTime();
2310 // Admin can load the course.
2311 $data = external_api::clean_returnvalue(
2312 core_calendar_external::get_calendar_day_view_returns(),
2313 core_calendar_external::get_calendar_day_view($timestart->format('n'), $timestart->format('Y'),
2314 $timestart->format('j'), $course->id, null)
2316 $this->assertEquals($data['courseid'], $course->id);
2317 // User enrolled in the course can load the course calendar.
2318 $this->setUser($user1);
2319 $data = external_api::clean_returnvalue(
2320 core_calendar_external::get_calendar_day_view_returns(),
2321 core_calendar_external::get_calendar_day_view($timestart->format('n'), $timestart->format('Y'),
2322 $timestart->format('j'), $course->id, null)
2324 $this->assertEquals($data['courseid'], $course->id);
2325 // User not enrolled in the course cannot load the course calendar.
2326 $this->setUser($user2);
2327 $this->expectException('require_login_exception');
2328 $data = external_api::clean_returnvalue(
2329 core_calendar_external::get_calendar_day_view_returns(),
2330 core_calendar_external::get_calendar_day_view($timestart->format('n'), $timestart->format('Y'),
2331 $timestart->format('j'), $course->id, null)
2336 * A user should not be able load the calendar upcoming view for a course they cannot access.
2338 public function test_get_calendar_upcoming_view_no_course_permission() {
2339 global $USER;
2340 $this->resetAfterTest(true);
2341 $this->setAdminUser();
2343 $generator = $this->getDataGenerator();
2344 $user1 = $generator->create_user();
2345 $user2 = $generator->create_user();
2346 $course = $generator->create_course();
2347 $generator->enrol_user($user1->id, $course->id, 'student');
2348 $name = 'Course Event (course' . $course->id . ')';
2349 $record = new stdClass();
2350 $record->courseid = $course->id;
2351 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2353 // Admin can load the course.
2354 $data = external_api::clean_returnvalue(
2355 core_calendar_external::get_calendar_upcoming_view_returns(),
2356 core_calendar_external::get_calendar_upcoming_view($course->id, null)
2358 $this->assertEquals($data['courseid'], $course->id);
2359 // User enrolled in the course can load the course calendar.
2360 $this->setUser($user1);
2361 $data = external_api::clean_returnvalue(
2362 core_calendar_external::get_calendar_upcoming_view_returns(),
2363 core_calendar_external::get_calendar_upcoming_view($course->id, null)
2365 $this->assertEquals($data['courseid'], $course->id);
2366 // User not enrolled in the course cannot load the course calendar.
2367 $this->setUser($user2);
2368 $this->expectException('require_login_exception');
2369 $data = external_api::clean_returnvalue(
2370 core_calendar_external::get_calendar_upcoming_view_returns(),
2371 core_calendar_external::get_calendar_upcoming_view($course->id, null)
2376 * A user should not be able load the calendar event for a course they cannot access.
2378 public function test_get_calendar_event_by_id_no_course_permission() {
2379 global $USER;
2380 $this->resetAfterTest(true);
2381 $this->setAdminUser();
2383 $generator = $this->getDataGenerator();
2384 $user1 = $generator->create_user();
2385 $user2 = $generator->create_user();
2386 $course = $generator->create_course();
2387 $generator->enrol_user($user1->id, $course->id, 'student');
2388 $name = 'Course Event (course' . $course->id . ')';
2389 $record = new stdClass();
2390 $record->courseid = $course->id;
2391 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2393 // Admin can load the course event.
2394 $data = external_api::clean_returnvalue(
2395 core_calendar_external::get_calendar_event_by_id_returns(),
2396 core_calendar_external::get_calendar_event_by_id($courseevent->id)
2398 $this->assertEquals($data['event']['id'], $courseevent->id);
2399 // User enrolled in the course can load the course event.
2400 $this->setUser($user1);
2401 $data = external_api::clean_returnvalue(
2402 core_calendar_external::get_calendar_event_by_id_returns(),
2403 core_calendar_external::get_calendar_event_by_id($courseevent->id)
2405 $this->assertEquals($data['event']['id'], $courseevent->id);
2406 // User not enrolled in the course cannot load the course event.
2407 $this->setUser($user2);
2408 $this->expectException('required_capability_exception');
2409 $data = external_api::clean_returnvalue(
2410 core_calendar_external::get_calendar_event_by_id_returns(),
2411 core_calendar_external::get_calendar_event_by_id($courseevent->id)
2416 * A user should not be able load the calendar events for a category they cannot see.
2418 public function test_get_calendar_events_hidden_category() {
2419 global $USER;
2420 $this->resetAfterTest(true);
2421 $this->setAdminUser();
2423 $generator = $this->getDataGenerator();
2424 $user1 = $generator->create_user();
2425 $category = $generator->create_category(['visible' => 0]);
2426 $name = 'Category Event (category: ' . $category->id . ')';
2427 $record = new stdClass();
2428 $record->categoryid = $category->id;
2429 $categoryevent = $this->create_calendar_event($name, $USER->id, 'category', 0, time(), $record);
2431 $events = [
2432 'eventids' => [$categoryevent->id]
2434 $options = [];
2435 // Admin can load the category event.
2436 $data = external_api::clean_returnvalue(
2437 core_calendar_external::get_calendar_events_returns(),
2438 core_calendar_external::get_calendar_events($events, $options)
2440 $this->assertEquals($data['events'][0]['id'], $categoryevent->id);
2441 // User with no special permission to see hidden categories will not see the event.
2442 $this->setUser($user1);
2443 $data = external_api::clean_returnvalue(
2444 core_calendar_external::get_calendar_events_returns(),
2445 core_calendar_external::get_calendar_events($events, $options)
2447 $this->assertCount(0, $data['events']);
2448 $this->assertEquals('nopermissions', $data['warnings'][0]['warningcode']);