MDL-60626 calendar: Check capabilities for api
[moodle.git] / calendar / tests / externallib_test.php
CommitLineData
644a7ef7
AA
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * External calendar functions unit tests
19 *
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
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29
30require_once($CFG->dirroot . '/webservice/tests/helpers.php');
31
32/**
33 * External course functions unit tests
34 *
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
40 */
8252b7c2 41class core_calendar_externallib_testcase extends externallib_advanced_testcase {
644a7ef7
AA
42
43 /**
44 * Tests set up
45 */
46 protected function setUp() {
47 global $CFG;
48 require_once($CFG->dirroot . '/calendar/externallib.php');
49 }
50
51 /** Create calendar events or update them
52 * Set $prop->id, if you want to do an update instead of creating an new event
53 *
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
62 */
63
64 public static function create_calendar_event($name, $userid = 0, $type = 'user', $repeats = 0, $timestart = null, $prop = null) {
f52459bb 65 global $CFG, $DB, $SITE;
644a7ef7
AA
66
67 require_once("$CFG->dirroot/calendar/lib.php");
68 if (!empty($prop)) {
261a41f1
AA
69 if (is_array($prop)) {
70 $prop = (object)$prop;
71 }
644a7ef7
AA
72 } else {
73 $prop = new stdClass();
74 }
75 $prop->name = $name;
76 if (empty($prop->eventtype)) {
77 $prop->eventtype = $type;
78 }
79 if (empty($prop->repeats)) {
80 $prop->repeats = $repeats;
81 }
82 if (empty($prop->timestart)) {
83 $prop->timestart = time();
84 }
85 if (empty($prop->timeduration)) {
86 $prop->timeduration = 0;
87 }
4139f131
RW
88 if (empty($prop->timesort)) {
89 $prop->timesort = 0;
90 }
91 if (empty($prop->type)) {
92 $prop->type = CALENDAR_EVENT_TYPE_STANDARD;
93 }
644a7ef7
AA
94 if (empty($prop->repeats)) {
95 $prop->repeat = 0;
96 } else {
97 $prop->repeat = 1;
98 }
99 if (empty($prop->userid)) {
261a41f1 100 if (!empty($userid)) {
644a7ef7 101 $prop->userid = $userid;
261a41f1 102 } else {
5900513f 103 $prop->userid = 0;
261a41f1 104 }
644a7ef7 105 }
5ac3b20d 106 if (!isset($prop->courseid)) {
644a7ef7
AA
107 $prop->courseid = $SITE->id;
108 }
f52459bb
JP
109
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;
124 }
125 }
126 $prop->priority = $priority;
127 }
128
e1cd93ce 129 $event = new calendar_event($prop);
644a7ef7
AA
130 return $event->create($prop);
131 }
132
133 public function test_create_calendar_events () {
134 global $DB, $USER;
135
136 $this->setAdminUser();
137 $this->resetAfterTest();
138 $prevcount = count($DB->get_records("event"));
139
140 // Create a few events and do asserts.
141 $this->create_calendar_event('test', $USER->id);
9dadb590
AA
142 $where = $DB->sql_compare_text('name') ." = ?";
143 $count = count($DB->get_records_select("event", $where, array('test')));
644a7ef7
AA
144 $this->assertEquals(1, $count);
145 $aftercount = count($DB->get_records("event"));
146 $this->assertEquals($prevcount + 1, $aftercount);
147
148 $this->create_calendar_event('user', $USER->id, 'user', 3);
9dadb590
AA
149 $where = $DB->sql_compare_text('name') ." = ?";
150 $count = count($DB->get_records_select("event", $where, array('user')));
151
644a7ef7
AA
152 $this->assertEquals(3, $count);
153 $aftercount = count($DB->get_records("event"));
154 $this->assertEquals($prevcount + 4, $aftercount);
155
156 }
157
158 /**
261a41f1 159 * Test delete_calendar_events
52f3e060
RT
160 *
161 * @expectedException moodle_exception
644a7ef7
AA
162 */
163 public function test_delete_calendar_events() {
164 global $DB, $USER;
165
166 $this->resetAfterTest(true);
167 $this->setAdminUser();
168
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);
175
176 $notdeletedcount = $DB->count_records('event');
177
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);
188
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)
195 );
196 core_calendar_external::delete_calendar_events($events);
197
198 // Check to see if things were deleted properly.
199 $deletedcount = $DB->count_records('event');
200 $this->assertEquals($notdeletedcount, $deletedcount);
201
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);
212
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);
219
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);
225
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),
230 );
231 core_calendar_external::delete_calendar_events($events);
232 $deletedcount = $DB->count_records('event');
233 $count = $notdeletedcount+5;
234 $this->assertEquals($count, $deletedcount);
235
236 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);
237 $events = array(
238 array('eventid' => $courseevent->id, 'repeat' => 0),
239 );
240 core_calendar_external::delete_calendar_events($events);
241 $deletedcount = $DB->count_records('event');
242 $count = $notdeletedcount+4;
243 $this->assertEquals($count, $deletedcount);
244
245 $this->assignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id);
246 $events = array(
247 array('eventid' => $userevent->id, 'repeat' => 0),
248 );
249 core_calendar_external::delete_calendar_events($events);
250 $deletedcount = $DB->count_records('event');
251 $count = $notdeletedcount+3;
252 $this->assertEquals($count, $deletedcount);
253
254 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
255 $events = array(
256 array('eventid' => $groupevent->id, 'repeat' => 0),
257 );
258 core_calendar_external::delete_calendar_events($events);
259 $deletedcount = $DB->count_records('event');
260 $count = $notdeletedcount+2;
261 $this->assertEquals($count, $deletedcount);
262
263 $notdeletedcount = $deletedcount;
264
265 // Let us try deleting without caps.
266
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);
276
277 $this->setGuestUser();
52f3e060 278
644a7ef7
AA
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)
284 );
285 core_calendar_external::delete_calendar_events($events);
286 }
287
261a41f1
AA
288 /**
289 * Test get_calendar_events
7c30224a
AA
290 */
291 public function test_get_calendar_events() {
292 global $DB, $USER;
293
294 $this->resetAfterTest(true);
f52459bb 295 set_config('calendar_adminseesall', 1);
7c30224a
AA
296 $this->setAdminUser();
297
298 // Create a few stuff to test with.
299 $user = $this->getDataGenerator()->create_user();
300 $course = $this->getDataGenerator()->create_course();
301 $record = new stdClass();
302 $record->courseid = $course->id;
303 $group = $this->getDataGenerator()->create_group($record);
304
305 $beforecount = $DB->count_records('event');
306
307 // Let's create a few events.
261a41f1 308 $siteevent = $this->create_calendar_event('site', $USER->id, 'site');
871988b0
JL
309
310 // This event will have description with an inline fake image.
311 $draftidfile = file_get_unused_draft_itemid();
312 $usercontext = context_course::instance($course->id);
313 $filerecord = array(
314 'contextid' => $usercontext->id,
315 'component' => 'user',
316 'filearea' => 'draft',
317 'itemid' => $draftidfile,
318 'filepath' => '/',
319 'filename' => 'fakeimage.png',
320 );
321 $fs = get_file_storage();
322 $fs->create_file_from_string($filerecord, 'img contents');
323
7c30224a
AA
324 $record = new stdClass();
325 $record->courseid = $course->id;
f52459bb 326 $record->groupid = 0;
871988b0
JL
327 $record->description = array(
328 'format' => FORMAT_HTML,
329 'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">',
330 'itemid' => $draftidfile
331 );
261a41f1 332 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record);
f52459bb
JP
333
334 $record = new stdClass();
335 $record->courseid = 0;
336 $record->groupid = 0;
337 $userevent = $this->create_calendar_event('user', $USER->id, 'user', 0, time(), $record);
338
7c30224a
AA
339 $record = new stdClass();
340 $record->courseid = $course->id;
341 $record->groupid = $group->id;
261a41f1 342 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);
7c30224a
AA
343
344 $paramevents = array ('eventids' => array($siteevent->id), 'courseids' => array($course->id), 'groupids' => array($group->id));
345 $options = array ('siteevents' => true, 'userevents' => true);
346 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1 347 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
7c30224a
AA
348
349 // Check to see if we got all events.
ef5b65da 350 $this->assertEquals(5, count($events['events']));
261a41f1 351 $this->assertEquals(0, count($events['warnings']));
7c30224a
AA
352 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7*WEEKSECS);
353 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
354 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
355 $this->assertEquals(5, count($events['events']));
356 $this->assertEquals(0, count($events['warnings']));
7c30224a 357
871988b0
JL
358 // Expect the same URL in the description of two different events (because they are repeated).
359 $coursecontext = context_course::instance($course->id);
360 $expectedurl = "webservice/pluginfile.php/$coursecontext->id/calendar/event_description/$courseevent->id/fakeimage.png";
361 $withdescription = 0;
362 foreach ($events['events'] as $event) {
363 if (!empty($event['description'])) {
364 $withdescription++;
365 $this->assertContains($expectedurl, $event['description']);
366 }
367 }
368 $this->assertEquals(2, $withdescription);
369
7c30224a 370 // Let's play around with caps.
f52459bb
JP
371
372 // Create user event for the user $user.
373 $record = new stdClass();
374 $record->courseid = 0;
375 $record->groupid = 0;
376 $this->create_calendar_event('user', $user->id, 'user', 0, time(), $record);
377
7c30224a
AA
378 $this->setUser($user);
379 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
380 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
381 $this->assertEquals(2, count($events['events'])); // site, user.
382 $this->assertEquals(2, count($events['warnings'])); // course, group.
7c30224a
AA
383
384 $role = $DB->get_record('role', array('shortname' => 'student'));
385 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
386 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
387 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
388 $this->assertEquals(4, count($events['events'])); // site, user, both course events.
389 $this->assertEquals(1, count($events['warnings'])); // group.
7c30224a 390
ef5b65da 391 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS);
7c30224a 392 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
393 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
394 $this->assertEquals(3, count($events['events'])); // site, user, one course event.
395 $this->assertEquals(1, count($events['warnings'])); // group.
7c30224a
AA
396
397 groups_add_member($group, $user);
398 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
399 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
400 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
401 $this->assertEquals(0, count($events['warnings']));
7c30224a
AA
402
403 $paramevents = array ('courseids' => array($course->id), 'groupids' => array($group->id));
404 $events = core_calendar_external::get_calendar_events($paramevents, $options);
e2c85157 405 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
261a41f1
AA
406 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
407 $this->assertEquals(0, count($events['warnings']));
7c30224a 408
261a41f1 409 $paramevents = array ('groupids' => array($group->id, 23));
7c30224a 410 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
411 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
412 $this->assertEquals(3, count($events['events'])); // site, user, group.
413 $this->assertEquals(1, count($events['warnings']));
7c30224a 414
261a41f1 415 $paramevents = array ('courseids' => array(23));
7c30224a 416 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
417 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
418 $this->assertEquals(2, count($events['events'])); // site, user.
419 $this->assertEquals(1, count($events['warnings']));
7c30224a
AA
420
421 $paramevents = array ();
422 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);
423 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
424 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
425 $this->assertEquals(0, count($events['events'])); // nothing returned.
426 $this->assertEquals(0, count($events['warnings']));
7c30224a
AA
427
428 $paramevents = array ('eventids' => array($siteevent->id, $groupevent->id));
429 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);
430 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
431 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
432 $this->assertEquals(2, count($events['events'])); // site, group.
433 $this->assertEquals(0, count($events['warnings']));
7c30224a
AA
434
435 $paramevents = array ('eventids' => array($siteevent->id));
436 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
437 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
438 $this->assertEquals(1, count($events['events'])); // site.
439 $this->assertEquals(0, count($events['warnings']));
11dc7c1c
NM
440
441 // Try getting a course event by its id.
442 $paramevents = array ('eventids' => array($courseevent->id));
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(1, count($events['events']));
446 $this->assertEquals(0, count($events['warnings']));
39b85137
JL
447
448 // Now, create an activity event.
449 $this->setAdminUser();
450 $nexttime = time() + DAYSECS;
451 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'duedate' => $nexttime));
452
453 $this->setUser($user);
454 $paramevents = array ('courseids' => array($course->id));
455 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS);
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
459 $this->assertCount(5, $events['events']);
460
461 // Hide the assignment.
462 set_coursemodule_visible($assign->cmid, 0);
463 // Empty all the caches that may be affected by this change.
464 accesslib_clear_all_caches_for_unit_testing();
465 course_modinfo::clear_instance_cache();
466
467 $events = core_calendar_external::get_calendar_events($paramevents, $options);
468 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
469 // Expect one less.
470 $this->assertCount(4, $events['events']);
7c30224a 471 }
15c0b1cc
AA
472
473 /**
474 * Test core_calendar_external::create_calendar_events
475 */
476 public function test_core_create_calendar_events() {
477 global $DB, $USER, $SITE;
478
479 $this->resetAfterTest(true);
480 $this->setAdminUser();
481
482 // Create a few stuff to test with.
483 $user = $this->getDataGenerator()->create_user();
484 $course = $this->getDataGenerator()->create_course();
485 $record = new stdClass();
486 $record->courseid = $course->id;
487 $group = $this->getDataGenerator()->create_group($record);
488
489 $prevcount = $DB->count_records('event');
490
491 // Let's create a few events.
492 $events = array (
493 array('name' => 'site', 'courseid' => $SITE->id, 'eventtype' => 'site'),
494 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),
495 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),
496 array('name' => 'user')
497 );
498 $eventsret = core_calendar_external::create_calendar_events($events);
e2c85157 499 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
15c0b1cc
AA
500
501 // Check to see if things were created properly.
502 $aftercount = $DB->count_records('event');
503 $this->assertEquals($prevcount + 5, $aftercount);
504 $this->assertEquals(5, count($eventsret['events']));
505 $this->assertEquals(0, count($eventsret['warnings']));
506
507 $sitecontext = context_system::instance();
508 $coursecontext = context_course::instance($course->id);
509
510 $this->setUser($user);
511 $prevcount = $aftercount;
512 $events = array (
513 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),
514 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),
515 array('name' => 'user')
516 );
517 $role = $DB->get_record('role', array('shortname' => 'student'));
518 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
519 groups_add_member($group, $user);
520 $this->assignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
521 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
522 $eventsret = core_calendar_external::create_calendar_events($events);
523 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
524 // Check to see if things were created properly.
525 $aftercount = $DB->count_records('event');
526 $this->assertEquals($prevcount + 4, $aftercount);
527 $this->assertEquals(4, count($eventsret['events']));
528 $this->assertEquals(0, count($eventsret['warnings']));
529
530 // Check to see nothing was created without proper permission.
531 $this->setGuestUser();
532 $prevcount = $DB->count_records('event');
533 $eventsret = core_calendar_external::create_calendar_events($events);
534 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
535 $aftercount = $DB->count_records('event');
536 $this->assertEquals($prevcount, $aftercount);
537 $this->assertEquals(0, count($eventsret['events']));
538 $this->assertEquals(3, count($eventsret['warnings']));
539
540 $this->setUser($user);
541 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
542 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
543 $prevcount = $DB->count_records('event');
544 $eventsret = core_calendar_external::create_calendar_events($events);
545 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
546 $aftercount = $DB->count_records('event');
547 $this->assertEquals($prevcount + 1, $aftercount); // User event.
548 $this->assertEquals(1, count($eventsret['events']));
549 $this->assertEquals(2, count($eventsret['warnings']));
550 }
4139f131
RW
551
552 /**
553 * Requesting calendar events from a given time should return all events with a sort
554 * time at or after the requested time. All events prior to that time should not
555 * be return.
556 *
557 * If there are no events on or after the given time then an empty result set should
558 * be returned.
559 */
1aeb58fa 560 public function test_get_calendar_action_events_by_timesort_after_time() {
4139f131
RW
561 $user = $this->getDataGenerator()->create_user();
562 $course = $this->getDataGenerator()->create_course();
563 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
564 $moduleinstance = $generator->create_instance(['course' => $course->id]);
565
566 $this->getDataGenerator()->enrol_user($user->id, $course->id);
567 $this->resetAfterTest(true);
568 $this->setUser($user);
569
570 $params = [
571 'type' => CALENDAR_EVENT_TYPE_ACTION,
572 'modulename' => 'assign',
573 'instance' => $moduleinstance->id,
574 'courseid' => $course->id,
575 ];
576
577 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
578 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
579 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
580 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
581 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
582 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
583 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
584 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
585
586 $result = core_calendar_external::get_calendar_action_events_by_timesort(5);
587 $result = external_api::clean_returnvalue(
588 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
589 $result
590 );
591 $events = $result['events'];
592
593 $this->assertCount(4, $events);
594 $this->assertEquals('Event 5', $events[0]['name']);
595 $this->assertEquals('Event 6', $events[1]['name']);
596 $this->assertEquals('Event 7', $events[2]['name']);
597 $this->assertEquals('Event 8', $events[3]['name']);
598 $this->assertEquals($event5->id, $result['firstid']);
599 $this->assertEquals($event8->id, $result['lastid']);
600
601 $result = core_calendar_external::get_calendar_action_events_by_timesort(9);
602 $result = external_api::clean_returnvalue(
603 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
604 $result
605 );
606
607 $this->assertEmpty($result['events']);
608 $this->assertNull($result['firstid']);
609 $this->assertNull($result['lastid']);
610 }
611
612 /**
613 * Requesting calendar events before a given time should return all events with a sort
614 * time at or before the requested time (inclusive). All events after that time
615 * should not be returned.
616 *
617 * If there are no events before the given time then an empty result set should be
618 * returned.
619 */
1aeb58fa 620 public function test_get_calendar_action_events_by_timesort_before_time() {
4139f131
RW
621 $user = $this->getDataGenerator()->create_user();
622 $course = $this->getDataGenerator()->create_course();
623 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
624 $moduleinstance = $generator->create_instance(['course' => $course->id]);
625
626 $this->getDataGenerator()->enrol_user($user->id, $course->id);
627 $this->resetAfterTest(true);
628 $this->setUser($user);
629
630 $params = [
631 'type' => CALENDAR_EVENT_TYPE_ACTION,
632 'modulename' => 'assign',
633 'instance' => $moduleinstance->id,
634 'courseid' => $course->id,
635 ];
636
637 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
638 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
639 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
640 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
641 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
642 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
643 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
644 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 9]));
645
646 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5);
647 $result = external_api::clean_returnvalue(
648 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
649 $result
650 );
651 $events = $result['events'];
652
653 $this->assertCount(4, $events);
654 $this->assertEquals('Event 1', $events[0]['name']);
655 $this->assertEquals('Event 2', $events[1]['name']);
656 $this->assertEquals('Event 3', $events[2]['name']);
657 $this->assertEquals('Event 4', $events[3]['name']);
658 $this->assertEquals($event1->id, $result['firstid']);
659 $this->assertEquals($event4->id, $result['lastid']);
660
661 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 1);
662 $result = external_api::clean_returnvalue(
663 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
664 $result
665 );
666
667 $this->assertEmpty($result['events']);
668 $this->assertNull($result['firstid']);
669 $this->assertNull($result['lastid']);
670 }
671
5900513f
MG
672 /**
673 * Test retrieving event that was overridden for a user
674 */
675 public function test_get_calendar_events_override() {
676 $user = $this->getDataGenerator()->create_user();
63e9e382 677 $user2 = $this->getDataGenerator()->create_user();
5900513f
MG
678 $teacher = $this->getDataGenerator()->create_user();
679 $anotheruser = $this->getDataGenerator()->create_user();
680 $course = $this->getDataGenerator()->create_course();
681 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
682 $moduleinstance = $generator->create_instance(['course' => $course->id]);
683
63e9e382
MG
684 $this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
685 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
5900513f
MG
686 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
687 $this->resetAfterTest(true);
688 $this->setAdminUser();
689
690 $params = [
691 'type' => CALENDAR_EVENT_TYPE_ACTION,
692 'modulename' => 'assign',
693 'instance' => $moduleinstance->id,
694 ];
695
696 $now = time();
63e9e382 697 // Create two events - one for everybody in the course and one only for the first student.
5900513f
MG
698 $event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS, $params + ['courseid' => $course->id]);
699 $event2 = $this->create_calendar_event('User event', $user->id, 'due', 0, $now + 2*DAYSECS, $params + ['courseid' => 0]);
700
63e9e382
MG
701 // Retrieve course events for the second student - only one "Base event" is returned.
702 $this->setUser($user2);
5900513f
MG
703 $paramevents = array('courseids' => array($course->id));
704 $options = array ('siteevents' => true, 'userevents' => true);
705 $events = core_calendar_external::get_calendar_events($paramevents, $options);
706 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
707 $this->assertEquals(1, count($events['events']));
708 $this->assertEquals(0, count($events['warnings']));
709 $this->assertEquals('Base event', $events['events'][0]['name']);
710
63e9e382 711 // Retrieve events for the first student - both events are returned.
5900513f
MG
712 $this->setUser($user);
713 $events = core_calendar_external::get_calendar_events($paramevents, $options);
714 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
715 $this->assertEquals(2, count($events['events']));
716 $this->assertEquals(0, count($events['warnings']));
717 $this->assertEquals('Base event', $events['events'][0]['name']);
718 $this->assertEquals('User event', $events['events'][1]['name']);
719
720 // Retrieve events by id as a teacher, 'User event' should be returned since teacher has access to this course.
721 $this->setUser($teacher);
722 $paramevents = ['eventids' => [$event2->id]];
723 $events = core_calendar_external::get_calendar_events($paramevents, $options);
724 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
725 $this->assertEquals(1, count($events['events']));
726 $this->assertEquals(0, count($events['warnings']));
727 $this->assertEquals('User event', $events['events'][0]['name']);
728
729 // Retrieve events by id as another user, nothing should be returned.
730 $this->setUser($anotheruser);
731 $paramevents = ['eventids' => [$event2->id, $event1->id]];
732 $events = core_calendar_external::get_calendar_events($paramevents, $options);
733 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
734 $this->assertEquals(0, count($events['events']));
735 $this->assertEquals(0, count($events['warnings']));
736 }
737
4139f131
RW
738 /**
739 * Requesting calendar events within a given time range should return all events with
740 * a sort time between the lower and upper time bound (inclusive).
741 *
742 * If there are no events in the given time range then an empty result set should be
743 * returned.
744 */
1aeb58fa 745 public function test_get_calendar_action_events_by_timesort_time_range() {
4139f131
RW
746 $user = $this->getDataGenerator()->create_user();
747 $course = $this->getDataGenerator()->create_course();
748 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
749 $moduleinstance = $generator->create_instance(['course' => $course->id]);
750
751 $this->getDataGenerator()->enrol_user($user->id, $course->id);
752 $this->resetAfterTest(true);
753 $this->setUser($user);
754
755 $params = [
756 'type' => CALENDAR_EVENT_TYPE_ACTION,
757 'modulename' => 'assign',
758 'instance' => $moduleinstance->id,
759 'courseid' => $course->id,
760 ];
761
762 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
763 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
764 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
765 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
766 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
767 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
768 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
769 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
770
771 $result = core_calendar_external::get_calendar_action_events_by_timesort(3, 6);
772 $result = external_api::clean_returnvalue(
773 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
774 $result
775 );
776 $events = $result['events'];
777
778 $this->assertCount(4, $events);
779 $this->assertEquals('Event 3', $events[0]['name']);
780 $this->assertEquals('Event 4', $events[1]['name']);
781 $this->assertEquals('Event 5', $events[2]['name']);
782 $this->assertEquals('Event 6', $events[3]['name']);
783 $this->assertEquals($event3->id, $result['firstid']);
784 $this->assertEquals($event6->id, $result['lastid']);
785
786 $result = core_calendar_external::get_calendar_action_events_by_timesort(10, 15);
787 $result = external_api::clean_returnvalue(
788 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
789 $result
790 );
791
792 $this->assertEmpty($result['events']);
793 $this->assertNull($result['firstid']);
794 $this->assertNull($result['lastid']);
795 }
796
797 /**
798 * Requesting calendar events within a given time range and a limit and offset should return
799 * the number of events up to the given limit value that have a sort time between the lower
800 * and uppper time bound (inclusive) where the result set is shifted by the offset value.
801 *
802 * If there are no events in the given time range then an empty result set should be
803 * returned.
804 */
1aeb58fa 805 public function test_get_calendar_action_events_by_timesort_time_limit_offset() {
4139f131
RW
806 $user = $this->getDataGenerator()->create_user();
807 $course = $this->getDataGenerator()->create_course();
808 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
809 $moduleinstance = $generator->create_instance(['course' => $course->id]);
810
811 $this->getDataGenerator()->enrol_user($user->id, $course->id);
812 $this->resetAfterTest(true);
813 $this->setUser($user);
814
815 $params = [
816 'type' => CALENDAR_EVENT_TYPE_ACTION,
817 'modulename' => 'assign',
818 'instance' => $moduleinstance->id,
819 'courseid' => $course->id,
820 ];
821
822 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
823 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
824 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
825 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
826 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
827 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
828 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
829 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
830
831 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event3->id, 2);
832 $result = external_api::clean_returnvalue(
833 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
834 $result
835 );
836 $events = $result['events'];
837
838 $this->assertCount(2, $events);
839 $this->assertEquals('Event 4', $events[0]['name']);
840 $this->assertEquals('Event 5', $events[1]['name']);
841 $this->assertEquals($event4->id, $result['firstid']);
842 $this->assertEquals($event5->id, $result['lastid']);
843
844 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event5->id, 2);
845 $result = external_api::clean_returnvalue(
846 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
847 $result
848 );
849 $events = $result['events'];
850
851 $this->assertCount(2, $events);
852 $this->assertEquals('Event 6', $events[0]['name']);
853 $this->assertEquals('Event 7', $events[1]['name']);
854 $this->assertEquals($event6->id, $result['firstid']);
855 $this->assertEquals($event7->id, $result['lastid']);
856
857 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event7->id, 2);
858 $result = external_api::clean_returnvalue(
859 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
860 $result
861 );
862
863 $this->assertEmpty($result['events']);
864 $this->assertNull($result['firstid']);
865 $this->assertNull($result['lastid']);
866 }
5e026bb0
RW
867
868 /**
869 * Requesting calendar events from a given course and time should return all
870 * events with a sort time at or after the requested time. All events prior
871 * to that time should not be return.
872 *
873 * If there are no events on or after the given time then an empty result set should
874 * be returned.
875 */
1aeb58fa 876 public function test_get_calendar_action_events_by_course_after_time() {
5e026bb0
RW
877 $user = $this->getDataGenerator()->create_user();
878 $course1 = $this->getDataGenerator()->create_course();
879 $course2 = $this->getDataGenerator()->create_course();
880 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
881 $instance1 = $generator->create_instance(['course' => $course1->id]);
882 $instance2 = $generator->create_instance(['course' => $course2->id]);
883 $records = [];
884
885 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
886 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
887 $this->resetAfterTest(true);
888 $this->setUser($user);
889
890 for ($i = 1; $i < 19; $i++) {
891 $courseid = ($i < 9) ? $course1->id : $course2->id;
892 $instance = ($i < 9) ? $instance1->id : $instance2->id;
893 $records[] = $this->create_calendar_event(
894 sprintf('Event %d', $i),
895 $user->id,
896 'user',
897 0,
898 1,
899 [
900 'type' => CALENDAR_EVENT_TYPE_ACTION,
901 'courseid' => $courseid,
902 'timesort' => $i,
903 'modulename' => 'assign',
904 'instance' => $instance,
905 ]
906 );
907 }
908
909 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 5);
910 $result = external_api::clean_returnvalue(
911 core_calendar_external::get_calendar_action_events_by_course_returns(),
912 $result
913 );
914 $result = $result['events'];
915
916 $this->assertCount(4, $result);
917 $this->assertEquals('Event 5', $result[0]['name']);
918 $this->assertEquals('Event 6', $result[1]['name']);
919 $this->assertEquals('Event 7', $result[2]['name']);
920 $this->assertEquals('Event 8', $result[3]['name']);
921
922 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 9);
923 $result = external_api::clean_returnvalue(
924 core_calendar_external::get_calendar_action_events_by_course_returns(),
925 $result
926 );
927 $result = $result['events'];
928
929 $this->assertEmpty($result);
930 }
931
932 /**
933 * Requesting calendar events for a course and before a given time should return
934 * all events with a sort time at or before the requested time (inclusive). All
935 * events after that time should not be returned.
936 *
937 * If there are no events before the given time then an empty result set should be
938 * returned.
939 */
1aeb58fa 940 public function test_get_calendar_action_events_by_course_before_time() {
5e026bb0
RW
941 $user = $this->getDataGenerator()->create_user();
942 $course1 = $this->getDataGenerator()->create_course();
943 $course2 = $this->getDataGenerator()->create_course();
944 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
945 $instance1 = $generator->create_instance(['course' => $course1->id]);
946 $instance2 = $generator->create_instance(['course' => $course2->id]);
947 $records = [];
948
949 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
950 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
951 $this->resetAfterTest(true);
952 $this->setUser($user);
953
954 for ($i = 1; $i < 19; $i++) {
955 $courseid = ($i < 9) ? $course1->id : $course2->id;
956 $instance = ($i < 9) ? $instance1->id : $instance2->id;
957 $records[] = $this->create_calendar_event(
958 sprintf('Event %d', $i),
959 $user->id,
960 'user',
961 0,
962 1,
963 [
964 'type' => CALENDAR_EVENT_TYPE_ACTION,
965 'courseid' => $courseid,
966 'timesort' => $i + 1,
967 'modulename' => 'assign',
968 'instance' => $instance,
969 ]
970 );
971 }
972
973 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 5);
974 $result = external_api::clean_returnvalue(
975 core_calendar_external::get_calendar_action_events_by_course_returns(),
976 $result
977 );
978 $result = $result['events'];
979
980 $this->assertCount(4, $result);
981 $this->assertEquals('Event 1', $result[0]['name']);
982 $this->assertEquals('Event 2', $result[1]['name']);
983 $this->assertEquals('Event 3', $result[2]['name']);
984 $this->assertEquals('Event 4', $result[3]['name']);
985
986 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 1);
987 $result = external_api::clean_returnvalue(
988 core_calendar_external::get_calendar_action_events_by_course_returns(),
989 $result
990 );
991 $result = $result['events'];
992
993 $this->assertEmpty($result);
994 }
995
996 /**
997 * Requesting calendar events for a course and within a given time range should
998 * return all events with a sort time between the lower and upper time bound
999 * (inclusive).
1000 *
1001 * If there are no events in the given time range then an empty result set should be
1002 * returned.
1003 */
1aeb58fa 1004 public function test_get_calendar_action_events_by_course_time_range() {
5e026bb0
RW
1005 $user = $this->getDataGenerator()->create_user();
1006 $course1 = $this->getDataGenerator()->create_course();
1007 $course2 = $this->getDataGenerator()->create_course();
1008 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1009 $instance1 = $generator->create_instance(['course' => $course1->id]);
1010 $instance2 = $generator->create_instance(['course' => $course2->id]);
1011 $records = [];
1012
1013 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1014 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1015 $this->resetAfterTest(true);
1016 $this->setUser($user);
1017
1018 for ($i = 1; $i < 19; $i++) {
1019 $courseid = ($i < 9) ? $course1->id : $course2->id;
1020 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1021 $records[] = $this->create_calendar_event(
1022 sprintf('Event %d', $i),
1023 $user->id,
1024 'user',
1025 0,
1026 1,
1027 [
1028 'type' => CALENDAR_EVENT_TYPE_ACTION,
1029 'courseid' => $courseid,
1030 'timesort' => $i,
1031 'modulename' => 'assign',
1032 'instance' => $instance,
1033 ]
1034 );
1035 }
1036
1037 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 3, 6);
1038 $result = external_api::clean_returnvalue(
1039 core_calendar_external::get_calendar_action_events_by_course_returns(),
1040 $result
1041 );
1042 $result = $result['events'];
1043
1044 $this->assertCount(4, $result);
1045 $this->assertEquals('Event 3', $result[0]['name']);
1046 $this->assertEquals('Event 4', $result[1]['name']);
1047 $this->assertEquals('Event 5', $result[2]['name']);
1048 $this->assertEquals('Event 6', $result[3]['name']);
1049
1050 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 10, 15);
1051 $result = external_api::clean_returnvalue(
1052 core_calendar_external::get_calendar_action_events_by_course_returns(),
1053 $result
1054 );
1055 $result = $result['events'];
1056
1057 $this->assertEmpty($result);
1058 }
1059
1060 /**
1061 * Requesting calendar events for a course and within a given time range and a limit
1062 * and offset should return the number of events up to the given limit value that have
1063 * a sort time between the lower and uppper time bound (inclusive) where the result
1064 * set is shifted by the offset value.
1065 *
1066 * If there are no events in the given time range then an empty result set should be
1067 * returned.
1068 */
1aeb58fa 1069 public function test_get_calendar_action_events_by_course_time_limit_offset() {
5e026bb0
RW
1070 $user = $this->getDataGenerator()->create_user();
1071 $course1 = $this->getDataGenerator()->create_course();
1072 $course2 = $this->getDataGenerator()->create_course();
1073 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1074 $instance1 = $generator->create_instance(['course' => $course1->id]);
1075 $instance2 = $generator->create_instance(['course' => $course2->id]);
1076 $records = [];
1077
1078 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1079 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1080 $this->resetAfterTest(true);
1081 $this->setUser($user);
1082
1083 for ($i = 1; $i < 19; $i++) {
1084 $courseid = ($i < 9) ? $course1->id : $course2->id;
1085 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1086 $records[] = $this->create_calendar_event(
1087 sprintf('Event %d', $i),
1088 $user->id,
1089 'user',
1090 0,
1091 1,
1092 [
1093 'type' => CALENDAR_EVENT_TYPE_ACTION,
1094 'courseid' => $courseid,
1095 'timesort' => $i,
1096 'modulename' => 'assign',
1097 'instance' => $instance,
1098 ]
1099 );
1100 }
1101
1102 $result = core_calendar_external::get_calendar_action_events_by_course(
1103 $course1->id, 2, 7, $records[2]->id, 2);
1104 $result = external_api::clean_returnvalue(
1105 core_calendar_external::get_calendar_action_events_by_course_returns(),
1106 $result
1107 );
1108 $result = $result['events'];
1109
1110 $this->assertCount(2, $result);
1111 $this->assertEquals('Event 4', $result[0]['name']);
1112 $this->assertEquals('Event 5', $result[1]['name']);
1113
1114 $result = core_calendar_external::get_calendar_action_events_by_course(
1115 $course1->id, 2, 7, $records[4]->id, 2);
1116 $result = external_api::clean_returnvalue(
1117 core_calendar_external::get_calendar_action_events_by_course_returns(),
1118 $result
1119 );
1120 $result = $result['events'];
1121
1122 $this->assertCount(2, $result);
1123 $this->assertEquals('Event 6', $result[0]['name']);
1124 $this->assertEquals('Event 7', $result[1]['name']);
1125
1126 $result = core_calendar_external::get_calendar_action_events_by_course(
1127 $course1->id, 2, 7, $records[6]->id, 2);
1128 $result = external_api::clean_returnvalue(
1129 core_calendar_external::get_calendar_action_events_by_course_returns(),
1130 $result
1131 );
1132 $result = $result['events'];
1133
1134 $this->assertEmpty($result);
1135 }
1aeb58fa
RW
1136
1137 /**
1138 * Test that get_action_events_by_courses will return a list of events for each
1139 * course you provided as long as the user is enrolled in the course.
1140 */
1141 public function test_get_action_events_by_courses() {
1142 $user = $this->getDataGenerator()->create_user();
1143 $course1 = $this->getDataGenerator()->create_course();
1144 $course2 = $this->getDataGenerator()->create_course();
1145 $course3 = $this->getDataGenerator()->create_course();
1146 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1147 $instance1 = $generator->create_instance(['course' => $course1->id]);
1148 $instance2 = $generator->create_instance(['course' => $course2->id]);
1149 $instance3 = $generator->create_instance(['course' => $course3->id]);
1150 $records = [];
1151 $mapresult = function($result) {
1152 $groupedbycourse = [];
1153 foreach ($result['groupedbycourse'] as $group) {
1154 $events = $group['events'];
1155 $courseid = $group['courseid'];
1156 $groupedbycourse[$courseid] = $events;
1157 }
1158
1159 return $groupedbycourse;
1160 };
1161
1162 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1163 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1164 $this->resetAfterTest(true);
1165 $this->setUser($user);
1166
1167 for ($i = 1; $i < 10; $i++) {
1168 if ($i < 3) {
1169 $courseid = $course1->id;
1170 $instance = $instance1->id;
1171 } else if ($i < 6) {
1172 $courseid = $course2->id;
1173 $instance = $instance2->id;
1174 } else {
1175 $courseid = $course3->id;
1176 $instance = $instance3->id;
1177 }
1178
1179 $records[] = $this->create_calendar_event(
1180 sprintf('Event %d', $i),
1181 $user->id,
1182 'user',
1183 0,
1184 1,
1185 [
1186 'type' => CALENDAR_EVENT_TYPE_ACTION,
1187 'courseid' => $courseid,
1188 'timesort' => $i,
1189 'modulename' => 'assign',
1190 'instance' => $instance,
1191 ]
1192 );
1193 }
1194
1195 $result = core_calendar_external::get_calendar_action_events_by_courses([], 1);
1196 $result = external_api::clean_returnvalue(
1197 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1198 $result
1199 );
1200 $result = $result['groupedbycourse'];
1201
1202 $this->assertEmpty($result);
1203
1204 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 3);
1205 $result = external_api::clean_returnvalue(
1206 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1207 $result
1208 );
1209
1210 $groupedbycourse = $mapresult($result);
1211
1212 $this->assertEmpty($groupedbycourse[$course1->id]);
1213
1214 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 1);
1215 $result = external_api::clean_returnvalue(
1216 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1217 $result
1218 );
1219 $groupedbycourse = $mapresult($result);
1220
1221 $this->assertCount(2, $groupedbycourse[$course1->id]);
1222 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1223 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);
1224
1225 $result = core_calendar_external::get_calendar_action_events_by_courses(
1226 [$course1->id, $course2->id], 1);
1227 $result = external_api::clean_returnvalue(
1228 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1229 $result
1230 );
1231 $groupedbycourse = $mapresult($result);
1232
1233 $this->assertCount(2, $groupedbycourse[$course1->id]);
1234 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1235 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);
1236 $this->assertCount(3, $groupedbycourse[$course2->id]);
1237 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1238 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);
1239 $this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']);
1240
1241 $result = core_calendar_external::get_calendar_action_events_by_courses(
1242 [$course1->id, $course2->id], 2, 4);
1243 $result = external_api::clean_returnvalue(
1244 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1245 $result
1246 );
1247 $groupedbycourse = $mapresult($result);
1248
1249 $this->assertCount(2, $groupedbycourse);
1250 $this->assertCount(1, $groupedbycourse[$course1->id]);
1251 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][0]['name']);
1252 $this->assertCount(2, $groupedbycourse[$course2->id]);
1253 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1254 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);
1255
1256 $result = core_calendar_external::get_calendar_action_events_by_courses(
1257 [$course1->id, $course2->id], 1, null, 1);
1258 $result = external_api::clean_returnvalue(
1259 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1260 $result
1261 );
1262 $groupedbycourse = $mapresult($result);
1263
1264 $this->assertCount(2, $groupedbycourse);
1265 $this->assertCount(1, $groupedbycourse[$course1->id]);
1266 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1267 $this->assertCount(1, $groupedbycourse[$course2->id]);
1268 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1269 }
5d942f5a
SL
1270
1271 /**
1272 * Test for deleting module events.
1273 */
1274 public function test_delete_calendar_events_for_modules() {
1275 $this->resetAfterTest();
1276 $this->setAdminUser();
1277 $course = $this->getDataGenerator()->create_course();
1278 $nexttime = time() + DAYSECS;
1279 $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'duedate' => $nexttime]);
1280 $events = calendar_get_events(time(), $nexttime, true, true, true);
1281 $this->assertCount(1, $events);
1282 $params = [];
1283 foreach ($events as $event) {
1284 $params[] = [
1285 'eventid' => $event->id,
1286 'repeat' => false
1287 ];
1288 }
1289
1290 $this->expectException('moodle_exception');
1291 core_calendar_external::delete_calendar_events($params);
1292 }
c6fb9310
RW
1293
1294 /**
1295 * Updating the event start day should change the date value but leave
1296 * the time of day unchanged.
1297 */
1298 public function test_update_event_start_day() {
1299 $generator = $this->getDataGenerator();
1300 $user = $generator->create_user();
1301 $roleid = $generator->create_role();
1302 $context = \context_system::instance();
96283892
RW
1303 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1304 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
c6fb9310
RW
1305 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1306
1307 $generator->role_assign($roleid, $user->id, $context->id);
1308 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1309
1310 $this->setUser($user);
1311 $this->resetAfterTest(true);
1312
1313 $event = $this->create_calendar_event(
1314 'Test event',
1315 $user->id,
1316 'user',
1317 0,
1318 null,
1319 [
1320 'courseid' => 0,
96283892 1321 'timestart' => $originalstarttime->getTimestamp()
c6fb9310
RW
1322 ]
1323 );
1324
96283892 1325 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
c6fb9310
RW
1326 $result = external_api::clean_returnvalue(
1327 core_calendar_external::update_event_start_day_returns(),
1328 $result
1329 );
1330
1331 $this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);
1332 }
1333
1334 /**
909d0858
RW
1335 * A user should not be able to edit an event that they don't have
1336 * capabilities for.
c6fb9310
RW
1337 */
1338 public function test_update_event_start_day_no_permission() {
1339 $generator = $this->getDataGenerator();
1340 $user = $generator->create_user();
1341 $roleid = $generator->create_role();
1342 $context = \context_system::instance();
96283892
RW
1343 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1344 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
c6fb9310
RW
1345 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1346
1347 $generator->role_assign($roleid, $user->id, $context->id);
1348 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1349
1350 $this->setUser($user);
1351 $this->resetAfterTest(true);
1352
1353 $event = $this->create_calendar_event(
1354 'Test event',
1355 $user->id,
1356 'user',
1357 0,
1358 null,
1359 [
1360 'courseid' => 0,
96283892 1361 'timestart' => $originalstarttime->getTimestamp()
c6fb9310
RW
1362 ]
1363 );
1364
1365 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1366 $this->expectException('moodle_exception');
96283892 1367 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
c6fb9310
RW
1368 $result = external_api::clean_returnvalue(
1369 core_calendar_external::update_event_start_day_returns(),
1370 $result
1371 );
1372 }
909d0858
RW
1373
1374 /**
1375 * A user should not be able to update a module event.
1376 */
1377 public function test_update_event_start_day_module_event() {
1378 $generator = $this->getDataGenerator();
1379 $user = $generator->create_user();
1380 $course = $generator->create_course();
96283892
RW
1381 $plugingenerator = $generator->get_plugin_generator('mod_assign');
1382 $moduleinstance = $plugingenerator->create_instance(['course' => $course->id]);
909d0858
RW
1383 $roleid = $generator->create_role();
1384 $context = \context_course::instance($course->id);
96283892
RW
1385 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1386 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
909d0858
RW
1387 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1388
1389 $generator->role_assign($roleid, $user->id, $context->id);
1390 $generator->enrol_user($user->id, $course->id);
1391
1392 $this->setUser($user);
1393 $this->resetAfterTest(true);
1394
1395 $event = $this->create_calendar_event(
1396 'Test event',
1397 $user->id,
1398 'user',
1399 0,
1400 null,
1401 [
1402 'modulename' => 'assign',
1403 'instance' => $moduleinstance->id,
1404 'courseid' => $course->id,
96283892 1405 'timestart' => $originalstarttime->getTimestamp()
909d0858
RW
1406 ]
1407 );
1408
1409 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1410 $this->expectException('moodle_exception');
96283892 1411 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
909d0858
RW
1412 $result = external_api::clean_returnvalue(
1413 core_calendar_external::update_event_start_day_returns(),
1414 $result
1415 );
1416 }
f0e6ff9a 1417
69b160ed
RW
1418 /**
1419 * Submit a request where the time duration until is earlier than the time
1420 * start in order to get a validation error from the server.
1421 */
1422 public function test_submit_create_update_form_validation_error() {
1423 $user = $this->getDataGenerator()->create_user();
1424 $timestart = new DateTime();
1425 $interval = new DateInterval("P1D"); // One day.
1426 $timedurationuntil = new DateTime();
1427 $timedurationuntil->sub($interval);
1428 $formdata = [
1429 'id' => 0,
1430 'userid' => $user->id,
1431 'modulename' => '',
1432 'instance' => 0,
1433 'visible' => 1,
1434 'name' => 'Test',
1435 'timestart' => [
1436 'day' => $timestart->format('j'),
1437 'month' => $timestart->format('n'),
1438 'year' => $timestart->format('Y'),
1439 'hour' => $timestart->format('G'),
1440 'minute' => 0,
1441 ],
1442 'eventtype' => 'user',
1443 'description' => [
1444 'text' => '',
1445 'format' => 1,
1446 ],
1447 'duration' => 1,
1448 'timedurationuntil' => [
1449 'day' => $timedurationuntil->format('j'),
1450 'month' => $timedurationuntil->format('n'),
1451 'year' => $timedurationuntil->format('Y'),
1452 'hour' => $timedurationuntil->format('G'),
1453 'minute' => 0,
1454 ]
1455 ];
1456
1457 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1458
1459 $querystring = http_build_query($formdata, '', '&amp;');
1460
1461 $this->resetAfterTest(true);
1462 $this->setUser($user);
1463
1464 $result = external_api::clean_returnvalue(
1465 core_calendar_external::submit_create_update_form_returns(),
1466 core_calendar_external::submit_create_update_form($querystring)
1467 );
1468
1469 $this->assertTrue($result['validationerror']);
1470 }
1471
1472 /**
1473 * A user with the moodle/calendar:manageownentries capability at the
1474 * system context should be able to create a user event.
1475 */
1476 public function test_submit_create_update_form_create_user_event() {
1477 $generator = $this->getDataGenerator();
1478 $user = $generator->create_user();
1479 $roleid = $generator->create_role();
1480 $context = \context_system::instance();
1481 $timestart = new DateTime();
1482 $interval = new DateInterval("P1D"); // One day.
1483 $timedurationuntil = new DateTime();
1484 $timedurationuntil->add($interval);
1485 $formdata = [
1486 'id' => 0,
1487 'userid' => $user->id,
1488 'modulename' => '',
1489 'instance' => 0,
1490 'visible' => 1,
1491 'name' => 'Test',
1492 'timestart' => [
1493 'day' => $timestart->format('j'),
1494 'month' => $timestart->format('n'),
1495 'year' => $timestart->format('Y'),
1496 'hour' => $timestart->format('G'),
1497 'minute' => 0,
1498 ],
1499 'eventtype' => 'user',
1500 'description' => [
1501 'text' => '',
1502 'format' => 1,
ea5f7707 1503 'itemid' => 0
69b160ed
RW
1504 ],
1505 'duration' => 1,
1506 'timedurationuntil' => [
1507 'day' => $timedurationuntil->format('j'),
1508 'month' => $timedurationuntil->format('n'),
1509 'year' => $timedurationuntil->format('Y'),
1510 'hour' => $timedurationuntil->format('G'),
1511 'minute' => 0,
1512 ]
1513 ];
1514
1515 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1516 $querystring = http_build_query($formdata, '', '&');
1517
1518 $generator->role_assign($roleid, $user->id, $context->id);
1519 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1520
1521 $user->ignoresesskey = true;
1522 $this->resetAfterTest(true);
1523 $this->setUser($user);
1524
1525 $result = external_api::clean_returnvalue(
1526 core_calendar_external::submit_create_update_form_returns(),
1527 core_calendar_external::submit_create_update_form($querystring)
1528 );
1529
1530 $event = $result['event'];
1531 $this->assertEquals($user->id, $event['userid']);
1532 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1533 $this->assertEquals($formdata['name'], $event['name']);
1534 }
1535
1536 /**
1537 * A user without the moodle/calendar:manageownentries capability at the
1538 * system context should not be able to create a user event.
1539 */
1540 public function test_submit_create_update_form_create_user_event_no_permission() {
1541 $generator = $this->getDataGenerator();
1542 $user = $generator->create_user();
1543 $roleid = $generator->create_role();
1544 $context = \context_system::instance();
1545 $timestart = new DateTime();
1546 $interval = new DateInterval("P1D"); // One day.
1547 $timedurationuntil = new DateTime();
1548 $timedurationuntil->add($interval);
1549 $formdata = [
1550 'id' => 0,
1551 'userid' => $user->id,
1552 'modulename' => '',
1553 'instance' => 0,
1554 'visible' => 1,
1555 'name' => 'Test',
1556 'timestart' => [
1557 'day' => $timestart->format('j'),
1558 'month' => $timestart->format('n'),
1559 'year' => $timestart->format('Y'),
1560 'hour' => $timestart->format('G'),
1561 'minute' => 0,
1562 ],
1563 'eventtype' => 'user',
1564 'description' => [
1565 'text' => '',
1566 'format' => 1,
1567 ],
1568 'duration' => 1,
1569 'timedurationuntil' => [
1570 'day' => $timedurationuntil->format('j'),
1571 'month' => $timedurationuntil->format('n'),
1572 'year' => $timedurationuntil->format('Y'),
1573 'hour' => $timedurationuntil->format('G'),
1574 'minute' => 0,
1575 ]
1576 ];
1577
1578 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1579 $querystring = http_build_query($formdata, '', '&');
1580
1581 $generator->role_assign($roleid, $user->id, $context->id);
1582 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1583
1584 $user->ignoresesskey = true;
1585 $this->resetAfterTest(true);
1586 $this->setUser($user);
1587
1588 $this->expectException('moodle_exception');
1589
1590 external_api::clean_returnvalue(
1591 core_calendar_external::submit_create_update_form_returns(),
1592 core_calendar_external::submit_create_update_form($querystring)
1593 );
1594 }
1595
1596 /**
1597 * A user with the moodle/calendar:manageentries capability at the
1598 * site course context should be able to create a site event.
1599 */
1600 public function test_submit_create_update_form_create_site_event() {
1601 $generator = $this->getDataGenerator();
1602 $user = $generator->create_user();
303d649a 1603 $context = context_system::instance();
69b160ed
RW
1604 $roleid = $generator->create_role();
1605 $timestart = new DateTime();
1606 $interval = new DateInterval("P1D"); // One day.
1607 $timedurationuntil = new DateTime();
1608 $timedurationuntil->add($interval);
1609 $formdata = [
1610 'id' => 0,
1611 'userid' => $user->id,
1612 'modulename' => '',
1613 'instance' => 0,
1614 'visible' => 1,
1615 'name' => 'Test',
1616 'timestart' => [
1617 'day' => $timestart->format('j'),
1618 'month' => $timestart->format('n'),
1619 'year' => $timestart->format('Y'),
1620 'hour' => $timestart->format('G'),
1621 'minute' => 0,
1622 ],
1623 'eventtype' => 'site',
1624 'description' => [
1625 'text' => '',
1626 'format' => 1,
ea5f7707 1627 'itemid' => 0
69b160ed
RW
1628 ],
1629 'duration' => 1,
1630 'timedurationuntil' => [
1631 'day' => $timedurationuntil->format('j'),
1632 'month' => $timedurationuntil->format('n'),
1633 'year' => $timedurationuntil->format('Y'),
1634 'hour' => $timedurationuntil->format('G'),
1635 'minute' => 0,
1636 ]
1637 ];
1638
1639 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1640 $querystring = http_build_query($formdata, '', '&');
1641
1642 $generator->role_assign($roleid, $user->id, $context->id);
1643
1644 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1645
1646 $user->ignoresesskey = true;
1647 $this->resetAfterTest(true);
1648 $this->setUser($user);
1649
1650 $result = external_api::clean_returnvalue(
1651 core_calendar_external::submit_create_update_form_returns(),
1652 core_calendar_external::submit_create_update_form($querystring)
1653 );
1654
1655 $event = $result['event'];
1656 $this->assertEquals($user->id, $event['userid']);
1657 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1658 $this->assertEquals($formdata['name'], $event['name']);
1659 }
1660
1661 /**
1662 * A user without the moodle/calendar:manageentries capability at the
1663 * site course context should not be able to create a site event.
1664 */
1665 public function test_submit_create_update_form_create_site_event_no_permission() {
1666 $generator = $this->getDataGenerator();
1667 $user = $generator->create_user();
1668 $context = context_course::instance(SITEID);
1669 $roleid = $generator->create_role();
1670 $timestart = new DateTime();
1671 $interval = new DateInterval("P1D"); // One day.
1672 $timedurationuntil = new DateTime();
1673 $timedurationuntil->add($interval);
1674 $formdata = [
1675 'id' => 0,
1676 'userid' => $user->id,
1677 'modulename' => '',
1678 'instance' => 0,
1679 'visible' => 1,
1680 'name' => 'Test',
1681 'timestart' => [
1682 'day' => $timestart->format('j'),
1683 'month' => $timestart->format('n'),
1684 'year' => $timestart->format('Y'),
1685 'hour' => $timestart->format('G'),
1686 'minute' => 0,
1687 ],
1688 'eventtype' => 'site',
1689 'description' => [
1690 'text' => '',
1691 'format' => 1,
1692 ],
1693 'duration' => 1,
1694 'timedurationuntil' => [
1695 'day' => $timedurationuntil->format('j'),
1696 'month' => $timedurationuntil->format('n'),
1697 'year' => $timedurationuntil->format('Y'),
1698 'hour' => $timedurationuntil->format('G'),
1699 'minute' => 0,
1700 ]
1701 ];
1702
1703 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1704 $querystring = http_build_query($formdata, '', '&');
1705
1706 $generator->role_assign($roleid, $user->id, $context->id);
1707
1708 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
1709
1710 $user->ignoresesskey = true;
1711 $this->resetAfterTest(true);
1712 $this->setUser($user);
1713
1714 $result = external_api::clean_returnvalue(
1715 core_calendar_external::submit_create_update_form_returns(),
1716 core_calendar_external::submit_create_update_form($querystring)
1717 );
1718
1719 $this->assertTrue($result['validationerror']);
1720 }
1721
1722 /**
1723 * A user that has the moodle/calendar:manageentries in a course that they
1724 * are enrolled in should be able to create a course event in that course.
1725 */
1726 public function test_submit_create_update_form_create_course_event() {
1727 $generator = $this->getDataGenerator();
1728 $user = $generator->create_user();
1729 $course = $generator->create_course();
1730 $context = context_course::instance($course->id);
1731 $roleid = $generator->create_role();
1732 $timestart = new DateTime();
1733 $interval = new DateInterval("P1D"); // One day.
1734 $timedurationuntil = new DateTime();
1735 $timedurationuntil->add($interval);
1736 $formdata = [
1737 'id' => 0,
1738 'userid' => $user->id,
1739 'modulename' => '',
1740 'instance' => 0,
1741 'visible' => 1,
1742 'name' => 'Test',
1743 'timestart' => [
1744 'day' => $timestart->format('j'),
1745 'month' => $timestart->format('n'),
1746 'year' => $timestart->format('Y'),
1747 'hour' => $timestart->format('G'),
1748 'minute' => 0,
1749 ],
1750 'eventtype' => 'course',
1751 'courseid' => $course->id,
1752 'description' => [
1753 'text' => '',
1754 'format' => 1,
ea5f7707 1755 'itemid' => 0,
69b160ed
RW
1756 ],
1757 'duration' => 1,
1758 'timedurationuntil' => [
1759 'day' => $timedurationuntil->format('j'),
1760 'month' => $timedurationuntil->format('n'),
1761 'year' => $timedurationuntil->format('Y'),
1762 'hour' => $timedurationuntil->format('G'),
1763 'minute' => 0,
1764 ]
1765 ];
1766
1767 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1768 $querystring = http_build_query($formdata, '', '&');
1769
1770 $generator->enrol_user($user->id, $course->id, 'student');
1771 $generator->role_assign($roleid, $user->id, $context->id);
1772
1773 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1774
1775 $user->ignoresesskey = true;
1776 $this->resetAfterTest(true);
1777 $this->setUser($user);
1778
1779 $result = external_api::clean_returnvalue(
1780 core_calendar_external::submit_create_update_form_returns(),
1781 core_calendar_external::submit_create_update_form($querystring)
1782 );
1783
1784 $event = $result['event'];
1785 $this->assertEquals($user->id, $event['userid']);
1786 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1787 $this->assertEquals($formdata['name'], $event['name']);
1788 $this->assertEquals($formdata['courseid'], $event['course']['id']);
1789 }
1790
1791 /**
1792 * A user without the moodle/calendar:manageentries capability in a course
1793 * that they are enrolled in should not be able to create a course event in that course.
1794 */
1795 public function test_submit_create_update_form_create_course_event_no_permission() {
1796 $generator = $this->getDataGenerator();
1797 $user = $generator->create_user();
1798 $course = $generator->create_course();
1799 $context = context_course::instance($course->id);
1800 $roleid = $generator->create_role();
1801 $timestart = new DateTime();
1802 $interval = new DateInterval("P1D"); // One day.
1803 $timedurationuntil = new DateTime();
1804 $timedurationuntil->add($interval);
1805 $formdata = [
1806 'id' => 0,
1807 'userid' => $user->id,
1808 'modulename' => '',
1809 'instance' => 0,
1810 'visible' => 1,
1811 'name' => 'Test',
1812 'timestart' => [
1813 'day' => $timestart->format('j'),
1814 'month' => $timestart->format('n'),
1815 'year' => $timestart->format('Y'),
1816 'hour' => $timestart->format('G'),
1817 'minute' => 0,
1818 ],
1819 'eventtype' => 'course',
1820 'courseid' => $course->id,
1821 'description' => [
1822 'text' => '',
1823 'format' => 1,
1824 ],
1825 'duration' => 1,
1826 'timedurationuntil' => [
1827 'day' => $timedurationuntil->format('j'),
1828 'month' => $timedurationuntil->format('n'),
1829 'year' => $timedurationuntil->format('Y'),
1830 'hour' => $timedurationuntil->format('G'),
1831 'minute' => 0,
1832 ]
1833 ];
1834
1835 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1836 $querystring = http_build_query($formdata, '', '&');
1837
1838 $generator->enrol_user($user->id, $course->id, 'student');
1839 $generator->role_assign($roleid, $user->id, $context->id);
1840
1841 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
1842
1843 $user->ignoresesskey = true;
1844 $this->resetAfterTest(true);
1845 $this->setUser($user);
1846
1847 $result = external_api::clean_returnvalue(
1848 core_calendar_external::submit_create_update_form_returns(),
1849 core_calendar_external::submit_create_update_form($querystring)
1850 );
1851
1852 $this->assertTrue($result['validationerror']);
1853 }
1854
1855 /**
1856 * A user should not be able to create an event for a course that they are
1857 * not enrolled in.
1858 */
1859 public function test_submit_create_update_form_create_course_event_not_enrolled() {
1860 $generator = $this->getDataGenerator();
1861 $user = $generator->create_user();
1862 $course = $generator->create_course();
1863 $course2 = $generator->create_course();
1864 $context = context_course::instance($course->id);
1865 $roleid = $generator->create_role();
1866 $timestart = new DateTime();
1867 $interval = new DateInterval("P1D"); // One day.
1868 $timedurationuntil = new DateTime();
1869 $timedurationuntil->add($interval);
1870 $formdata = [
1871 'id' => 0,
1872 'userid' => $user->id,
1873 'modulename' => '',
1874 'instance' => 0,
1875 'visible' => 1,
1876 'name' => 'Test',
1877 'timestart' => [
1878 'day' => $timestart->format('j'),
1879 'month' => $timestart->format('n'),
1880 'year' => $timestart->format('Y'),
1881 'hour' => $timestart->format('G'),
1882 'minute' => 0,
1883 ],
1884 'eventtype' => 'course',
1885 'courseid' => $course2->id, // Not enrolled.
1886 'description' => [
1887 'text' => '',
1888 'format' => 1,
1889 ],
1890 'duration' => 1,
1891 'timedurationuntil' => [
1892 'day' => $timedurationuntil->format('j'),
1893 'month' => $timedurationuntil->format('n'),
1894 'year' => $timedurationuntil->format('Y'),
1895 'hour' => $timedurationuntil->format('G'),
1896 'minute' => 0,
1897 ]
1898 ];
1899
1900 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1901 $querystring = http_build_query($formdata, '', '&');
1902
1903 $generator->enrol_user($user->id, $course->id, 'student');
1904 $generator->role_assign($roleid, $user->id, $context->id);
1905
1906 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1907
1908 $user->ignoresesskey = true;
1909 $this->resetAfterTest(true);
1910 $this->setUser($user);
1911
1912 $this->expectException('moodle_exception');
1913
1914 external_api::clean_returnvalue(
1915 core_calendar_external::submit_create_update_form_returns(),
1916 core_calendar_external::submit_create_update_form($querystring)
1917 );
1918 }
1919
1920 /**
1921 * A user should be able to create an event for a group that they are a member of in
1922 * a course in which they are enrolled and have the moodle/calendar:manageentries capability.
1923 */
1924 public function test_submit_create_update_form_create_group_event_group_member_manage_course() {
1925 $generator = $this->getDataGenerator();
1926 $user = $generator->create_user();
1927 $course = $generator->create_course();
1928 $group = $generator->create_group(array('courseid' => $course->id));
1929 $context = context_course::instance($course->id);
1930 $roleid = $generator->create_role();
1931 $timestart = new DateTime();
1932 $interval = new DateInterval("P1D"); // One day.
1933 $timedurationuntil = new DateTime();
1934 $timedurationuntil->add($interval);
1935 $formdata = [
1936 'id' => 0,
1937 'userid' => $user->id,
1938 'modulename' => '',
1939 'instance' => 0,
1940 'visible' => 1,
1941 'name' => 'Test',
1942 'timestart' => [
1943 'day' => $timestart->format('j'),
1944 'month' => $timestart->format('n'),
1945 'year' => $timestart->format('Y'),
1946 'hour' => $timestart->format('G'),
1947 'minute' => 0,
1948 ],
1949 'eventtype' => 'group',
1950 'groupid' => "{$course->id}-{$group->id}", // The form format.
1951 'groupcourseid' => $course->id,
1952 'description' => [
1953 'text' => '',
1954 'format' => 1,
ea5f7707 1955 'itemid' => 0
69b160ed
RW
1956 ],
1957 'duration' => 1,
1958 'timedurationuntil' => [
1959 'day' => $timedurationuntil->format('j'),
1960 'month' => $timedurationuntil->format('n'),
1961 'year' => $timedurationuntil->format('Y'),
1962 'hour' => $timedurationuntil->format('G'),
1963 'minute' => 0,
1964 ]
1965 ];
1966
1967 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1968 $querystring = http_build_query($formdata, '', '&');
1969
1970 $generator->enrol_user($user->id, $course->id, 'student');
1971 $generator->role_assign($roleid, $user->id, $context->id);
1972 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
1973
1974 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1975
1976 $user->ignoresesskey = true;
1977 $this->resetAfterTest(true);
1978 $this->setUser($user);
1979
1980 $result = external_api::clean_returnvalue(
1981 core_calendar_external::submit_create_update_form_returns(),
1982 core_calendar_external::submit_create_update_form($querystring)
1983 );
1984
1985 $event = $result['event'];
1986 $this->assertEquals($user->id, $event['userid']);
1987 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1988 $this->assertEquals($formdata['name'], $event['name']);
1989 $this->assertEquals($group->id, $event['groupid']);
1990 }
1991
1992 /**
1993 * A user should be able to create an event for a group that they are a member of in
1994 * a course in which they are enrolled and have the moodle/calendar:managegroupentries capability.
1995 */
1996 public function test_submit_create_update_form_create_group_event_group_member_manage_group_entries() {
1997 $generator = $this->getDataGenerator();
1998 $user = $generator->create_user();
1999 $course = $generator->create_course();
2000 $group = $generator->create_group(array('courseid' => $course->id));
2001 $context = context_course::instance($course->id);
2002 $roleid = $generator->create_role();
2003 $timestart = new DateTime();
2004 $interval = new DateInterval("P1D"); // One day.
2005 $timedurationuntil = new DateTime();
2006 $timedurationuntil->add($interval);
2007 $formdata = [
2008 'id' => 0,
2009 'userid' => $user->id,
2010 'modulename' => '',
2011 'instance' => 0,
2012 'visible' => 1,
2013 'name' => 'Test',
2014 'timestart' => [
2015 'day' => $timestart->format('j'),
2016 'month' => $timestart->format('n'),
2017 'year' => $timestart->format('Y'),
2018 'hour' => $timestart->format('G'),
2019 'minute' => 0,
2020 ],
2021 'eventtype' => 'group',
2022 'groupid' => "{$course->id}-{$group->id}", // The form format.
2023 'groupcourseid' => $course->id,
2024 'description' => [
2025 'text' => '',
2026 'format' => 1,
ea5f7707 2027 'itemid' => 0
69b160ed
RW
2028 ],
2029 'duration' => 1,
2030 'timedurationuntil' => [
2031 'day' => $timedurationuntil->format('j'),
2032 'month' => $timedurationuntil->format('n'),
2033 'year' => $timedurationuntil->format('Y'),
2034 'hour' => $timedurationuntil->format('G'),
2035 'minute' => 0,
2036 ]
2037 ];
2038
2039 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2040 $querystring = http_build_query($formdata, '', '&');
2041
2042 $generator->enrol_user($user->id, $course->id, 'student');
2043 $generator->role_assign($roleid, $user->id, $context->id);
2044 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
2045
2046 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
2047 assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
2048
2049 $user->ignoresesskey = true;
2050 $this->resetAfterTest(true);
2051 $this->setUser($user);
2052
2053 $result = external_api::clean_returnvalue(
2054 core_calendar_external::submit_create_update_form_returns(),
2055 core_calendar_external::submit_create_update_form($querystring)
2056 );
2057
2058 $event = $result['event'];
2059 $this->assertEquals($user->id, $event['userid']);
2060 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2061 $this->assertEquals($formdata['name'], $event['name']);
2062 $this->assertEquals($group->id, $event['groupid']);
2063 }
2064
2065 /**
2066 * A user should be able to create an event for any group in a course in which
2067 * they are enrolled and have the moodle/site:accessallgroups capability.
2068 */
2069 public function test_submit_create_update_form_create_group_event_access_all_groups() {
2070 $generator = $this->getDataGenerator();
2071 $user = $generator->create_user();
2072 $course = $generator->create_course();
2073 $group = $generator->create_group(array('courseid' => $course->id));
2074 $context = context_course::instance($course->id);
2075 $roleid = $generator->create_role();
2076 $timestart = new DateTime();
2077 $interval = new DateInterval("P1D"); // One day.
2078 $timedurationuntil = new DateTime();
2079 $timedurationuntil->add($interval);
2080 $formdata = [
2081 'id' => 0,
2082 'userid' => $user->id,
2083 'modulename' => '',
2084 'instance' => 0,
2085 'visible' => 1,
2086 'name' => 'Test',
2087 'timestart' => [
2088 'day' => $timestart->format('j'),
2089 'month' => $timestart->format('n'),
2090 'year' => $timestart->format('Y'),
2091 'hour' => $timestart->format('G'),
2092 'minute' => 0,
2093 ],
2094 'eventtype' => 'group',
2095 'groupid' => "{$course->id}-{$group->id}", // The form format.
2096 'groupcourseid' => $course->id,
2097 'description' => [
2098 'text' => '',
2099 'format' => 1,
ea5f7707 2100 'itemid' => 0
69b160ed
RW
2101 ],
2102 'duration' => 1,
2103 'timedurationuntil' => [
2104 'day' => $timedurationuntil->format('j'),
2105 'month' => $timedurationuntil->format('n'),
2106 'year' => $timedurationuntil->format('Y'),
2107 'hour' => $timedurationuntil->format('G'),
2108 'minute' => 0,
2109 ]
2110 ];
2111
2112 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2113 $querystring = http_build_query($formdata, '', '&');
2114
2115 $generator->enrol_user($user->id, $course->id, 'student');
2116 $generator->role_assign($roleid, $user->id, $context->id);
2117
2118 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2119 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
2120
2121 $user->ignoresesskey = true;
2122 $this->resetAfterTest(true);
2123 $this->setUser($user);
2124
2125 $result = external_api::clean_returnvalue(
2126 core_calendar_external::submit_create_update_form_returns(),
2127 core_calendar_external::submit_create_update_form($querystring)
2128 );
2129
2130 $event = $result['event'];
2131 $this->assertEquals($user->id, $event['userid']);
2132 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2133 $this->assertEquals($formdata['name'], $event['name']);
2134 $this->assertEquals($group->id, $event['groupid']);
2135 }
2136
2137 /**
2138 * A user should not be able to create an event for any group that they are not a
2139 * member of in a course in which they are enrolled but don't have the
2140 * moodle/site:accessallgroups capability.
2141 */
2142 public function test_submit_create_update_form_create_group_event_non_member_no_permission() {
2143 $generator = $this->getDataGenerator();
2144 $user = $generator->create_user();
2145 $course = $generator->create_course();
2146 $group = $generator->create_group(array('courseid' => $course->id));
2147 $context = context_course::instance($course->id);
2148 $roleid = $generator->create_role();
2149 $timestart = new DateTime();
2150 $interval = new DateInterval("P1D"); // One day.
2151 $timedurationuntil = new DateTime();
2152 $timedurationuntil->add($interval);
2153 $formdata = [
2154 'id' => 0,
2155 'userid' => $user->id,
2156 'modulename' => '',
2157 'instance' => 0,
2158 'visible' => 1,
2159 'name' => 'Test',
2160 'timestart' => [
2161 'day' => $timestart->format('j'),
2162 'month' => $timestart->format('n'),
2163 'year' => $timestart->format('Y'),
2164 'hour' => $timestart->format('G'),
2165 'minute' => 0,
2166 ],
2167 'eventtype' => 'group',
2168 'groupid' => "{$course->id}-{$group->id}", // The form format.
2169 'groupcourseid' => $course->id,
2170 'description' => [
2171 'text' => '',
2172 'format' => 1,
2173 ],
2174 'duration' => 1,
2175 'timedurationuntil' => [
2176 'day' => $timedurationuntil->format('j'),
2177 'month' => $timedurationuntil->format('n'),
2178 'year' => $timedurationuntil->format('Y'),
2179 'hour' => $timedurationuntil->format('G'),
2180 'minute' => 0,
2181 ]
2182 ];
2183
2184 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2185 $querystring = http_build_query($formdata, '', '&');
2186
2187 $generator->enrol_user($user->id, $course->id, 'student');
2188 $generator->role_assign($roleid, $user->id, $context->id);
2189
2190 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2191 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
2192
2193 $user->ignoresesskey = true;
2194 $this->resetAfterTest(true);
2195 $this->setUser($user);
2196
2197 $result = external_api::clean_returnvalue(
2198 core_calendar_external::submit_create_update_form_returns(),
2199 core_calendar_external::submit_create_update_form($querystring)
2200 );
2201
2202 $this->assertTrue($result['validationerror']);
2203 }
7c30224a 2204}