MDL-64641 calendar: New WS core_calendar_get_access_information
[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();
754016ab 300 $user2 = $this->getDataGenerator()->create_user();
7c30224a 301 $course = $this->getDataGenerator()->create_course();
754016ab
SL
302
303 $category = $this->getDataGenerator()->create_category();
304
305 $category2 = $this->getDataGenerator()->create_category();
306 $category2b = $this->getDataGenerator()->create_category(['parent' => $category2->id]);
307 $course3 = $this->getDataGenerator()->create_course(['category' => $category2b->id]);
308
309 $role = $DB->get_record('role', array('shortname' => 'student'));
310 $this->getDataGenerator()->enrol_user($user2->id, $course3->id, $role->id);
311
7c30224a
AA
312 $record = new stdClass();
313 $record->courseid = $course->id;
314 $group = $this->getDataGenerator()->create_group($record);
315
316 $beforecount = $DB->count_records('event');
317
318 // Let's create a few events.
261a41f1 319 $siteevent = $this->create_calendar_event('site', $USER->id, 'site');
871988b0
JL
320
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',
331 );
332 $fs = get_file_storage();
333 $fs->create_file_from_string($filerecord, 'img contents');
334
7c30224a
AA
335 $record = new stdClass();
336 $record->courseid = $course->id;
f52459bb 337 $record->groupid = 0;
871988b0
JL
338 $record->description = array(
339 'format' => FORMAT_HTML,
340 'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">',
341 'itemid' => $draftidfile
342 );
261a41f1 343 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record);
f52459bb
JP
344
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);
349
7c30224a
AA
350 $record = new stdClass();
351 $record->courseid = $course->id;
352 $record->groupid = $group->id;
261a41f1 353 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);
7c30224a 354
754016ab
SL
355 $paramevents = array ('eventids' => array($siteevent->id), 'courseids' => array($course->id),
356 'groupids' => array($group->id), 'categoryids' => array($category->id));
357
7c30224a
AA
358 $options = array ('siteevents' => true, 'userevents' => true);
359 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1 360 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
7c30224a
AA
361
362 // Check to see if we got all events.
ef5b65da 363 $this->assertEquals(5, count($events['events']));
261a41f1 364 $this->assertEquals(0, count($events['warnings']));
7c30224a
AA
365 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7*WEEKSECS);
366 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
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']));
7c30224a 370
871988b0
JL
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']);
379 }
380 }
381 $this->assertEquals(2, $withdescription);
382
7c30224a 383 // Let's play around with caps.
f52459bb
JP
384
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);
390
7c30224a
AA
391 $this->setUser($user);
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(2, count($events['events'])); // site, user.
395 $this->assertEquals(2, count($events['warnings'])); // course, group.
7c30224a
AA
396
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);
261a41f1
AA
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.
7c30224a 403
ef5b65da 404 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS);
7c30224a 405 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
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.
7c30224a
AA
409
410 groups_add_member($group, $user);
411 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
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']));
7c30224a
AA
415
416 $paramevents = array ('courseids' => array($course->id), 'groupids' => array($group->id));
417 $events = core_calendar_external::get_calendar_events($paramevents, $options);
e2c85157 418 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
261a41f1
AA
419 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
420 $this->assertEquals(0, count($events['warnings']));
7c30224a 421
261a41f1 422 $paramevents = array ('groupids' => array($group->id, 23));
7c30224a 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(3, count($events['events'])); // site, user, group.
426 $this->assertEquals(1, count($events['warnings']));
7c30224a 427
261a41f1 428 $paramevents = array ('courseids' => array(23));
7c30224a 429 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
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']));
7c30224a
AA
433
434 $paramevents = array ();
435 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);
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(0, count($events['events'])); // nothing returned.
439 $this->assertEquals(0, count($events['warnings']));
7c30224a
AA
440
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);
261a41f1
AA
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']));
7c30224a
AA
447
448 $paramevents = array ('eventids' => array($siteevent->id));
449 $events = core_calendar_external::get_calendar_events($paramevents, $options);
261a41f1
AA
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']));
11dc7c1c
NM
453
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']));
39b85137
JL
460
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));
465
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);
471
472 $this->assertCount(5, $events['events']);
473
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();
479
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']);
754016ab
SL
484
485 // Create some category events.
486 $this->setAdminUser();
487 $record = new stdClass();
44ae0838 488 $record->courseid = 0;
754016ab 489 $record->categoryid = $category->id;
44ae0838
JL
490 $record->timestart = time() - DAYSECS;
491 $catevent1 = $this->create_calendar_event('category a', $USER->id, 'category', 0, time(), $record);
754016ab 492
44ae0838
JL
493 $record = new stdClass();
494 $record->courseid = 0;
754016ab 495 $record->categoryid = $category2->id;
44ae0838
JL
496 $record->timestart = time() + DAYSECS;
497 $catevent2 = $this->create_calendar_event('category b', $USER->id, 'category', 0, time(), $record);
754016ab
SL
498
499 // Now as student, make sure we get the events of the courses I am enrolled.
500 $this->setUser($user2);
501 $paramevents = array('categoryids' => array($category2b->id));
44ae0838 502 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);
754016ab
SL
503 $events = core_calendar_external::get_calendar_events($paramevents, $options);
504 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
505
506 // Should be just one, since there's just one category event of the course I am enrolled (course3 - cat2b).
507 $this->assertEquals(1, count($events['events']));
44ae0838 508 $this->assertEquals($catevent2->id, $events['events'][0]['id']);
e3c04bd9 509 $this->assertEquals($category2->id, $events['events'][0]['categoryid']);
44ae0838
JL
510 $this->assertEquals(0, count($events['warnings']));
511
512 // Now get category events but by course (there aren't course events in the course).
513 $paramevents = array('courseids' => array($course3->id));
514 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);
515 $events = core_calendar_external::get_calendar_events($paramevents, $options);
516 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
517 $this->assertEquals(1, count($events['events']));
518 $this->assertEquals($catevent2->id, $events['events'][0]['id']);
519 $this->assertEquals(0, count($events['warnings']));
520
521 // Empty events in one where I'm not enrolled and one parent category
522 // (parent of a category where this is a course where the user is enrolled).
523 $paramevents = array('categoryids' => array($category2->id, $category->id));
524 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);
525 $events = core_calendar_external::get_calendar_events($paramevents, $options);
526 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
527 $this->assertEquals(1, count($events['events']));
528 $this->assertEquals($catevent2->id, $events['events'][0]['id']);
754016ab
SL
529 $this->assertEquals(0, count($events['warnings']));
530
531 // Admin can see all category events.
532 $this->setAdminUser();
533 $paramevents = array('categoryids' => array($category->id, $category2->id, $category2b->id));
44ae0838 534 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);
754016ab
SL
535 $events = core_calendar_external::get_calendar_events($paramevents, $options);
536 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
537 $this->assertEquals(2, count($events['events']));
538 $this->assertEquals(0, count($events['warnings']));
44ae0838 539 $this->assertEquals($catevent1->id, $events['events'][0]['id']);
e3c04bd9 540 $this->assertEquals($category->id, $events['events'][0]['categoryid']);
44ae0838 541 $this->assertEquals($catevent2->id, $events['events'][1]['id']);
e3c04bd9 542 $this->assertEquals($category2->id, $events['events'][1]['categoryid']);
7c30224a 543 }
15c0b1cc
AA
544
545 /**
546 * Test core_calendar_external::create_calendar_events
547 */
548 public function test_core_create_calendar_events() {
549 global $DB, $USER, $SITE;
550
551 $this->resetAfterTest(true);
552 $this->setAdminUser();
553
554 // Create a few stuff to test with.
555 $user = $this->getDataGenerator()->create_user();
556 $course = $this->getDataGenerator()->create_course();
557 $record = new stdClass();
558 $record->courseid = $course->id;
559 $group = $this->getDataGenerator()->create_group($record);
560
561 $prevcount = $DB->count_records('event');
562
563 // Let's create a few events.
564 $events = array (
565 array('name' => 'site', 'courseid' => $SITE->id, 'eventtype' => 'site'),
566 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),
567 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),
568 array('name' => 'user')
569 );
570 $eventsret = core_calendar_external::create_calendar_events($events);
e2c85157 571 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
15c0b1cc
AA
572
573 // Check to see if things were created properly.
574 $aftercount = $DB->count_records('event');
575 $this->assertEquals($prevcount + 5, $aftercount);
576 $this->assertEquals(5, count($eventsret['events']));
577 $this->assertEquals(0, count($eventsret['warnings']));
578
579 $sitecontext = context_system::instance();
580 $coursecontext = context_course::instance($course->id);
581
582 $this->setUser($user);
583 $prevcount = $aftercount;
584 $events = array (
585 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),
586 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),
587 array('name' => 'user')
588 );
589 $role = $DB->get_record('role', array('shortname' => 'student'));
590 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
591 groups_add_member($group, $user);
592 $this->assignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
593 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
594 $eventsret = core_calendar_external::create_calendar_events($events);
595 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
596 // Check to see if things were created properly.
597 $aftercount = $DB->count_records('event');
598 $this->assertEquals($prevcount + 4, $aftercount);
599 $this->assertEquals(4, count($eventsret['events']));
600 $this->assertEquals(0, count($eventsret['warnings']));
601
602 // Check to see nothing was created without proper permission.
603 $this->setGuestUser();
604 $prevcount = $DB->count_records('event');
605 $eventsret = core_calendar_external::create_calendar_events($events);
606 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
607 $aftercount = $DB->count_records('event');
608 $this->assertEquals($prevcount, $aftercount);
609 $this->assertEquals(0, count($eventsret['events']));
610 $this->assertEquals(3, count($eventsret['warnings']));
611
612 $this->setUser($user);
613 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);
614 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);
615 $prevcount = $DB->count_records('event');
616 $eventsret = core_calendar_external::create_calendar_events($events);
617 $eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
618 $aftercount = $DB->count_records('event');
619 $this->assertEquals($prevcount + 1, $aftercount); // User event.
620 $this->assertEquals(1, count($eventsret['events']));
621 $this->assertEquals(2, count($eventsret['warnings']));
622 }
4139f131
RW
623
624 /**
625 * Requesting calendar events from a given time should return all events with a sort
626 * time at or after the requested time. All events prior to that time should not
627 * be return.
628 *
629 * If there are no events on or after the given time then an empty result set should
630 * be returned.
631 */
1aeb58fa 632 public function test_get_calendar_action_events_by_timesort_after_time() {
4139f131
RW
633 $user = $this->getDataGenerator()->create_user();
634 $course = $this->getDataGenerator()->create_course();
635 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
636 $moduleinstance = $generator->create_instance(['course' => $course->id]);
637
638 $this->getDataGenerator()->enrol_user($user->id, $course->id);
639 $this->resetAfterTest(true);
640 $this->setUser($user);
641
642 $params = [
643 'type' => CALENDAR_EVENT_TYPE_ACTION,
644 'modulename' => 'assign',
645 'instance' => $moduleinstance->id,
646 'courseid' => $course->id,
647 ];
648
649 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
650 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
651 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
652 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
653 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
654 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
655 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
656 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
657
658 $result = core_calendar_external::get_calendar_action_events_by_timesort(5);
659 $result = external_api::clean_returnvalue(
660 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
661 $result
662 );
663 $events = $result['events'];
664
665 $this->assertCount(4, $events);
666 $this->assertEquals('Event 5', $events[0]['name']);
667 $this->assertEquals('Event 6', $events[1]['name']);
668 $this->assertEquals('Event 7', $events[2]['name']);
669 $this->assertEquals('Event 8', $events[3]['name']);
670 $this->assertEquals($event5->id, $result['firstid']);
671 $this->assertEquals($event8->id, $result['lastid']);
672
673 $result = core_calendar_external::get_calendar_action_events_by_timesort(9);
674 $result = external_api::clean_returnvalue(
675 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
676 $result
677 );
678
679 $this->assertEmpty($result['events']);
680 $this->assertNull($result['firstid']);
681 $this->assertNull($result['lastid']);
7af6528e
DM
682
683 // Requesting action events on behalf of another user.
684 $this->setAdminUser();
685 $result = core_calendar_external::get_calendar_action_events_by_timesort(5, null, 0, 20, false, $user->id);
686 $result = external_api::clean_returnvalue(
687 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
688 $result
689 );
690 $events = $result['events'];
691
692 $this->assertCount(4, $events);
693 $this->assertEquals('Event 5', $events[0]['name']);
694 $this->assertEquals('Event 6', $events[1]['name']);
695 $this->assertEquals('Event 7', $events[2]['name']);
696 $this->assertEquals('Event 8', $events[3]['name']);
697 $this->assertEquals($event5->id, $result['firstid']);
698 $this->assertEquals($event8->id, $result['lastid']);
4139f131
RW
699 }
700
701 /**
702 * Requesting calendar events before a given time should return all events with a sort
703 * time at or before the requested time (inclusive). All events after that time
704 * should not be returned.
705 *
706 * If there are no events before the given time then an empty result set should be
707 * returned.
708 */
1aeb58fa 709 public function test_get_calendar_action_events_by_timesort_before_time() {
4139f131
RW
710 $user = $this->getDataGenerator()->create_user();
711 $course = $this->getDataGenerator()->create_course();
712 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
713 $moduleinstance = $generator->create_instance(['course' => $course->id]);
714
715 $this->getDataGenerator()->enrol_user($user->id, $course->id);
716 $this->resetAfterTest(true);
717 $this->setUser($user);
718
719 $params = [
720 'type' => CALENDAR_EVENT_TYPE_ACTION,
721 'modulename' => 'assign',
722 'instance' => $moduleinstance->id,
723 'courseid' => $course->id,
724 ];
725
726 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
727 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
728 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
729 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
730 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
731 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
732 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
733 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 9]));
734
735 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5);
736 $result = external_api::clean_returnvalue(
737 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
738 $result
739 );
740 $events = $result['events'];
741
742 $this->assertCount(4, $events);
743 $this->assertEquals('Event 1', $events[0]['name']);
744 $this->assertEquals('Event 2', $events[1]['name']);
745 $this->assertEquals('Event 3', $events[2]['name']);
746 $this->assertEquals('Event 4', $events[3]['name']);
747 $this->assertEquals($event1->id, $result['firstid']);
748 $this->assertEquals($event4->id, $result['lastid']);
749
750 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 1);
751 $result = external_api::clean_returnvalue(
752 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
753 $result
754 );
755
756 $this->assertEmpty($result['events']);
757 $this->assertNull($result['firstid']);
758 $this->assertNull($result['lastid']);
7af6528e
DM
759
760 // Requesting action events on behalf of another user.
761 $this->setAdminUser();
762
763 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5, 0, 20, false, $user->id);
764 $result = external_api::clean_returnvalue(
765 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
766 $result
767 );
768 $events = $result['events'];
769
770 $this->assertCount(4, $events);
771 $this->assertEquals('Event 1', $events[0]['name']);
772 $this->assertEquals('Event 2', $events[1]['name']);
773 $this->assertEquals('Event 3', $events[2]['name']);
774 $this->assertEquals('Event 4', $events[3]['name']);
775 $this->assertEquals($event1->id, $result['firstid']);
776 $this->assertEquals($event4->id, $result['lastid']);
4139f131
RW
777 }
778
5900513f
MG
779 /**
780 * Test retrieving event that was overridden for a user
781 */
782 public function test_get_calendar_events_override() {
783 $user = $this->getDataGenerator()->create_user();
63e9e382 784 $user2 = $this->getDataGenerator()->create_user();
5900513f
MG
785 $teacher = $this->getDataGenerator()->create_user();
786 $anotheruser = $this->getDataGenerator()->create_user();
787 $course = $this->getDataGenerator()->create_course();
788 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
789 $moduleinstance = $generator->create_instance(['course' => $course->id]);
790
63e9e382
MG
791 $this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
792 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
5900513f
MG
793 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
794 $this->resetAfterTest(true);
795 $this->setAdminUser();
796
797 $params = [
798 'type' => CALENDAR_EVENT_TYPE_ACTION,
799 'modulename' => 'assign',
800 'instance' => $moduleinstance->id,
801 ];
802
803 $now = time();
63e9e382 804 // Create two events - one for everybody in the course and one only for the first student.
5900513f
MG
805 $event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS, $params + ['courseid' => $course->id]);
806 $event2 = $this->create_calendar_event('User event', $user->id, 'due', 0, $now + 2*DAYSECS, $params + ['courseid' => 0]);
807
63e9e382
MG
808 // Retrieve course events for the second student - only one "Base event" is returned.
809 $this->setUser($user2);
5900513f
MG
810 $paramevents = array('courseids' => array($course->id));
811 $options = array ('siteevents' => true, 'userevents' => true);
812 $events = core_calendar_external::get_calendar_events($paramevents, $options);
813 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
814 $this->assertEquals(1, count($events['events']));
815 $this->assertEquals(0, count($events['warnings']));
816 $this->assertEquals('Base event', $events['events'][0]['name']);
817
63e9e382 818 // Retrieve events for the first student - both events are returned.
5900513f
MG
819 $this->setUser($user);
820 $events = core_calendar_external::get_calendar_events($paramevents, $options);
821 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
822 $this->assertEquals(2, count($events['events']));
823 $this->assertEquals(0, count($events['warnings']));
824 $this->assertEquals('Base event', $events['events'][0]['name']);
825 $this->assertEquals('User event', $events['events'][1]['name']);
826
827 // Retrieve events by id as a teacher, 'User event' should be returned since teacher has access to this course.
828 $this->setUser($teacher);
829 $paramevents = ['eventids' => [$event2->id]];
830 $events = core_calendar_external::get_calendar_events($paramevents, $options);
831 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
832 $this->assertEquals(1, count($events['events']));
833 $this->assertEquals(0, count($events['warnings']));
834 $this->assertEquals('User event', $events['events'][0]['name']);
835
836 // Retrieve events by id as another user, nothing should be returned.
837 $this->setUser($anotheruser);
838 $paramevents = ['eventids' => [$event2->id, $event1->id]];
839 $events = core_calendar_external::get_calendar_events($paramevents, $options);
840 $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
841 $this->assertEquals(0, count($events['events']));
842 $this->assertEquals(0, count($events['warnings']));
843 }
844
4139f131
RW
845 /**
846 * Requesting calendar events within a given time range should return all events with
847 * a sort time between the lower and upper time bound (inclusive).
848 *
849 * If there are no events in the given time range then an empty result set should be
850 * returned.
851 */
1aeb58fa 852 public function test_get_calendar_action_events_by_timesort_time_range() {
4139f131
RW
853 $user = $this->getDataGenerator()->create_user();
854 $course = $this->getDataGenerator()->create_course();
855 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
856 $moduleinstance = $generator->create_instance(['course' => $course->id]);
857
858 $this->getDataGenerator()->enrol_user($user->id, $course->id);
859 $this->resetAfterTest(true);
860 $this->setUser($user);
861
862 $params = [
863 'type' => CALENDAR_EVENT_TYPE_ACTION,
864 'modulename' => 'assign',
865 'instance' => $moduleinstance->id,
866 'courseid' => $course->id,
867 ];
868
869 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
870 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
871 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
872 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
873 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
874 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
875 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
876 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
877
878 $result = core_calendar_external::get_calendar_action_events_by_timesort(3, 6);
879 $result = external_api::clean_returnvalue(
880 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
881 $result
882 );
883 $events = $result['events'];
884
885 $this->assertCount(4, $events);
886 $this->assertEquals('Event 3', $events[0]['name']);
887 $this->assertEquals('Event 4', $events[1]['name']);
888 $this->assertEquals('Event 5', $events[2]['name']);
889 $this->assertEquals('Event 6', $events[3]['name']);
890 $this->assertEquals($event3->id, $result['firstid']);
891 $this->assertEquals($event6->id, $result['lastid']);
892
893 $result = core_calendar_external::get_calendar_action_events_by_timesort(10, 15);
894 $result = external_api::clean_returnvalue(
895 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
896 $result
897 );
898
899 $this->assertEmpty($result['events']);
900 $this->assertNull($result['firstid']);
901 $this->assertNull($result['lastid']);
902 }
903
904 /**
905 * Requesting calendar events within a given time range and a limit and offset should return
906 * the number of events up to the given limit value that have a sort time between the lower
907 * and uppper time bound (inclusive) where the result set is shifted by the offset value.
908 *
909 * If there are no events in the given time range then an empty result set should be
910 * returned.
911 */
1aeb58fa 912 public function test_get_calendar_action_events_by_timesort_time_limit_offset() {
4139f131
RW
913 $user = $this->getDataGenerator()->create_user();
914 $course = $this->getDataGenerator()->create_course();
915 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
916 $moduleinstance = $generator->create_instance(['course' => $course->id]);
917
918 $this->getDataGenerator()->enrol_user($user->id, $course->id);
919 $this->resetAfterTest(true);
920 $this->setUser($user);
921
922 $params = [
923 'type' => CALENDAR_EVENT_TYPE_ACTION,
924 'modulename' => 'assign',
925 'instance' => $moduleinstance->id,
926 'courseid' => $course->id,
927 ];
928
929 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));
930 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));
931 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));
932 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));
933 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));
934 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));
935 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));
936 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));
937
938 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event3->id, 2);
939 $result = external_api::clean_returnvalue(
940 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
941 $result
942 );
943 $events = $result['events'];
944
945 $this->assertCount(2, $events);
946 $this->assertEquals('Event 4', $events[0]['name']);
947 $this->assertEquals('Event 5', $events[1]['name']);
948 $this->assertEquals($event4->id, $result['firstid']);
949 $this->assertEquals($event5->id, $result['lastid']);
950
951 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event5->id, 2);
952 $result = external_api::clean_returnvalue(
953 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
954 $result
955 );
956 $events = $result['events'];
957
958 $this->assertCount(2, $events);
959 $this->assertEquals('Event 6', $events[0]['name']);
960 $this->assertEquals('Event 7', $events[1]['name']);
961 $this->assertEquals($event6->id, $result['firstid']);
962 $this->assertEquals($event7->id, $result['lastid']);
963
964 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event7->id, 2);
965 $result = external_api::clean_returnvalue(
966 core_calendar_external::get_calendar_action_events_by_timesort_returns(),
967 $result
968 );
969
970 $this->assertEmpty($result['events']);
971 $this->assertNull($result['firstid']);
972 $this->assertNull($result['lastid']);
973 }
5e026bb0 974
c84ee678
AG
975 /**
976 * Check that it is possible to restrict the calendar events to events where the user is not suspended in the course.
977 */
978 public function test_get_calendar_action_events_by_timesort_suspended_course() {
979 $this->resetAfterTest();
980 $user1 = $this->getDataGenerator()->create_user();
981 $user2 = $this->getDataGenerator()->create_user();
982 $course = $this->getDataGenerator()->create_course();
983 $this->setAdminUser();
984 $lesson = $this->getDataGenerator()->create_module('lesson', [
985 'name' => 'Lesson 1',
986 'course' => $course->id,
987 'available' => time(),
988 'deadline' => (time() + (60 * 60 * 24 * 5))
989 ]
990 );
991 $this->getDataGenerator()->enrol_user($user1->id, $course->id, null, 'manual', 0, 0, ENROL_USER_SUSPENDED);
992 $this->getDataGenerator()->enrol_user($user2->id, $course->id);
993
994 $this->setUser($user1);
995 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true);
996 $this->assertEmpty($result->events);
997 $this->setUser($user2);
998 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true);
999 $this->assertCount(1, $result->events);
1000 $this->assertEquals('Lesson 1 closes', $result->events[0]->name);
1001 }
1002
5e026bb0
RW
1003 /**
1004 * Requesting calendar events from a given course and time should return all
1005 * events with a sort time at or after the requested time. All events prior
1006 * to that time should not be return.
1007 *
1008 * If there are no events on or after the given time then an empty result set should
1009 * be returned.
1010 */
1aeb58fa 1011 public function test_get_calendar_action_events_by_course_after_time() {
5e026bb0
RW
1012 $user = $this->getDataGenerator()->create_user();
1013 $course1 = $this->getDataGenerator()->create_course();
1014 $course2 = $this->getDataGenerator()->create_course();
1015 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1016 $instance1 = $generator->create_instance(['course' => $course1->id]);
1017 $instance2 = $generator->create_instance(['course' => $course2->id]);
1018 $records = [];
1019
1020 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1021 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1022 $this->resetAfterTest(true);
1023 $this->setUser($user);
1024
1025 for ($i = 1; $i < 19; $i++) {
1026 $courseid = ($i < 9) ? $course1->id : $course2->id;
1027 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1028 $records[] = $this->create_calendar_event(
1029 sprintf('Event %d', $i),
1030 $user->id,
1031 'user',
1032 0,
1033 1,
1034 [
1035 'type' => CALENDAR_EVENT_TYPE_ACTION,
1036 'courseid' => $courseid,
1037 'timesort' => $i,
1038 'modulename' => 'assign',
1039 'instance' => $instance,
1040 ]
1041 );
1042 }
1043
1044 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 5);
1045 $result = external_api::clean_returnvalue(
1046 core_calendar_external::get_calendar_action_events_by_course_returns(),
1047 $result
1048 );
1049 $result = $result['events'];
1050
1051 $this->assertCount(4, $result);
1052 $this->assertEquals('Event 5', $result[0]['name']);
1053 $this->assertEquals('Event 6', $result[1]['name']);
1054 $this->assertEquals('Event 7', $result[2]['name']);
1055 $this->assertEquals('Event 8', $result[3]['name']);
1056
1057 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 9);
1058 $result = external_api::clean_returnvalue(
1059 core_calendar_external::get_calendar_action_events_by_course_returns(),
1060 $result
1061 );
1062 $result = $result['events'];
1063
1064 $this->assertEmpty($result);
1065 }
1066
1067 /**
1068 * Requesting calendar events for a course and before a given time should return
1069 * all events with a sort time at or before the requested time (inclusive). All
1070 * events after that time should not be returned.
1071 *
1072 * If there are no events before the given time then an empty result set should be
1073 * returned.
1074 */
1aeb58fa 1075 public function test_get_calendar_action_events_by_course_before_time() {
5e026bb0
RW
1076 $user = $this->getDataGenerator()->create_user();
1077 $course1 = $this->getDataGenerator()->create_course();
1078 $course2 = $this->getDataGenerator()->create_course();
1079 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1080 $instance1 = $generator->create_instance(['course' => $course1->id]);
1081 $instance2 = $generator->create_instance(['course' => $course2->id]);
1082 $records = [];
1083
1084 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1085 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1086 $this->resetAfterTest(true);
1087 $this->setUser($user);
1088
1089 for ($i = 1; $i < 19; $i++) {
1090 $courseid = ($i < 9) ? $course1->id : $course2->id;
1091 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1092 $records[] = $this->create_calendar_event(
1093 sprintf('Event %d', $i),
1094 $user->id,
1095 'user',
1096 0,
1097 1,
1098 [
1099 'type' => CALENDAR_EVENT_TYPE_ACTION,
1100 'courseid' => $courseid,
1101 'timesort' => $i + 1,
1102 'modulename' => 'assign',
1103 'instance' => $instance,
1104 ]
1105 );
1106 }
1107
1108 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 5);
1109 $result = external_api::clean_returnvalue(
1110 core_calendar_external::get_calendar_action_events_by_course_returns(),
1111 $result
1112 );
1113 $result = $result['events'];
1114
1115 $this->assertCount(4, $result);
1116 $this->assertEquals('Event 1', $result[0]['name']);
1117 $this->assertEquals('Event 2', $result[1]['name']);
1118 $this->assertEquals('Event 3', $result[2]['name']);
1119 $this->assertEquals('Event 4', $result[3]['name']);
1120
1121 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 1);
1122 $result = external_api::clean_returnvalue(
1123 core_calendar_external::get_calendar_action_events_by_course_returns(),
1124 $result
1125 );
1126 $result = $result['events'];
1127
1128 $this->assertEmpty($result);
1129 }
1130
1131 /**
1132 * Requesting calendar events for a course and within a given time range should
1133 * return all events with a sort time between the lower and upper time bound
1134 * (inclusive).
1135 *
1136 * If there are no events in the given time range then an empty result set should be
1137 * returned.
1138 */
1aeb58fa 1139 public function test_get_calendar_action_events_by_course_time_range() {
5e026bb0
RW
1140 $user = $this->getDataGenerator()->create_user();
1141 $course1 = $this->getDataGenerator()->create_course();
1142 $course2 = $this->getDataGenerator()->create_course();
1143 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1144 $instance1 = $generator->create_instance(['course' => $course1->id]);
1145 $instance2 = $generator->create_instance(['course' => $course2->id]);
1146 $records = [];
1147
1148 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1149 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1150 $this->resetAfterTest(true);
1151 $this->setUser($user);
1152
1153 for ($i = 1; $i < 19; $i++) {
1154 $courseid = ($i < 9) ? $course1->id : $course2->id;
1155 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1156 $records[] = $this->create_calendar_event(
1157 sprintf('Event %d', $i),
1158 $user->id,
1159 'user',
1160 0,
1161 1,
1162 [
1163 'type' => CALENDAR_EVENT_TYPE_ACTION,
1164 'courseid' => $courseid,
1165 'timesort' => $i,
1166 'modulename' => 'assign',
1167 'instance' => $instance,
1168 ]
1169 );
1170 }
1171
1172 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 3, 6);
1173 $result = external_api::clean_returnvalue(
1174 core_calendar_external::get_calendar_action_events_by_course_returns(),
1175 $result
1176 );
1177 $result = $result['events'];
1178
1179 $this->assertCount(4, $result);
1180 $this->assertEquals('Event 3', $result[0]['name']);
1181 $this->assertEquals('Event 4', $result[1]['name']);
1182 $this->assertEquals('Event 5', $result[2]['name']);
1183 $this->assertEquals('Event 6', $result[3]['name']);
1184
1185 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 10, 15);
1186 $result = external_api::clean_returnvalue(
1187 core_calendar_external::get_calendar_action_events_by_course_returns(),
1188 $result
1189 );
1190 $result = $result['events'];
1191
1192 $this->assertEmpty($result);
1193 }
1194
1195 /**
1196 * Requesting calendar events for a course and within a given time range and a limit
1197 * and offset should return the number of events up to the given limit value that have
1198 * a sort time between the lower and uppper time bound (inclusive) where the result
1199 * set is shifted by the offset value.
1200 *
1201 * If there are no events in the given time range then an empty result set should be
1202 * returned.
1203 */
1aeb58fa 1204 public function test_get_calendar_action_events_by_course_time_limit_offset() {
5e026bb0
RW
1205 $user = $this->getDataGenerator()->create_user();
1206 $course1 = $this->getDataGenerator()->create_course();
1207 $course2 = $this->getDataGenerator()->create_course();
1208 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1209 $instance1 = $generator->create_instance(['course' => $course1->id]);
1210 $instance2 = $generator->create_instance(['course' => $course2->id]);
1211 $records = [];
1212
1213 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1214 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1215 $this->resetAfterTest(true);
1216 $this->setUser($user);
1217
1218 for ($i = 1; $i < 19; $i++) {
1219 $courseid = ($i < 9) ? $course1->id : $course2->id;
1220 $instance = ($i < 9) ? $instance1->id : $instance2->id;
1221 $records[] = $this->create_calendar_event(
1222 sprintf('Event %d', $i),
1223 $user->id,
1224 'user',
1225 0,
1226 1,
1227 [
1228 'type' => CALENDAR_EVENT_TYPE_ACTION,
1229 'courseid' => $courseid,
1230 'timesort' => $i,
1231 'modulename' => 'assign',
1232 'instance' => $instance,
1233 ]
1234 );
1235 }
1236
1237 $result = core_calendar_external::get_calendar_action_events_by_course(
1238 $course1->id, 2, 7, $records[2]->id, 2);
1239 $result = external_api::clean_returnvalue(
1240 core_calendar_external::get_calendar_action_events_by_course_returns(),
1241 $result
1242 );
1243 $result = $result['events'];
1244
1245 $this->assertCount(2, $result);
1246 $this->assertEquals('Event 4', $result[0]['name']);
1247 $this->assertEquals('Event 5', $result[1]['name']);
1248
1249 $result = core_calendar_external::get_calendar_action_events_by_course(
1250 $course1->id, 2, 7, $records[4]->id, 2);
1251 $result = external_api::clean_returnvalue(
1252 core_calendar_external::get_calendar_action_events_by_course_returns(),
1253 $result
1254 );
1255 $result = $result['events'];
1256
1257 $this->assertCount(2, $result);
1258 $this->assertEquals('Event 6', $result[0]['name']);
1259 $this->assertEquals('Event 7', $result[1]['name']);
1260
1261 $result = core_calendar_external::get_calendar_action_events_by_course(
1262 $course1->id, 2, 7, $records[6]->id, 2);
1263 $result = external_api::clean_returnvalue(
1264 core_calendar_external::get_calendar_action_events_by_course_returns(),
1265 $result
1266 );
1267 $result = $result['events'];
1268
1269 $this->assertEmpty($result);
1270 }
1aeb58fa
RW
1271
1272 /**
1273 * Test that get_action_events_by_courses will return a list of events for each
1274 * course you provided as long as the user is enrolled in the course.
1275 */
1276 public function test_get_action_events_by_courses() {
1277 $user = $this->getDataGenerator()->create_user();
1278 $course1 = $this->getDataGenerator()->create_course();
1279 $course2 = $this->getDataGenerator()->create_course();
1280 $course3 = $this->getDataGenerator()->create_course();
1281 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
1282 $instance1 = $generator->create_instance(['course' => $course1->id]);
1283 $instance2 = $generator->create_instance(['course' => $course2->id]);
1284 $instance3 = $generator->create_instance(['course' => $course3->id]);
1285 $records = [];
1286 $mapresult = function($result) {
1287 $groupedbycourse = [];
1288 foreach ($result['groupedbycourse'] as $group) {
1289 $events = $group['events'];
1290 $courseid = $group['courseid'];
1291 $groupedbycourse[$courseid] = $events;
1292 }
1293
1294 return $groupedbycourse;
1295 };
1296
1297 $this->getDataGenerator()->enrol_user($user->id, $course1->id);
1298 $this->getDataGenerator()->enrol_user($user->id, $course2->id);
1299 $this->resetAfterTest(true);
1300 $this->setUser($user);
1301
1302 for ($i = 1; $i < 10; $i++) {
1303 if ($i < 3) {
1304 $courseid = $course1->id;
1305 $instance = $instance1->id;
1306 } else if ($i < 6) {
1307 $courseid = $course2->id;
1308 $instance = $instance2->id;
1309 } else {
1310 $courseid = $course3->id;
1311 $instance = $instance3->id;
1312 }
1313
1314 $records[] = $this->create_calendar_event(
1315 sprintf('Event %d', $i),
1316 $user->id,
1317 'user',
1318 0,
1319 1,
1320 [
1321 'type' => CALENDAR_EVENT_TYPE_ACTION,
1322 'courseid' => $courseid,
1323 'timesort' => $i,
1324 'modulename' => 'assign',
1325 'instance' => $instance,
1326 ]
1327 );
1328 }
1329
1330 $result = core_calendar_external::get_calendar_action_events_by_courses([], 1);
1331 $result = external_api::clean_returnvalue(
1332 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1333 $result
1334 );
1335 $result = $result['groupedbycourse'];
1336
1337 $this->assertEmpty($result);
1338
1339 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 3);
1340 $result = external_api::clean_returnvalue(
1341 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1342 $result
1343 );
1344
1345 $groupedbycourse = $mapresult($result);
1346
1347 $this->assertEmpty($groupedbycourse[$course1->id]);
1348
1349 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 1);
1350 $result = external_api::clean_returnvalue(
1351 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1352 $result
1353 );
1354 $groupedbycourse = $mapresult($result);
1355
1356 $this->assertCount(2, $groupedbycourse[$course1->id]);
1357 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1358 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);
1359
1360 $result = core_calendar_external::get_calendar_action_events_by_courses(
1361 [$course1->id, $course2->id], 1);
1362 $result = external_api::clean_returnvalue(
1363 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1364 $result
1365 );
1366 $groupedbycourse = $mapresult($result);
1367
1368 $this->assertCount(2, $groupedbycourse[$course1->id]);
1369 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1370 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);
1371 $this->assertCount(3, $groupedbycourse[$course2->id]);
1372 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1373 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);
1374 $this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']);
1375
1376 $result = core_calendar_external::get_calendar_action_events_by_courses(
1377 [$course1->id, $course2->id], 2, 4);
1378 $result = external_api::clean_returnvalue(
1379 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1380 $result
1381 );
1382 $groupedbycourse = $mapresult($result);
1383
1384 $this->assertCount(2, $groupedbycourse);
1385 $this->assertCount(1, $groupedbycourse[$course1->id]);
1386 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][0]['name']);
1387 $this->assertCount(2, $groupedbycourse[$course2->id]);
1388 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1389 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);
1390
1391 $result = core_calendar_external::get_calendar_action_events_by_courses(
1392 [$course1->id, $course2->id], 1, null, 1);
1393 $result = external_api::clean_returnvalue(
1394 core_calendar_external::get_calendar_action_events_by_courses_returns(),
1395 $result
1396 );
1397 $groupedbycourse = $mapresult($result);
1398
1399 $this->assertCount(2, $groupedbycourse);
1400 $this->assertCount(1, $groupedbycourse[$course1->id]);
1401 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
1402 $this->assertCount(1, $groupedbycourse[$course2->id]);
1403 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);
1404 }
5d942f5a
SL
1405
1406 /**
1407 * Test for deleting module events.
1408 */
1409 public function test_delete_calendar_events_for_modules() {
1410 $this->resetAfterTest();
1411 $this->setAdminUser();
1412 $course = $this->getDataGenerator()->create_course();
1413 $nexttime = time() + DAYSECS;
1414 $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'duedate' => $nexttime]);
1415 $events = calendar_get_events(time(), $nexttime, true, true, true);
1416 $this->assertCount(1, $events);
1417 $params = [];
1418 foreach ($events as $event) {
1419 $params[] = [
1420 'eventid' => $event->id,
1421 'repeat' => false
1422 ];
1423 }
1424
1425 $this->expectException('moodle_exception');
1426 core_calendar_external::delete_calendar_events($params);
1427 }
c6fb9310
RW
1428
1429 /**
1430 * Updating the event start day should change the date value but leave
1431 * the time of day unchanged.
1432 */
1433 public function test_update_event_start_day() {
1434 $generator = $this->getDataGenerator();
1435 $user = $generator->create_user();
1436 $roleid = $generator->create_role();
1437 $context = \context_system::instance();
96283892
RW
1438 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1439 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
c6fb9310
RW
1440 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1441
1442 $generator->role_assign($roleid, $user->id, $context->id);
1443 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1444
1445 $this->setUser($user);
1446 $this->resetAfterTest(true);
1447
1448 $event = $this->create_calendar_event(
1449 'Test event',
1450 $user->id,
1451 'user',
1452 0,
1453 null,
1454 [
1455 'courseid' => 0,
96283892 1456 'timestart' => $originalstarttime->getTimestamp()
c6fb9310
RW
1457 ]
1458 );
1459
96283892 1460 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
c6fb9310
RW
1461 $result = external_api::clean_returnvalue(
1462 core_calendar_external::update_event_start_day_returns(),
1463 $result
1464 );
1465
1466 $this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);
1467 }
1468
1469 /**
909d0858
RW
1470 * A user should not be able to edit an event that they don't have
1471 * capabilities for.
c6fb9310
RW
1472 */
1473 public function test_update_event_start_day_no_permission() {
1474 $generator = $this->getDataGenerator();
1475 $user = $generator->create_user();
1476 $roleid = $generator->create_role();
1477 $context = \context_system::instance();
96283892
RW
1478 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1479 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
c6fb9310
RW
1480 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1481
1482 $generator->role_assign($roleid, $user->id, $context->id);
1483 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1484
1485 $this->setUser($user);
1486 $this->resetAfterTest(true);
1487
1488 $event = $this->create_calendar_event(
1489 'Test event',
1490 $user->id,
1491 'user',
1492 0,
1493 null,
1494 [
1495 'courseid' => 0,
96283892 1496 'timestart' => $originalstarttime->getTimestamp()
c6fb9310
RW
1497 ]
1498 );
1499
1500 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1501 $this->expectException('moodle_exception');
96283892 1502 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
c6fb9310
RW
1503 $result = external_api::clean_returnvalue(
1504 core_calendar_external::update_event_start_day_returns(),
1505 $result
1506 );
1507 }
909d0858
RW
1508
1509 /**
1510 * A user should not be able to update a module event.
1511 */
1512 public function test_update_event_start_day_module_event() {
1513 $generator = $this->getDataGenerator();
1514 $user = $generator->create_user();
1515 $course = $generator->create_course();
96283892
RW
1516 $plugingenerator = $generator->get_plugin_generator('mod_assign');
1517 $moduleinstance = $plugingenerator->create_instance(['course' => $course->id]);
909d0858
RW
1518 $roleid = $generator->create_role();
1519 $context = \context_course::instance($course->id);
96283892
RW
1520 $originalstarttime = new DateTimeImmutable('2017-01-1T15:00:00+08:00');
1521 $newstartdate = new DateTimeImmutable('2018-02-2T10:00:00+08:00');
909d0858
RW
1522 $expected = new DateTimeImmutable('2018-02-2T15:00:00+08:00');
1523
1524 $generator->role_assign($roleid, $user->id, $context->id);
1525 $generator->enrol_user($user->id, $course->id);
1526
1527 $this->setUser($user);
1528 $this->resetAfterTest(true);
1529
1530 $event = $this->create_calendar_event(
1531 'Test event',
1532 $user->id,
1533 'user',
1534 0,
1535 null,
1536 [
1537 'modulename' => 'assign',
1538 'instance' => $moduleinstance->id,
1539 'courseid' => $course->id,
96283892 1540 'timestart' => $originalstarttime->getTimestamp()
909d0858
RW
1541 ]
1542 );
1543
1544 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1545 $this->expectException('moodle_exception');
96283892 1546 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
909d0858
RW
1547 $result = external_api::clean_returnvalue(
1548 core_calendar_external::update_event_start_day_returns(),
1549 $result
1550 );
1551 }
f0e6ff9a 1552
69b160ed
RW
1553 /**
1554 * Submit a request where the time duration until is earlier than the time
1555 * start in order to get a validation error from the server.
1556 */
1557 public function test_submit_create_update_form_validation_error() {
1558 $user = $this->getDataGenerator()->create_user();
1559 $timestart = new DateTime();
1560 $interval = new DateInterval("P1D"); // One day.
1561 $timedurationuntil = new DateTime();
1562 $timedurationuntil->sub($interval);
1563 $formdata = [
1564 'id' => 0,
1565 'userid' => $user->id,
1566 'modulename' => '',
1567 'instance' => 0,
1568 'visible' => 1,
1569 'name' => 'Test',
1570 'timestart' => [
1571 'day' => $timestart->format('j'),
1572 'month' => $timestart->format('n'),
1573 'year' => $timestart->format('Y'),
1574 'hour' => $timestart->format('G'),
1575 'minute' => 0,
1576 ],
1577 'eventtype' => 'user',
1578 'description' => [
1579 'text' => '',
1580 'format' => 1,
1581 ],
ef4e04ee 1582 'location' => 'Test',
69b160ed
RW
1583 'duration' => 1,
1584 'timedurationuntil' => [
1585 'day' => $timedurationuntil->format('j'),
1586 'month' => $timedurationuntil->format('n'),
1587 'year' => $timedurationuntil->format('Y'),
1588 'hour' => $timedurationuntil->format('G'),
1589 'minute' => 0,
1590 ]
1591 ];
1592
1593 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1594
1595 $querystring = http_build_query($formdata, '', '&amp;');
1596
1597 $this->resetAfterTest(true);
1598 $this->setUser($user);
1599
1600 $result = external_api::clean_returnvalue(
1601 core_calendar_external::submit_create_update_form_returns(),
1602 core_calendar_external::submit_create_update_form($querystring)
1603 );
1604
1605 $this->assertTrue($result['validationerror']);
1606 }
1607
1608 /**
1609 * A user with the moodle/calendar:manageownentries capability at the
1610 * system context should be able to create a user event.
1611 */
1612 public function test_submit_create_update_form_create_user_event() {
1613 $generator = $this->getDataGenerator();
1614 $user = $generator->create_user();
1615 $roleid = $generator->create_role();
1616 $context = \context_system::instance();
1617 $timestart = new DateTime();
1618 $interval = new DateInterval("P1D"); // One day.
1619 $timedurationuntil = new DateTime();
1620 $timedurationuntil->add($interval);
1621 $formdata = [
1622 'id' => 0,
1623 'userid' => $user->id,
1624 'modulename' => '',
1625 'instance' => 0,
1626 'visible' => 1,
1627 'name' => 'Test',
1628 'timestart' => [
1629 'day' => $timestart->format('j'),
1630 'month' => $timestart->format('n'),
1631 'year' => $timestart->format('Y'),
1632 'hour' => $timestart->format('G'),
1633 'minute' => 0,
1634 ],
1635 'eventtype' => 'user',
1636 'description' => [
1637 'text' => '',
1638 'format' => 1,
ea5f7707 1639 'itemid' => 0
69b160ed 1640 ],
ef4e04ee 1641 'location' => 'Test',
69b160ed
RW
1642 'duration' => 1,
1643 'timedurationuntil' => [
1644 'day' => $timedurationuntil->format('j'),
1645 'month' => $timedurationuntil->format('n'),
1646 'year' => $timedurationuntil->format('Y'),
1647 'hour' => $timedurationuntil->format('G'),
1648 'minute' => 0,
1649 ]
1650 ];
1651
1652 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1653 $querystring = http_build_query($formdata, '', '&');
1654
1655 $generator->role_assign($roleid, $user->id, $context->id);
1656 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
1657
1658 $user->ignoresesskey = true;
1659 $this->resetAfterTest(true);
1660 $this->setUser($user);
1661
1662 $result = external_api::clean_returnvalue(
1663 core_calendar_external::submit_create_update_form_returns(),
1664 core_calendar_external::submit_create_update_form($querystring)
1665 );
1666
1667 $event = $result['event'];
1668 $this->assertEquals($user->id, $event['userid']);
1669 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1670 $this->assertEquals($formdata['name'], $event['name']);
1671 }
1672
1673 /**
1674 * A user without the moodle/calendar:manageownentries capability at the
1675 * system context should not be able to create a user event.
1676 */
1677 public function test_submit_create_update_form_create_user_event_no_permission() {
1678 $generator = $this->getDataGenerator();
1679 $user = $generator->create_user();
1680 $roleid = $generator->create_role();
1681 $context = \context_system::instance();
1682 $timestart = new DateTime();
1683 $interval = new DateInterval("P1D"); // One day.
1684 $timedurationuntil = new DateTime();
1685 $timedurationuntil->add($interval);
1686 $formdata = [
1687 'id' => 0,
1688 'userid' => $user->id,
1689 'modulename' => '',
1690 'instance' => 0,
1691 'visible' => 1,
1692 'name' => 'Test',
1693 'timestart' => [
1694 'day' => $timestart->format('j'),
1695 'month' => $timestart->format('n'),
1696 'year' => $timestart->format('Y'),
1697 'hour' => $timestart->format('G'),
1698 'minute' => 0,
1699 ],
1700 'eventtype' => 'user',
1701 'description' => [
1702 'text' => '',
1703 'format' => 1,
1704 ],
ef4e04ee 1705 'location' => 'Test',
69b160ed
RW
1706 'duration' => 1,
1707 'timedurationuntil' => [
1708 'day' => $timedurationuntil->format('j'),
1709 'month' => $timedurationuntil->format('n'),
1710 'year' => $timedurationuntil->format('Y'),
1711 'hour' => $timedurationuntil->format('G'),
1712 'minute' => 0,
1713 ]
1714 ];
1715
1716 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1717 $querystring = http_build_query($formdata, '', '&');
1718
1719 $generator->role_assign($roleid, $user->id, $context->id);
1720 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1721
1722 $user->ignoresesskey = true;
1723 $this->resetAfterTest(true);
1724 $this->setUser($user);
1725
1726 $this->expectException('moodle_exception');
1727
1728 external_api::clean_returnvalue(
1729 core_calendar_external::submit_create_update_form_returns(),
1730 core_calendar_external::submit_create_update_form($querystring)
1731 );
1732 }
1733
1734 /**
1735 * A user with the moodle/calendar:manageentries capability at the
1736 * site course context should be able to create a site event.
1737 */
1738 public function test_submit_create_update_form_create_site_event() {
1739 $generator = $this->getDataGenerator();
1740 $user = $generator->create_user();
303d649a 1741 $context = context_system::instance();
69b160ed
RW
1742 $roleid = $generator->create_role();
1743 $timestart = new DateTime();
1744 $interval = new DateInterval("P1D"); // One day.
1745 $timedurationuntil = new DateTime();
1746 $timedurationuntil->add($interval);
1747 $formdata = [
1748 'id' => 0,
1749 'userid' => $user->id,
1750 'modulename' => '',
1751 'instance' => 0,
1752 'visible' => 1,
1753 'name' => 'Test',
1754 'timestart' => [
1755 'day' => $timestart->format('j'),
1756 'month' => $timestart->format('n'),
1757 'year' => $timestart->format('Y'),
1758 'hour' => $timestart->format('G'),
1759 'minute' => 0,
1760 ],
1761 'eventtype' => 'site',
1762 'description' => [
1763 'text' => '',
1764 'format' => 1,
ea5f7707 1765 'itemid' => 0
69b160ed 1766 ],
ef4e04ee 1767 'location' => 'Test',
69b160ed
RW
1768 'duration' => 1,
1769 'timedurationuntil' => [
1770 'day' => $timedurationuntil->format('j'),
1771 'month' => $timedurationuntil->format('n'),
1772 'year' => $timedurationuntil->format('Y'),
1773 'hour' => $timedurationuntil->format('G'),
1774 'minute' => 0,
1775 ]
1776 ];
1777
1778 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1779 $querystring = http_build_query($formdata, '', '&');
1780
1781 $generator->role_assign($roleid, $user->id, $context->id);
1782
1783 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1784
1785 $user->ignoresesskey = true;
1786 $this->resetAfterTest(true);
1787 $this->setUser($user);
1788
1789 $result = external_api::clean_returnvalue(
1790 core_calendar_external::submit_create_update_form_returns(),
1791 core_calendar_external::submit_create_update_form($querystring)
1792 );
1793
1794 $event = $result['event'];
1795 $this->assertEquals($user->id, $event['userid']);
1796 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1797 $this->assertEquals($formdata['name'], $event['name']);
1798 }
1799
1800 /**
1801 * A user without the moodle/calendar:manageentries capability at the
1802 * site course context should not be able to create a site event.
1803 */
1804 public function test_submit_create_update_form_create_site_event_no_permission() {
1805 $generator = $this->getDataGenerator();
1806 $user = $generator->create_user();
1807 $context = context_course::instance(SITEID);
1808 $roleid = $generator->create_role();
1809 $timestart = new DateTime();
1810 $interval = new DateInterval("P1D"); // One day.
1811 $timedurationuntil = new DateTime();
1812 $timedurationuntil->add($interval);
1813 $formdata = [
1814 'id' => 0,
1815 'userid' => $user->id,
1816 'modulename' => '',
1817 'instance' => 0,
1818 'visible' => 1,
1819 'name' => 'Test',
1820 'timestart' => [
1821 'day' => $timestart->format('j'),
1822 'month' => $timestart->format('n'),
1823 'year' => $timestart->format('Y'),
1824 'hour' => $timestart->format('G'),
1825 'minute' => 0,
1826 ],
1827 'eventtype' => 'site',
1828 'description' => [
1829 'text' => '',
1830 'format' => 1,
1831 ],
ef4e04ee 1832 'location' => 'Test',
69b160ed
RW
1833 'duration' => 1,
1834 'timedurationuntil' => [
1835 'day' => $timedurationuntil->format('j'),
1836 'month' => $timedurationuntil->format('n'),
1837 'year' => $timedurationuntil->format('Y'),
1838 'hour' => $timedurationuntil->format('G'),
1839 'minute' => 0,
1840 ]
1841 ];
1842
1843 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1844 $querystring = http_build_query($formdata, '', '&');
1845
1846 $generator->role_assign($roleid, $user->id, $context->id);
1847
1848 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
1849
1850 $user->ignoresesskey = true;
1851 $this->resetAfterTest(true);
1852 $this->setUser($user);
1853
1854 $result = external_api::clean_returnvalue(
1855 core_calendar_external::submit_create_update_form_returns(),
1856 core_calendar_external::submit_create_update_form($querystring)
1857 );
1858
1859 $this->assertTrue($result['validationerror']);
1860 }
1861
1862 /**
1863 * A user that has the moodle/calendar:manageentries in a course that they
1864 * are enrolled in should be able to create a course event in that course.
1865 */
1866 public function test_submit_create_update_form_create_course_event() {
1867 $generator = $this->getDataGenerator();
1868 $user = $generator->create_user();
1869 $course = $generator->create_course();
1870 $context = context_course::instance($course->id);
1871 $roleid = $generator->create_role();
1872 $timestart = new DateTime();
1873 $interval = new DateInterval("P1D"); // One day.
1874 $timedurationuntil = new DateTime();
1875 $timedurationuntil->add($interval);
1876 $formdata = [
1877 'id' => 0,
1878 'userid' => $user->id,
1879 'modulename' => '',
1880 'instance' => 0,
1881 'visible' => 1,
1882 'name' => 'Test',
1883 'timestart' => [
1884 'day' => $timestart->format('j'),
1885 'month' => $timestart->format('n'),
1886 'year' => $timestart->format('Y'),
1887 'hour' => $timestart->format('G'),
1888 'minute' => 0,
1889 ],
1890 'eventtype' => 'course',
1891 'courseid' => $course->id,
1892 'description' => [
1893 'text' => '',
1894 'format' => 1,
ea5f7707 1895 'itemid' => 0,
69b160ed 1896 ],
ef4e04ee 1897 'location' => 'Test',
69b160ed
RW
1898 'duration' => 1,
1899 'timedurationuntil' => [
1900 'day' => $timedurationuntil->format('j'),
1901 'month' => $timedurationuntil->format('n'),
1902 'year' => $timedurationuntil->format('Y'),
1903 'hour' => $timedurationuntil->format('G'),
1904 'minute' => 0,
1905 ]
1906 ];
1907
1908 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1909 $querystring = http_build_query($formdata, '', '&');
1910
1911 $generator->enrol_user($user->id, $course->id, 'student');
1912 $generator->role_assign($roleid, $user->id, $context->id);
1913
1914 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
1915
1916 $user->ignoresesskey = true;
1917 $this->resetAfterTest(true);
1918 $this->setUser($user);
1919
1920 $result = external_api::clean_returnvalue(
1921 core_calendar_external::submit_create_update_form_returns(),
1922 core_calendar_external::submit_create_update_form($querystring)
1923 );
1924
1925 $event = $result['event'];
1926 $this->assertEquals($user->id, $event['userid']);
1927 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
1928 $this->assertEquals($formdata['name'], $event['name']);
1929 $this->assertEquals($formdata['courseid'], $event['course']['id']);
1930 }
1931
1932 /**
1933 * A user without the moodle/calendar:manageentries capability in a course
1934 * that they are enrolled in should not be able to create a course event in that course.
1935 */
1936 public function test_submit_create_update_form_create_course_event_no_permission() {
1937 $generator = $this->getDataGenerator();
1938 $user = $generator->create_user();
1939 $course = $generator->create_course();
1940 $context = context_course::instance($course->id);
1941 $roleid = $generator->create_role();
1942 $timestart = new DateTime();
1943 $interval = new DateInterval("P1D"); // One day.
1944 $timedurationuntil = new DateTime();
1945 $timedurationuntil->add($interval);
1946 $formdata = [
1947 'id' => 0,
1948 'userid' => $user->id,
1949 'modulename' => '',
1950 'instance' => 0,
1951 'visible' => 1,
1952 'name' => 'Test',
1953 'timestart' => [
1954 'day' => $timestart->format('j'),
1955 'month' => $timestart->format('n'),
1956 'year' => $timestart->format('Y'),
1957 'hour' => $timestart->format('G'),
1958 'minute' => 0,
1959 ],
1960 'eventtype' => 'course',
1961 'courseid' => $course->id,
1962 'description' => [
1963 'text' => '',
1964 'format' => 1,
1965 ],
ef4e04ee 1966 'location' => 'Test',
69b160ed
RW
1967 'duration' => 1,
1968 'timedurationuntil' => [
1969 'day' => $timedurationuntil->format('j'),
1970 'month' => $timedurationuntil->format('n'),
1971 'year' => $timedurationuntil->format('Y'),
1972 'hour' => $timedurationuntil->format('G'),
1973 'minute' => 0,
1974 ]
1975 ];
1976
1977 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
1978 $querystring = http_build_query($formdata, '', '&');
1979
1980 $generator->enrol_user($user->id, $course->id, 'student');
1981 $generator->role_assign($roleid, $user->id, $context->id);
1982
1983 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
1984
1985 $user->ignoresesskey = true;
1986 $this->resetAfterTest(true);
1987 $this->setUser($user);
1988
1989 $result = external_api::clean_returnvalue(
1990 core_calendar_external::submit_create_update_form_returns(),
1991 core_calendar_external::submit_create_update_form($querystring)
1992 );
1993
1994 $this->assertTrue($result['validationerror']);
1995 }
1996
1997 /**
1998 * A user should not be able to create an event for a course that they are
1999 * not enrolled in.
2000 */
2001 public function test_submit_create_update_form_create_course_event_not_enrolled() {
2002 $generator = $this->getDataGenerator();
2003 $user = $generator->create_user();
2004 $course = $generator->create_course();
2005 $course2 = $generator->create_course();
2006 $context = context_course::instance($course->id);
2007 $roleid = $generator->create_role();
2008 $timestart = new DateTime();
2009 $interval = new DateInterval("P1D"); // One day.
2010 $timedurationuntil = new DateTime();
2011 $timedurationuntil->add($interval);
2012 $formdata = [
2013 'id' => 0,
2014 'userid' => $user->id,
2015 'modulename' => '',
2016 'instance' => 0,
2017 'visible' => 1,
2018 'name' => 'Test',
2019 'timestart' => [
2020 'day' => $timestart->format('j'),
2021 'month' => $timestart->format('n'),
2022 'year' => $timestart->format('Y'),
2023 'hour' => $timestart->format('G'),
2024 'minute' => 0,
2025 ],
2026 'eventtype' => 'course',
2027 'courseid' => $course2->id, // Not enrolled.
2028 'description' => [
2029 'text' => '',
2030 'format' => 1,
2031 ],
ef4e04ee 2032 'location' => 'Test',
69b160ed
RW
2033 'duration' => 1,
2034 'timedurationuntil' => [
2035 'day' => $timedurationuntil->format('j'),
2036 'month' => $timedurationuntil->format('n'),
2037 'year' => $timedurationuntil->format('Y'),
2038 'hour' => $timedurationuntil->format('G'),
2039 'minute' => 0,
2040 ]
2041 ];
2042
2043 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2044 $querystring = http_build_query($formdata, '', '&');
2045
2046 $generator->enrol_user($user->id, $course->id, 'student');
2047 $generator->role_assign($roleid, $user->id, $context->id);
2048
2049 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2050
2051 $user->ignoresesskey = true;
2052 $this->resetAfterTest(true);
2053 $this->setUser($user);
2054
dfc609e5 2055 $result = external_api::clean_returnvalue(
69b160ed
RW
2056 core_calendar_external::submit_create_update_form_returns(),
2057 core_calendar_external::submit_create_update_form($querystring)
2058 );
dfc609e5
SL
2059
2060 $this->assertTrue($result['validationerror']);
69b160ed
RW
2061 }
2062
2063 /**
2064 * A user should be able to create an event for a group that they are a member of in
2065 * a course in which they are enrolled and have the moodle/calendar:manageentries capability.
2066 */
2067 public function test_submit_create_update_form_create_group_event_group_member_manage_course() {
2068 $generator = $this->getDataGenerator();
2069 $user = $generator->create_user();
2070 $course = $generator->create_course();
2071 $group = $generator->create_group(array('courseid' => $course->id));
2072 $context = context_course::instance($course->id);
2073 $roleid = $generator->create_role();
2074 $timestart = new DateTime();
2075 $interval = new DateInterval("P1D"); // One day.
2076 $timedurationuntil = new DateTime();
2077 $timedurationuntil->add($interval);
2078 $formdata = [
2079 'id' => 0,
2080 'userid' => $user->id,
2081 'modulename' => '',
2082 'instance' => 0,
2083 'visible' => 1,
2084 'name' => 'Test',
2085 'timestart' => [
2086 'day' => $timestart->format('j'),
2087 'month' => $timestart->format('n'),
2088 'year' => $timestart->format('Y'),
2089 'hour' => $timestart->format('G'),
2090 'minute' => 0,
2091 ],
2092 'eventtype' => 'group',
dfc609e5 2093 'groupid' => $group->id,
69b160ed
RW
2094 'groupcourseid' => $course->id,
2095 'description' => [
2096 'text' => '',
2097 'format' => 1,
ea5f7707 2098 'itemid' => 0
69b160ed 2099 ],
ef4e04ee 2100 'location' => 'Test',
69b160ed
RW
2101 'duration' => 1,
2102 'timedurationuntil' => [
2103 'day' => $timedurationuntil->format('j'),
2104 'month' => $timedurationuntil->format('n'),
2105 'year' => $timedurationuntil->format('Y'),
2106 'hour' => $timedurationuntil->format('G'),
2107 'minute' => 0,
2108 ]
2109 ];
2110
2111 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2112 $querystring = http_build_query($formdata, '', '&');
2113
2114 $generator->enrol_user($user->id, $course->id, 'student');
2115 $generator->role_assign($roleid, $user->id, $context->id);
2116 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
2117
2118 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2119
2120 $user->ignoresesskey = true;
2121 $this->resetAfterTest(true);
2122 $this->setUser($user);
2123
2124 $result = external_api::clean_returnvalue(
2125 core_calendar_external::submit_create_update_form_returns(),
2126 core_calendar_external::submit_create_update_form($querystring)
2127 );
2128
2129 $event = $result['event'];
2130 $this->assertEquals($user->id, $event['userid']);
2131 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2132 $this->assertEquals($formdata['name'], $event['name']);
2133 $this->assertEquals($group->id, $event['groupid']);
2134 }
2135
2136 /**
2137 * A user should be able to create an event for a group that they are a member of in
2138 * a course in which they are enrolled and have the moodle/calendar:managegroupentries capability.
2139 */
2140 public function test_submit_create_update_form_create_group_event_group_member_manage_group_entries() {
2141 $generator = $this->getDataGenerator();
2142 $user = $generator->create_user();
2143 $course = $generator->create_course();
2144 $group = $generator->create_group(array('courseid' => $course->id));
2145 $context = context_course::instance($course->id);
2146 $roleid = $generator->create_role();
2147 $timestart = new DateTime();
2148 $interval = new DateInterval("P1D"); // One day.
2149 $timedurationuntil = new DateTime();
2150 $timedurationuntil->add($interval);
2151 $formdata = [
2152 'id' => 0,
2153 'userid' => $user->id,
2154 'modulename' => '',
2155 'instance' => 0,
2156 'visible' => 1,
2157 'name' => 'Test',
2158 'timestart' => [
2159 'day' => $timestart->format('j'),
2160 'month' => $timestart->format('n'),
2161 'year' => $timestart->format('Y'),
2162 'hour' => $timestart->format('G'),
2163 'minute' => 0,
2164 ],
2165 'eventtype' => 'group',
dfc609e5 2166 'groupid' => $group->id,
69b160ed
RW
2167 'groupcourseid' => $course->id,
2168 'description' => [
2169 'text' => '',
2170 'format' => 1,
ea5f7707 2171 'itemid' => 0
69b160ed 2172 ],
ef4e04ee 2173 'location' => 'Test',
69b160ed
RW
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 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
2190
2191 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);
2192 assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
2193
2194 $user->ignoresesskey = true;
2195 $this->resetAfterTest(true);
2196 $this->setUser($user);
2197
2198 $result = external_api::clean_returnvalue(
2199 core_calendar_external::submit_create_update_form_returns(),
2200 core_calendar_external::submit_create_update_form($querystring)
2201 );
2202
2203 $event = $result['event'];
2204 $this->assertEquals($user->id, $event['userid']);
2205 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2206 $this->assertEquals($formdata['name'], $event['name']);
2207 $this->assertEquals($group->id, $event['groupid']);
2208 }
2209
2210 /**
2211 * A user should be able to create an event for any group in a course in which
2212 * they are enrolled and have the moodle/site:accessallgroups capability.
2213 */
2214 public function test_submit_create_update_form_create_group_event_access_all_groups() {
2215 $generator = $this->getDataGenerator();
2216 $user = $generator->create_user();
2217 $course = $generator->create_course();
2218 $group = $generator->create_group(array('courseid' => $course->id));
2219 $context = context_course::instance($course->id);
2220 $roleid = $generator->create_role();
2221 $timestart = new DateTime();
2222 $interval = new DateInterval("P1D"); // One day.
2223 $timedurationuntil = new DateTime();
2224 $timedurationuntil->add($interval);
2225 $formdata = [
2226 'id' => 0,
2227 'userid' => $user->id,
2228 'modulename' => '',
2229 'instance' => 0,
2230 'visible' => 1,
2231 'name' => 'Test',
2232 'timestart' => [
2233 'day' => $timestart->format('j'),
2234 'month' => $timestart->format('n'),
2235 'year' => $timestart->format('Y'),
2236 'hour' => $timestart->format('G'),
2237 'minute' => 0,
2238 ],
2239 'eventtype' => 'group',
dfc609e5 2240 'groupid' => $group->id,
69b160ed
RW
2241 'groupcourseid' => $course->id,
2242 'description' => [
2243 'text' => '',
2244 'format' => 1,
ea5f7707 2245 'itemid' => 0
69b160ed 2246 ],
ef4e04ee 2247 'location' => 'Test',
69b160ed
RW
2248 'duration' => 1,
2249 'timedurationuntil' => [
2250 'day' => $timedurationuntil->format('j'),
2251 'month' => $timedurationuntil->format('n'),
2252 'year' => $timedurationuntil->format('Y'),
2253 'hour' => $timedurationuntil->format('G'),
2254 'minute' => 0,
2255 ]
2256 ];
2257
2258 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2259 $querystring = http_build_query($formdata, '', '&');
2260
2261 $generator->enrol_user($user->id, $course->id, 'student');
2262 $generator->role_assign($roleid, $user->id, $context->id);
2263
2264 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2265 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
2266
2267 $user->ignoresesskey = true;
2268 $this->resetAfterTest(true);
2269 $this->setUser($user);
2270
2271 $result = external_api::clean_returnvalue(
2272 core_calendar_external::submit_create_update_form_returns(),
2273 core_calendar_external::submit_create_update_form($querystring)
2274 );
2275
2276 $event = $result['event'];
2277 $this->assertEquals($user->id, $event['userid']);
2278 $this->assertEquals($formdata['eventtype'], $event['eventtype']);
2279 $this->assertEquals($formdata['name'], $event['name']);
2280 $this->assertEquals($group->id, $event['groupid']);
2281 }
2282
2283 /**
2284 * A user should not be able to create an event for any group that they are not a
2285 * member of in a course in which they are enrolled but don't have the
2286 * moodle/site:accessallgroups capability.
2287 */
2288 public function test_submit_create_update_form_create_group_event_non_member_no_permission() {
2289 $generator = $this->getDataGenerator();
2290 $user = $generator->create_user();
2291 $course = $generator->create_course();
2292 $group = $generator->create_group(array('courseid' => $course->id));
2293 $context = context_course::instance($course->id);
2294 $roleid = $generator->create_role();
2295 $timestart = new DateTime();
2296 $interval = new DateInterval("P1D"); // One day.
2297 $timedurationuntil = new DateTime();
2298 $timedurationuntil->add($interval);
2299 $formdata = [
2300 'id' => 0,
2301 'userid' => $user->id,
2302 'modulename' => '',
2303 'instance' => 0,
2304 'visible' => 1,
2305 'name' => 'Test',
2306 'timestart' => [
2307 'day' => $timestart->format('j'),
2308 'month' => $timestart->format('n'),
2309 'year' => $timestart->format('Y'),
2310 'hour' => $timestart->format('G'),
2311 'minute' => 0,
2312 ],
2313 'eventtype' => 'group',
dfc609e5 2314 'groupid' => $group->id,
69b160ed
RW
2315 'groupcourseid' => $course->id,
2316 'description' => [
2317 'text' => '',
2318 'format' => 1,
2319 ],
ef4e04ee 2320 'location' => 'Test',
69b160ed
RW
2321 'duration' => 1,
2322 'timedurationuntil' => [
2323 'day' => $timedurationuntil->format('j'),
2324 'month' => $timedurationuntil->format('n'),
2325 'year' => $timedurationuntil->format('Y'),
2326 'hour' => $timedurationuntil->format('G'),
2327 'minute' => 0,
2328 ]
2329 ];
2330
2331 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);
2332 $querystring = http_build_query($formdata, '', '&');
2333
2334 $generator->enrol_user($user->id, $course->id, 'student');
2335 $generator->role_assign($roleid, $user->id, $context->id);
2336
2337 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
2338 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
2339
2340 $user->ignoresesskey = true;
2341 $this->resetAfterTest(true);
2342 $this->setUser($user);
2343
2344 $result = external_api::clean_returnvalue(
2345 core_calendar_external::submit_create_update_form_returns(),
2346 core_calendar_external::submit_create_update_form($querystring)
2347 );
2348
2349 $this->assertTrue($result['validationerror']);
2350 }
9e0884d4
DW
2351
2352 /**
2353 * A user should not be able load the calendar monthly view for a course they cannot access.
2354 */
2355 public function test_get_calendar_monthly_view_no_course_permission() {
2356 global $USER;
2357 $this->resetAfterTest(true);
2358 $this->setAdminUser();
2359
2360 $generator = $this->getDataGenerator();
2361 $user1 = $generator->create_user();
2362 $user2 = $generator->create_user();
2363 $course = $generator->create_course();
2364 $generator->enrol_user($user1->id, $course->id, 'student');
2365 $name = 'Course Event (course' . $course->id . ')';
2366 $record = new stdClass();
2367 $record->courseid = $course->id;
2368 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2369
2370 $timestart = new DateTime();
2371 // Admin can load the course.
2372 $data = external_api::clean_returnvalue(
2373 core_calendar_external::get_calendar_monthly_view_returns(),
0cf28875 2374 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
641e7d41 2375 $course->id, null, false, true)
9e0884d4
DW
2376 );
2377 $this->assertEquals($data['courseid'], $course->id);
2378 // User enrolled in the course can load the course calendar.
2379 $this->setUser($user1);
2380 $data = external_api::clean_returnvalue(
2381 core_calendar_external::get_calendar_monthly_view_returns(),
0cf28875 2382 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
641e7d41 2383 $course->id, null, false, true)
9e0884d4
DW
2384 );
2385 $this->assertEquals($data['courseid'], $course->id);
2386 // User not enrolled in the course cannot load the course calendar.
2387 $this->setUser($user2);
80011997 2388 $this->expectException('require_login_exception');
9e0884d4
DW
2389 $data = external_api::clean_returnvalue(
2390 core_calendar_external::get_calendar_monthly_view_returns(),
0cf28875 2391 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),
641e7d41 2392 $course->id, null, false, false)
9e0884d4
DW
2393 );
2394 }
2395
2396 /**
2397 * A user should not be able load the calendar day view for a course they cannot access.
2398 */
2399 public function test_get_calendar_day_view_no_course_permission() {
2400 global $USER;
2401 $this->resetAfterTest(true);
2402 $this->setAdminUser();
2403
2404 $generator = $this->getDataGenerator();
2405 $user1 = $generator->create_user();
2406 $user2 = $generator->create_user();
2407 $course = $generator->create_course();
2408 $generator->enrol_user($user1->id, $course->id, 'student');
2409 $name = 'Course Event (course' . $course->id . ')';
2410 $record = new stdClass();
2411 $record->courseid = $course->id;
2412 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2413
2414 $timestart = new DateTime();
2415 // Admin can load the course.
2416 $data = external_api::clean_returnvalue(
2417 core_calendar_external::get_calendar_day_view_returns(),
0cf28875 2418 core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),
9e0884d4
DW
2419 $timestart->format('j'), $course->id, null)
2420 );
2421 $this->assertEquals($data['courseid'], $course->id);
2422 // User enrolled in the course can load the course calendar.
2423 $this->setUser($user1);
2424 $data = external_api::clean_returnvalue(
2425 core_calendar_external::get_calendar_day_view_returns(),
0cf28875 2426 core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),
9e0884d4
DW
2427 $timestart->format('j'), $course->id, null)
2428 );
2429 $this->assertEquals($data['courseid'], $course->id);
2430 // User not enrolled in the course cannot load the course calendar.
2431 $this->setUser($user2);
80011997 2432 $this->expectException('require_login_exception');
9e0884d4
DW
2433 $data = external_api::clean_returnvalue(
2434 core_calendar_external::get_calendar_day_view_returns(),
0cf28875 2435 core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),
9e0884d4
DW
2436 $timestart->format('j'), $course->id, null)
2437 );
2438 }
2439
2440 /**
2441 * A user should not be able load the calendar upcoming view for a course they cannot access.
2442 */
2443 public function test_get_calendar_upcoming_view_no_course_permission() {
2444 global $USER;
2445 $this->resetAfterTest(true);
2446 $this->setAdminUser();
2447
2448 $generator = $this->getDataGenerator();
2449 $user1 = $generator->create_user();
2450 $user2 = $generator->create_user();
2451 $course = $generator->create_course();
2452 $generator->enrol_user($user1->id, $course->id, 'student');
2453 $name = 'Course Event (course' . $course->id . ')';
2454 $record = new stdClass();
2455 $record->courseid = $course->id;
2456 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2457
2458 // Admin can load the course.
2459 $data = external_api::clean_returnvalue(
2460 core_calendar_external::get_calendar_upcoming_view_returns(),
2461 core_calendar_external::get_calendar_upcoming_view($course->id, null)
2462 );
2463 $this->assertEquals($data['courseid'], $course->id);
2464 // User enrolled in the course can load the course calendar.
2465 $this->setUser($user1);
2466 $data = external_api::clean_returnvalue(
2467 core_calendar_external::get_calendar_upcoming_view_returns(),
2468 core_calendar_external::get_calendar_upcoming_view($course->id, null)
2469 );
2470 $this->assertEquals($data['courseid'], $course->id);
2471 // User not enrolled in the course cannot load the course calendar.
2472 $this->setUser($user2);
80011997 2473 $this->expectException('require_login_exception');
9e0884d4
DW
2474 $data = external_api::clean_returnvalue(
2475 core_calendar_external::get_calendar_upcoming_view_returns(),
2476 core_calendar_external::get_calendar_upcoming_view($course->id, null)
2477 );
2478 }
2479
2480 /**
2481 * A user should not be able load the calendar event for a course they cannot access.
2482 */
2483 public function test_get_calendar_event_by_id_no_course_permission() {
2484 global $USER;
2485 $this->resetAfterTest(true);
2486 $this->setAdminUser();
2487
2488 $generator = $this->getDataGenerator();
2489 $user1 = $generator->create_user();
2490 $user2 = $generator->create_user();
2491 $course = $generator->create_course();
2492 $generator->enrol_user($user1->id, $course->id, 'student');
2493 $name = 'Course Event (course' . $course->id . ')';
2494 $record = new stdClass();
2495 $record->courseid = $course->id;
2496 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);
2497
2498 // Admin can load the course event.
2499 $data = external_api::clean_returnvalue(
2500 core_calendar_external::get_calendar_event_by_id_returns(),
2501 core_calendar_external::get_calendar_event_by_id($courseevent->id)
2502 );
2503 $this->assertEquals($data['event']['id'], $courseevent->id);
2504 // User enrolled in the course can load the course event.
2505 $this->setUser($user1);
2506 $data = external_api::clean_returnvalue(
2507 core_calendar_external::get_calendar_event_by_id_returns(),
2508 core_calendar_external::get_calendar_event_by_id($courseevent->id)
2509 );
2510 $this->assertEquals($data['event']['id'], $courseevent->id);
2511 // User not enrolled in the course cannot load the course event.
2512 $this->setUser($user2);
80011997 2513 $this->expectException('required_capability_exception');
9e0884d4
DW
2514 $data = external_api::clean_returnvalue(
2515 core_calendar_external::get_calendar_event_by_id_returns(),
2516 core_calendar_external::get_calendar_event_by_id($courseevent->id)
2517 );
2518 }
2519
2520 /**
2521 * A user should not be able load the calendar events for a category they cannot see.
2522 */
2523 public function test_get_calendar_events_hidden_category() {
2524 global $USER;
2525 $this->resetAfterTest(true);
2526 $this->setAdminUser();
2527
2528 $generator = $this->getDataGenerator();
2529 $user1 = $generator->create_user();
2530 $category = $generator->create_category(['visible' => 0]);
2531 $name = 'Category Event (category: ' . $category->id . ')';
2532 $record = new stdClass();
2533 $record->categoryid = $category->id;
2534 $categoryevent = $this->create_calendar_event($name, $USER->id, 'category', 0, time(), $record);
2535
2536 $events = [
2537 'eventids' => [$categoryevent->id]
2538 ];
2539 $options = [];
2540 // Admin can load the category event.
2541 $data = external_api::clean_returnvalue(
2542 core_calendar_external::get_calendar_events_returns(),
2543 core_calendar_external::get_calendar_events($events, $options)
2544 );
2545 $this->assertEquals($data['events'][0]['id'], $categoryevent->id);
2546 // User with no special permission to see hidden categories will not see the event.
2547 $this->setUser($user1);
2548 $data = external_api::clean_returnvalue(
2549 core_calendar_external::get_calendar_events_returns(),
2550 core_calendar_external::get_calendar_events($events, $options)
2551 );
2552 $this->assertCount(0, $data['events']);
2553 $this->assertEquals('nopermissions', $data['warnings'][0]['warningcode']);
2554 }
a46980fa
JL
2555
2556 /**
2557 * Test get_calendar_access_information for admins.
2558 */
2559 public function test_get_calendar_access_information_for_admins() {
2560 global $CFG;
2561 $this->resetAfterTest(true);
2562 $this->setAdminUser();
2563
2564 $CFG->calendar_adminseesall = 1;
2565
2566 $data = external_api::clean_returnvalue(
2567 core_calendar_external::get_calendar_access_information_returns(),
2568 core_calendar_external::get_calendar_access_information()
2569 );
2570 $this->assertTrue($data['canmanageownentries']);
2571 $this->assertTrue($data['canmanagegroupentries']);
2572 $this->assertTrue($data['canmanageentries']);
2573 }
2574
2575 /**
2576 * Test get_calendar_access_information for authenticated users.
2577 */
2578 public function test_get_calendar_access_information_for_authenticated_users() {
2579 $this->resetAfterTest(true);
2580 $this->setUser($this->getDataGenerator()->create_user());
2581
2582 $data = external_api::clean_returnvalue(
2583 core_calendar_external::get_calendar_access_information_returns(),
2584 core_calendar_external::get_calendar_access_information()
2585 );
2586 $this->assertTrue($data['canmanageownentries']);
2587 $this->assertFalse($data['canmanagegroupentries']);
2588 $this->assertFalse($data['canmanageentries']);
2589 }
2590
2591 /**
2592 * Test get_calendar_access_information for student users.
2593 */
2594 public function test_get_calendar_access_information_for_student_users() {
2595 global $DB;
2596 $this->resetAfterTest(true);
2597
2598 $user = $this->getDataGenerator()->create_user();
2599 $course = $this->getDataGenerator()->create_course();
2600 $role = $DB->get_record('role', array('shortname' => 'student'));
2601 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
2602
2603 $this->setUser($user);
2604
2605 $data = external_api::clean_returnvalue(
2606 core_calendar_external::get_calendar_access_information_returns(),
2607 core_calendar_external::get_calendar_access_information($course->id)
2608 );
2609 $this->assertTrue($data['canmanageownentries']);
2610 $this->assertFalse($data['canmanagegroupentries']);
2611 $this->assertFalse($data['canmanageentries']);
2612 }
2613
2614 /**
2615 * Test get_calendar_access_information for teacher users.
2616 */
2617 public function test_get_calendar_access_information_for_teacher_users() {
2618 global $DB;
2619 $this->resetAfterTest(true);
2620
2621 $user = $this->getDataGenerator()->create_user();
2622 $course = $this->getDataGenerator()->create_course(['groupmode' => 1]);
2623 $role = $DB->get_record('role', array('shortname' => 'editingteacher'));
2624 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
2625 $this->getDataGenerator()->create_group(['courseid' => $course->id]);
2626
2627 $this->setUser($user);
2628
2629 $data = external_api::clean_returnvalue(
2630 core_calendar_external::get_calendar_access_information_returns(),
2631 core_calendar_external::get_calendar_access_information($course->id)
2632 );
2633 $this->assertTrue($data['canmanageownentries']);
2634 $this->assertTrue($data['canmanagegroupentries']);
2635 $this->assertTrue($data['canmanageentries']);
2636 }
7c30224a 2637}