See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 namespace core_calendar; 18 19 use core_calendar_external; 20 use externallib_advanced_testcase; 21 22 defined('MOODLE_INTERNAL') || die(); 23 24 global $CFG; 25 26 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 27 28 /** 29 * External course functions unit tests 30 * 31 * @package core_calendar 32 * @category external 33 * @copyright 2012 Ankit Agarwal 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 * @since Moodle 2.5 36 */ 37 class externallib_test extends externallib_advanced_testcase { 38 39 /** 40 * Tests set up 41 */ 42 protected function setUp(): void { 43 global $CFG; 44 require_once($CFG->dirroot . '/calendar/externallib.php'); 45 } 46 47 /** Create calendar events or update them 48 * Set $prop->id, if you want to do an update instead of creating an new event 49 * 50 * @param string $name Event title 51 * @param int $userid User id 52 * @param string $type Event type 53 * @param int $repeats Number of repeated events to create 54 * @param int $timestart Time stamp of the event start 55 * @param mixed $prop List of event properties as array or object 56 * @return mixed Event object or false; 57 * @since Moodle 2.5 58 */ 59 60 public static function create_calendar_event($name, $userid = 0, $type = 'user', $repeats = 0, $timestart = null, $prop = null) { 61 global $CFG, $DB, $SITE; 62 63 require_once("$CFG->dirroot/calendar/lib.php"); 64 if (!empty($prop)) { 65 if (is_array($prop)) { 66 $prop = (object)$prop; 67 } 68 } else { 69 $prop = new \stdClass(); 70 } 71 $prop->name = $name; 72 if (empty($prop->eventtype)) { 73 $prop->eventtype = $type; 74 } 75 if (empty($prop->repeats)) { 76 $prop->repeats = $repeats; 77 } 78 if (empty($prop->timestart)) { 79 $prop->timestart = time(); 80 } 81 if (empty($prop->timeduration)) { 82 $prop->timeduration = 0; 83 } 84 if (empty($prop->timesort)) { 85 $prop->timesort = 0; 86 } 87 if (empty($prop->type)) { 88 $prop->type = CALENDAR_EVENT_TYPE_STANDARD; 89 } 90 if (empty($prop->repeats)) { 91 $prop->repeat = 0; 92 } else { 93 $prop->repeat = 1; 94 } 95 if (empty($prop->userid)) { 96 if (!empty($userid)) { 97 $prop->userid = $userid; 98 } else { 99 $prop->userid = 0; 100 } 101 } 102 if (!isset($prop->courseid)) { 103 // Set a default value of the event's course ID field. 104 if ($type === 'user') { 105 // If it's a user event, course ID should be zero. 106 $prop->courseid = 0; 107 } else { 108 // Otherwise, default to the site ID. 109 $prop->courseid = $SITE->id; 110 } 111 } 112 113 // Determine event priority. 114 if ($prop->courseid == 0 && isset($prop->groupid) && $prop->groupid == 0 && !empty($prop->userid)) { 115 // User override event. 116 $prop->priority = CALENDAR_EVENT_USER_OVERRIDE_PRIORITY; 117 } else if ($prop->courseid != $SITE->id && !empty($prop->groupid)) { 118 // Group override event. 119 $priorityparams = ['courseid' => $prop->courseid, 'groupid' => $prop->groupid]; 120 // Group override event with the highest priority. 121 $groupevents = $DB->get_records('event', $priorityparams, 'priority DESC', 'id, priority', 0, 1); 122 $priority = 1; 123 if (!empty($groupevents)) { 124 $event = reset($groupevents); 125 if (!empty($event->priority)) { 126 $priority = $event->priority + 1; 127 } 128 } 129 $prop->priority = $priority; 130 } 131 132 $event = new \calendar_event($prop); 133 return $event->create($prop); 134 } 135 136 public function test_create_calendar_events () { 137 global $DB, $USER; 138 139 $this->setAdminUser(); 140 $this->resetAfterTest(); 141 $prevcount = count($DB->get_records("event")); 142 143 // Create a few events and do asserts. 144 $this->create_calendar_event('test', $USER->id); 145 $where = $DB->sql_compare_text('name') ." = ?"; 146 $count = count($DB->get_records_select("event", $where, array('test'))); 147 $this->assertEquals(1, $count); 148 $aftercount = count($DB->get_records("event")); 149 $this->assertEquals($prevcount + 1, $aftercount); 150 151 $this->create_calendar_event('user', $USER->id, 'user', 3); 152 $where = $DB->sql_compare_text('name') ." = ?"; 153 $count = count($DB->get_records_select("event", $where, array('user'))); 154 155 $this->assertEquals(3, $count); 156 $aftercount = count($DB->get_records("event")); 157 $this->assertEquals($prevcount + 4, $aftercount); 158 159 } 160 161 /** 162 * Test delete_calendar_events 163 */ 164 public function test_delete_calendar_events() { 165 global $DB, $USER; 166 167 $this->resetAfterTest(true); 168 $this->setAdminUser(); 169 170 // Create a few stuff to test with. 171 $user = $this->getDataGenerator()->create_user(); 172 $course = $this->getDataGenerator()->create_course(); 173 $record = new \stdClass(); 174 $record->courseid = $course->id; 175 $group = $this->getDataGenerator()->create_group($record); 176 177 $notdeletedcount = $DB->count_records('event'); 178 179 // Let's create a few events. 180 $siteevent = $this->create_calendar_event('site', $USER->id, 'site'); 181 $record = new \stdClass(); 182 $record->courseid = $course->id; 183 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record); 184 $userevent = $this->create_calendar_event('user', $USER->id); 185 $record = new \stdClass(); 186 $record->courseid = $course->id; 187 $record->groupid = $group->id; 188 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record); 189 190 // Now lets try to delete stuff with proper rights. 191 $events = array( 192 array('eventid' => $siteevent->id, 'repeat' => 0), 193 array('eventid' => $courseevent->id, 'repeat' => 1), 194 array('eventid' => $userevent->id, 'repeat' => 0), 195 array('eventid' => $groupevent->id, 'repeat' => 0) 196 ); 197 core_calendar_external::delete_calendar_events($events); 198 199 // Check to see if things were deleted properly. 200 $deletedcount = $DB->count_records('event'); 201 $this->assertEquals($notdeletedcount, $deletedcount); 202 203 // Let's create a few events. 204 $siteevent = $this->create_calendar_event('site', $USER->id, 'site'); 205 $record = new \stdClass(); 206 $record->courseid = $course->id; 207 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 3, time(), $record); 208 $userevent = $this->create_calendar_event('user', $user->id); 209 $record = new \stdClass(); 210 $record->courseid = $course->id; 211 $record->groupid = $group->id; 212 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record); 213 214 $this->setuser($user); 215 $sitecontext = \context_system::instance(); 216 $coursecontext = \context_course::instance($course->id); 217 $usercontext = \context_user::instance($user->id); 218 $role = $DB->get_record('role', array('shortname' => 'student')); 219 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 220 221 // Remove all caps. 222 $this->unassignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id); 223 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id); 224 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id); 225 $this->unassignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id); 226 227 // Assign proper caps and attempt delete. 228 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id); 229 $events = array( 230 array('eventid' => $siteevent->id, 'repeat' => 0), 231 ); 232 core_calendar_external::delete_calendar_events($events); 233 $deletedcount = $DB->count_records('event'); 234 $count = $notdeletedcount+5; 235 $this->assertEquals($count, $deletedcount); 236 237 $this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id); 238 $events = array( 239 array('eventid' => $courseevent->id, 'repeat' => 0), 240 ); 241 core_calendar_external::delete_calendar_events($events); 242 $deletedcount = $DB->count_records('event'); 243 $count = $notdeletedcount+4; 244 $this->assertEquals($count, $deletedcount); 245 246 $this->assignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id); 247 $events = array( 248 array('eventid' => $userevent->id, 'repeat' => 0), 249 ); 250 core_calendar_external::delete_calendar_events($events); 251 $deletedcount = $DB->count_records('event'); 252 $count = $notdeletedcount+3; 253 $this->assertEquals($count, $deletedcount); 254 255 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id); 256 $events = array( 257 array('eventid' => $groupevent->id, 'repeat' => 0), 258 ); 259 core_calendar_external::delete_calendar_events($events); 260 $deletedcount = $DB->count_records('event'); 261 $count = $notdeletedcount+2; 262 $this->assertEquals($count, $deletedcount); 263 264 $notdeletedcount = $deletedcount; 265 266 // Let us try deleting without caps. 267 268 $siteevent = $this->create_calendar_event('site', $USER->id, 'site'); 269 $record = new \stdClass(); 270 $record->courseid = $course->id; 271 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 3, time(), $record); 272 $userevent = $this->create_calendar_event('user', $USER->id); 273 $record = new \stdClass(); 274 $record->courseid = $course->id; 275 $record->groupid = $group->id; 276 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record); 277 278 $this->setGuestUser(); 279 280 $events = array( 281 array('eventid' => $siteevent->id, 'repeat' => 0), 282 array('eventid' => $courseevent->id, 'repeat' => 0), 283 array('eventid' => $userevent->id, 'repeat' => 0), 284 array('eventid' => $groupevent->id, 'repeat' => 0) 285 ); 286 $this->expectException(\moodle_exception::class); 287 core_calendar_external::delete_calendar_events($events); 288 } 289 290 /** 291 * Test get_calendar_events 292 */ 293 public function test_get_calendar_events() { 294 global $DB, $USER; 295 296 $this->resetAfterTest(true); 297 set_config('calendar_adminseesall', 1); 298 $this->setAdminUser(); 299 300 // Create a few stuff to test with. 301 $user = $this->getDataGenerator()->create_user(); 302 $user2 = $this->getDataGenerator()->create_user(); 303 $course = $this->getDataGenerator()->create_course(); 304 305 $category = $this->getDataGenerator()->create_category(); 306 307 $category2 = $this->getDataGenerator()->create_category(); 308 $category2b = $this->getDataGenerator()->create_category(['parent' => $category2->id]); 309 $course3 = $this->getDataGenerator()->create_course(['category' => $category2b->id]); 310 311 $role = $DB->get_record('role', array('shortname' => 'student')); 312 $this->getDataGenerator()->enrol_user($user2->id, $course3->id, $role->id); 313 314 $record = new \stdClass(); 315 $record->courseid = $course->id; 316 $group = $this->getDataGenerator()->create_group($record); 317 318 $beforecount = $DB->count_records('event'); 319 320 // Let's create a few events. 321 $siteevent = $this->create_calendar_event('site', $USER->id, 'site'); 322 323 // This event will have description with an inline fake image. 324 $draftidfile = file_get_unused_draft_itemid(); 325 $usercontext = \context_course::instance($course->id); 326 $filerecord = array( 327 'contextid' => $usercontext->id, 328 'component' => 'user', 329 'filearea' => 'draft', 330 'itemid' => $draftidfile, 331 'filepath' => '/', 332 'filename' => 'fakeimage.png', 333 ); 334 $fs = get_file_storage(); 335 $fs->create_file_from_string($filerecord, 'img contents'); 336 337 $record = new \stdClass(); 338 $record->courseid = $course->id; 339 $record->groupid = 0; 340 $record->description = array( 341 'format' => FORMAT_HTML, 342 'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">', 343 'itemid' => $draftidfile 344 ); 345 $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record); 346 347 $record = new \stdClass(); 348 $record->courseid = 0; 349 $record->groupid = 0; 350 $userevent = $this->create_calendar_event('user', $USER->id, 'user', 0, time(), $record); 351 352 $record = new \stdClass(); 353 $record->courseid = $course->id; 354 $record->groupid = $group->id; 355 $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record); 356 357 $paramevents = array ('eventids' => array($siteevent->id), 'courseids' => array($course->id), 358 'groupids' => array($group->id), 'categoryids' => array($category->id)); 359 360 $options = array ('siteevents' => true, 'userevents' => true); 361 $events = core_calendar_external::get_calendar_events($paramevents, $options); 362 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 363 364 // Check to see if we got all events. 365 $this->assertEquals(5, count($events['events'])); 366 $this->assertEquals(0, count($events['warnings'])); 367 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7*WEEKSECS); 368 $events = core_calendar_external::get_calendar_events($paramevents, $options); 369 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 370 $this->assertEquals(5, count($events['events'])); 371 $this->assertEquals(0, count($events['warnings'])); 372 373 // Expect the same URL in the description of two different events (because they are repeated). 374 $coursecontext = \context_course::instance($course->id); 375 $expectedurl = "webservice/pluginfile.php/$coursecontext->id/calendar/event_description/$courseevent->id/fakeimage.png"; 376 $withdescription = 0; 377 foreach ($events['events'] as $event) { 378 if (!empty($event['description'])) { 379 $withdescription++; 380 $this->assertStringContainsString($expectedurl, $event['description']); 381 } 382 } 383 $this->assertEquals(2, $withdescription); 384 385 // Let's play around with caps. 386 387 // Create user event for the user $user. 388 $record = new \stdClass(); 389 $record->courseid = 0; 390 $record->groupid = 0; 391 $this->create_calendar_event('user', $user->id, 'user', 0, time(), $record); 392 393 $this->setUser($user); 394 $events = core_calendar_external::get_calendar_events($paramevents, $options); 395 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 396 $this->assertEquals(2, count($events['events'])); // site, user. 397 $this->assertEquals(2, count($events['warnings'])); // course, group. 398 399 $role = $DB->get_record('role', array('shortname' => 'student')); 400 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 401 $events = core_calendar_external::get_calendar_events($paramevents, $options); 402 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 403 $this->assertEquals(4, count($events['events'])); // site, user, both course events. 404 $this->assertEquals(1, count($events['warnings'])); // group. 405 406 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS); 407 $events = core_calendar_external::get_calendar_events($paramevents, $options); 408 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 409 $this->assertEquals(3, count($events['events'])); // site, user, one course event. 410 $this->assertEquals(1, count($events['warnings'])); // group. 411 412 groups_add_member($group, $user); 413 $events = core_calendar_external::get_calendar_events($paramevents, $options); 414 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 415 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event. 416 $this->assertEquals(0, count($events['warnings'])); 417 418 $paramevents = array ('courseids' => array($course->id), 'groupids' => array($group->id)); 419 $events = core_calendar_external::get_calendar_events($paramevents, $options); 420 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 421 $this->assertEquals(4, count($events['events'])); // site, user, group, one course event. 422 $this->assertEquals(0, count($events['warnings'])); 423 424 $paramevents = array ('groupids' => array($group->id, 23)); 425 $events = core_calendar_external::get_calendar_events($paramevents, $options); 426 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 427 $this->assertEquals(3, count($events['events'])); // site, user, group. 428 $this->assertEquals(1, count($events['warnings'])); 429 430 $paramevents = array ('courseids' => array(23)); 431 $events = core_calendar_external::get_calendar_events($paramevents, $options); 432 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 433 $this->assertEquals(2, count($events['events'])); // site, user. 434 $this->assertEquals(1, count($events['warnings'])); 435 436 $paramevents = array (); 437 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS); 438 $events = core_calendar_external::get_calendar_events($paramevents, $options); 439 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 440 $this->assertEquals(0, count($events['events'])); // nothing returned. 441 $this->assertEquals(0, count($events['warnings'])); 442 443 $paramevents = array ('eventids' => array($siteevent->id, $groupevent->id)); 444 $options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS); 445 $events = core_calendar_external::get_calendar_events($paramevents, $options); 446 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 447 $this->assertEquals(2, count($events['events'])); // site, group. 448 $this->assertEquals(0, count($events['warnings'])); 449 450 $paramevents = array ('eventids' => array($siteevent->id)); 451 $events = core_calendar_external::get_calendar_events($paramevents, $options); 452 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 453 $this->assertEquals(1, count($events['events'])); // site. 454 $this->assertEquals(0, count($events['warnings'])); 455 456 // Try getting a course event by its id. 457 $paramevents = array ('eventids' => array($courseevent->id)); 458 $events = core_calendar_external::get_calendar_events($paramevents, $options); 459 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 460 $this->assertEquals(1, count($events['events'])); 461 $this->assertEquals(0, count($events['warnings'])); 462 463 // Now, create an activity event. 464 $this->setAdminUser(); 465 $nexttime = time() + DAYSECS; 466 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'duedate' => $nexttime)); 467 468 $this->setUser($user); 469 $paramevents = array ('courseids' => array($course->id)); 470 $options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS); 471 $events = core_calendar_external::get_calendar_events($paramevents, $options); 472 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 473 474 $this->assertCount(5, $events['events']); 475 476 // Hide the assignment. 477 set_coursemodule_visible($assign->cmid, 0); 478 // Empty all the caches that may be affected by this change. 479 accesslib_clear_all_caches_for_unit_testing(); 480 \course_modinfo::clear_instance_cache(); 481 482 $events = core_calendar_external::get_calendar_events($paramevents, $options); 483 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 484 // Expect one less. 485 $this->assertCount(4, $events['events']); 486 487 // Create some category events. 488 $this->setAdminUser(); 489 $record = new \stdClass(); 490 $record->courseid = 0; 491 $record->categoryid = $category->id; 492 $record->timestart = time() - DAYSECS; 493 $catevent1 = $this->create_calendar_event('category a', $USER->id, 'category', 0, time(), $record); 494 495 $record = new \stdClass(); 496 $record->courseid = 0; 497 $record->categoryid = $category2->id; 498 $record->timestart = time() + DAYSECS; 499 $catevent2 = $this->create_calendar_event('category b', $USER->id, 'category', 0, time(), $record); 500 501 // Now as student, make sure we get the events of the courses I am enrolled. 502 $this->setUser($user2); 503 $paramevents = array('categoryids' => array($category2b->id)); 504 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false); 505 $events = core_calendar_external::get_calendar_events($paramevents, $options); 506 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 507 508 // Should be just one, since there's just one category event of the course I am enrolled (course3 - cat2b). 509 $this->assertEquals(1, count($events['events'])); 510 $this->assertEquals($catevent2->id, $events['events'][0]['id']); 511 $this->assertEquals($category2->id, $events['events'][0]['categoryid']); 512 $this->assertEquals(0, count($events['warnings'])); 513 514 // Now get category events but by course (there aren't course events in the course). 515 $paramevents = array('courseids' => array($course3->id)); 516 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false); 517 $events = core_calendar_external::get_calendar_events($paramevents, $options); 518 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 519 $this->assertEquals(1, count($events['events'])); 520 $this->assertEquals($catevent2->id, $events['events'][0]['id']); 521 $this->assertEquals(0, count($events['warnings'])); 522 523 // Empty events in one where I'm not enrolled and one parent category 524 // (parent of a category where this is a course where the user is enrolled). 525 $paramevents = array('categoryids' => array($category2->id, $category->id)); 526 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false); 527 $events = core_calendar_external::get_calendar_events($paramevents, $options); 528 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 529 $this->assertEquals(1, count($events['events'])); 530 $this->assertEquals($catevent2->id, $events['events'][0]['id']); 531 $this->assertEquals(0, count($events['warnings'])); 532 533 // Admin can see all category events. 534 $this->setAdminUser(); 535 $paramevents = array('categoryids' => array($category->id, $category2->id, $category2b->id)); 536 $options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false); 537 $events = core_calendar_external::get_calendar_events($paramevents, $options); 538 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 539 $this->assertEquals(2, count($events['events'])); 540 $this->assertEquals(0, count($events['warnings'])); 541 $this->assertEquals($catevent1->id, $events['events'][0]['id']); 542 $this->assertEquals($category->id, $events['events'][0]['categoryid']); 543 $this->assertEquals($catevent2->id, $events['events'][1]['id']); 544 $this->assertEquals($category2->id, $events['events'][1]['categoryid']); 545 } 546 547 /** 548 * Test get_calendar_events with mathjax in the name. 549 */ 550 public function test_get_calendar_events_with_mathjax() { 551 global $USER; 552 553 $this->resetAfterTest(true); 554 set_config('calendar_adminseesall', 1); 555 $this->setAdminUser(); 556 557 // Enable MathJax filter in content and headings. 558 $this->configure_filters([ 559 ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true], 560 ]); 561 562 // Create a site event with mathjax in the name and description. 563 $siteevent = $this->create_calendar_event('Site Event $$(a+b)=2$$', $USER->id, 'site', 0, time(), 564 ['description' => 'Site Event Description $$(a+b)=2$$']); 565 566 // Now call the WebService. 567 $events = core_calendar_external::get_calendar_events(); 568 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 569 570 // Format the original data. 571 $sitecontext = \context_system::instance(); 572 $siteevent->name = $siteevent->format_external_name(); 573 list($siteevent->description, $siteevent->descriptionformat) = $siteevent->format_external_text(); 574 575 // Check that the event data is formatted. 576 $this->assertCount(1, $events['events']); 577 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $events['events'][0]['name']); 578 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $events['events'][0]['description']); 579 $this->assertEquals($siteevent->name, $events['events'][0]['name']); 580 $this->assertEquals($siteevent->description, $events['events'][0]['description']); 581 } 582 583 /** 584 * Test core_calendar_external::create_calendar_events 585 */ 586 public function test_core_create_calendar_events() { 587 global $DB, $USER, $SITE; 588 589 $this->resetAfterTest(true); 590 $this->setAdminUser(); 591 592 // Create a few stuff to test with. 593 $user = $this->getDataGenerator()->create_user(); 594 $course = $this->getDataGenerator()->create_course(); 595 $record = new \stdClass(); 596 $record->courseid = $course->id; 597 $group = $this->getDataGenerator()->create_group($record); 598 599 $prevcount = $DB->count_records('event'); 600 601 // Let's create a few events. 602 $events = array ( 603 array('name' => 'site', 'courseid' => $SITE->id, 'eventtype' => 'site'), 604 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2), 605 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'), 606 array('name' => 'user') 607 ); 608 $eventsret = core_calendar_external::create_calendar_events($events); 609 $eventsret = \external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret); 610 611 // Check to see if things were created properly. 612 $aftercount = $DB->count_records('event'); 613 $this->assertEquals($prevcount + 5, $aftercount); 614 $this->assertEquals(5, count($eventsret['events'])); 615 $this->assertEquals(0, count($eventsret['warnings'])); 616 617 $sitecontext = \context_system::instance(); 618 $coursecontext = \context_course::instance($course->id); 619 620 $this->setUser($user); 621 $prevcount = $aftercount; 622 $events = array ( 623 array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2), 624 array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'), 625 array('name' => 'user') 626 ); 627 $role = $DB->get_record('role', array('shortname' => 'student')); 628 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 629 groups_add_member($group, $user); 630 $this->assignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id); 631 $this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id); 632 $eventsret = core_calendar_external::create_calendar_events($events); 633 $eventsret = \external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret); 634 // Check to see if things were created properly. 635 $aftercount = $DB->count_records('event'); 636 $this->assertEquals($prevcount + 4, $aftercount); 637 $this->assertEquals(4, count($eventsret['events'])); 638 $this->assertEquals(0, count($eventsret['warnings'])); 639 640 // Check to see nothing was created without proper permission. 641 $this->setGuestUser(); 642 $prevcount = $DB->count_records('event'); 643 $eventsret = core_calendar_external::create_calendar_events($events); 644 $eventsret = \external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret); 645 $aftercount = $DB->count_records('event'); 646 $this->assertEquals($prevcount, $aftercount); 647 $this->assertEquals(0, count($eventsret['events'])); 648 $this->assertEquals(3, count($eventsret['warnings'])); 649 650 $this->setUser($user); 651 $this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id); 652 $this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id); 653 $prevcount = $DB->count_records('event'); 654 $eventsret = core_calendar_external::create_calendar_events($events); 655 $eventsret = \external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret); 656 $aftercount = $DB->count_records('event'); 657 $this->assertEquals($prevcount + 1, $aftercount); // User event. 658 $this->assertEquals(1, count($eventsret['events'])); 659 $this->assertEquals(2, count($eventsret['warnings'])); 660 } 661 662 /** 663 * Requesting calendar events from a given time should return all events with a sort 664 * time at or after the requested time. All events prior to that time should not 665 * be return. 666 * 667 * If there are no events on or after the given time then an empty result set should 668 * be returned. 669 */ 670 public function test_get_calendar_action_events_by_timesort_after_time() { 671 $user = $this->getDataGenerator()->create_user(); 672 $course = $this->getDataGenerator()->create_course(); 673 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 674 $moduleinstance = $generator->create_instance(['course' => $course->id]); 675 676 $this->getDataGenerator()->enrol_user($user->id, $course->id); 677 $this->resetAfterTest(true); 678 $this->setUser($user); 679 680 $params = [ 681 'type' => CALENDAR_EVENT_TYPE_ACTION, 682 'modulename' => 'assign', 683 'instance' => $moduleinstance->id, 684 'courseid' => $course->id, 685 ]; 686 687 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1])); 688 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2])); 689 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3])); 690 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4])); 691 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5])); 692 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6])); 693 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7])); 694 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8])); 695 696 $result = core_calendar_external::get_calendar_action_events_by_timesort(5); 697 $result = \external_api::clean_returnvalue( 698 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 699 $result 700 ); 701 $events = $result['events']; 702 703 $this->assertCount(4, $events); 704 $this->assertEquals('Event 5', $events[0]['name']); 705 $this->assertEquals('Event 6', $events[1]['name']); 706 $this->assertEquals('Event 7', $events[2]['name']); 707 $this->assertEquals('Event 8', $events[3]['name']); 708 $this->assertEquals($event5->id, $result['firstid']); 709 $this->assertEquals($event8->id, $result['lastid']); 710 711 $result = core_calendar_external::get_calendar_action_events_by_timesort(9); 712 $result = \external_api::clean_returnvalue( 713 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 714 $result 715 ); 716 717 $this->assertEmpty($result['events']); 718 $this->assertNull($result['firstid']); 719 $this->assertNull($result['lastid']); 720 721 // Requesting action events on behalf of another user. 722 $this->setAdminUser(); 723 $result = core_calendar_external::get_calendar_action_events_by_timesort(5, null, 0, 20, false, $user->id); 724 $result = \external_api::clean_returnvalue( 725 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 726 $result 727 ); 728 $events = $result['events']; 729 730 $this->assertCount(4, $events); 731 $this->assertEquals('Event 5', $events[0]['name']); 732 $this->assertEquals('Event 6', $events[1]['name']); 733 $this->assertEquals('Event 7', $events[2]['name']); 734 $this->assertEquals('Event 8', $events[3]['name']); 735 $this->assertEquals($event5->id, $result['firstid']); 736 $this->assertEquals($event8->id, $result['lastid']); 737 } 738 739 /** 740 * Requesting calendar events before a given time should return all events with a sort 741 * time at or before the requested time (inclusive). All events after that time 742 * should not be returned. 743 * 744 * If there are no events before the given time then an empty result set should be 745 * returned. 746 */ 747 public function test_get_calendar_action_events_by_timesort_before_time() { 748 $user = $this->getDataGenerator()->create_user(); 749 $course = $this->getDataGenerator()->create_course(); 750 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 751 $moduleinstance = $generator->create_instance(['course' => $course->id]); 752 753 $this->getDataGenerator()->enrol_user($user->id, $course->id); 754 $this->resetAfterTest(true); 755 $this->setUser($user); 756 757 $params = [ 758 'type' => CALENDAR_EVENT_TYPE_ACTION, 759 'modulename' => 'assign', 760 'instance' => $moduleinstance->id, 761 'courseid' => $course->id, 762 ]; 763 764 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2])); 765 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3])); 766 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4])); 767 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5])); 768 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6])); 769 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7])); 770 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8])); 771 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 9])); 772 773 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5); 774 $result = \external_api::clean_returnvalue( 775 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 776 $result 777 ); 778 $events = $result['events']; 779 780 $this->assertCount(4, $events); 781 $this->assertEquals('Event 1', $events[0]['name']); 782 $this->assertEquals('Event 2', $events[1]['name']); 783 $this->assertEquals('Event 3', $events[2]['name']); 784 $this->assertEquals('Event 4', $events[3]['name']); 785 $this->assertEquals($event1->id, $result['firstid']); 786 $this->assertEquals($event4->id, $result['lastid']); 787 788 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 1); 789 $result = \external_api::clean_returnvalue( 790 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 791 $result 792 ); 793 794 $this->assertEmpty($result['events']); 795 $this->assertNull($result['firstid']); 796 $this->assertNull($result['lastid']); 797 798 // Requesting action events on behalf of another user. 799 $this->setAdminUser(); 800 801 $result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5, 0, 20, false, $user->id); 802 $result = \external_api::clean_returnvalue( 803 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 804 $result 805 ); 806 $events = $result['events']; 807 808 $this->assertCount(4, $events); 809 $this->assertEquals('Event 1', $events[0]['name']); 810 $this->assertEquals('Event 2', $events[1]['name']); 811 $this->assertEquals('Event 3', $events[2]['name']); 812 $this->assertEquals('Event 4', $events[3]['name']); 813 $this->assertEquals($event1->id, $result['firstid']); 814 $this->assertEquals($event4->id, $result['lastid']); 815 } 816 817 /** 818 * Test retrieving event that was overridden for a user 819 */ 820 public function test_get_calendar_events_override() { 821 $user = $this->getDataGenerator()->create_user(); 822 $user2 = $this->getDataGenerator()->create_user(); 823 $teacher = $this->getDataGenerator()->create_user(); 824 $anotheruser = $this->getDataGenerator()->create_user(); 825 $course = $this->getDataGenerator()->create_course(); 826 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 827 $moduleinstance = $generator->create_instance(['course' => $course->id]); 828 829 $this->getDataGenerator()->enrol_user($user->id, $course->id, 'student'); 830 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 831 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher'); 832 $this->resetAfterTest(true); 833 $this->setAdminUser(); 834 835 $params = [ 836 'type' => CALENDAR_EVENT_TYPE_ACTION, 837 'modulename' => 'assign', 838 'instance' => $moduleinstance->id, 839 ]; 840 841 $now = time(); 842 // Create two events - one for everybody in the course and one only for the first student. 843 $event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS, $params + ['courseid' => $course->id]); 844 $event2 = $this->create_calendar_event('User event', $user->id, 'due', 0, $now + 2*DAYSECS, $params + ['courseid' => 0]); 845 846 // Retrieve course events for the second student - only one "Base event" is returned. 847 $this->setUser($user2); 848 $paramevents = array('courseids' => array($course->id)); 849 $options = array ('siteevents' => true, 'userevents' => true); 850 $events = core_calendar_external::get_calendar_events($paramevents, $options); 851 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 852 $this->assertEquals(1, count($events['events'])); 853 $this->assertEquals(0, count($events['warnings'])); 854 $this->assertEquals('Base event', $events['events'][0]['name']); 855 856 // Retrieve events for the first student - both events are returned. 857 $this->setUser($user); 858 $events = core_calendar_external::get_calendar_events($paramevents, $options); 859 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 860 $this->assertEquals(2, count($events['events'])); 861 $this->assertEquals(0, count($events['warnings'])); 862 $this->assertEquals('Base event', $events['events'][0]['name']); 863 $this->assertEquals('User event', $events['events'][1]['name']); 864 865 // Retrieve events by id as a teacher, 'User event' should be returned since teacher has access to this course. 866 $this->setUser($teacher); 867 $paramevents = ['eventids' => [$event2->id]]; 868 $events = core_calendar_external::get_calendar_events($paramevents, $options); 869 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 870 $this->assertEquals(1, count($events['events'])); 871 $this->assertEquals(0, count($events['warnings'])); 872 $this->assertEquals('User event', $events['events'][0]['name']); 873 874 // Retrieve events by id as another user, nothing should be returned. 875 $this->setUser($anotheruser); 876 $paramevents = ['eventids' => [$event2->id, $event1->id]]; 877 $events = core_calendar_external::get_calendar_events($paramevents, $options); 878 $events = \external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); 879 $this->assertEquals(0, count($events['events'])); 880 $this->assertEquals(0, count($events['warnings'])); 881 } 882 883 /** 884 * Requesting calendar events within a given time range should return all events with 885 * a sort time between the lower and upper time bound (inclusive). 886 * 887 * If there are no events in the given time range then an empty result set should be 888 * returned. 889 */ 890 public function test_get_calendar_action_events_by_timesort_time_range() { 891 $user = $this->getDataGenerator()->create_user(); 892 $course = $this->getDataGenerator()->create_course(); 893 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 894 $moduleinstance = $generator->create_instance(['course' => $course->id]); 895 896 $this->getDataGenerator()->enrol_user($user->id, $course->id); 897 $this->resetAfterTest(true); 898 $this->setUser($user); 899 900 $params = [ 901 'type' => CALENDAR_EVENT_TYPE_ACTION, 902 'modulename' => 'assign', 903 'instance' => $moduleinstance->id, 904 'courseid' => $course->id, 905 ]; 906 907 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1])); 908 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2])); 909 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3])); 910 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4])); 911 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5])); 912 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6])); 913 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7])); 914 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8])); 915 916 $result = core_calendar_external::get_calendar_action_events_by_timesort(3, 6); 917 $result = \external_api::clean_returnvalue( 918 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 919 $result 920 ); 921 $events = $result['events']; 922 923 $this->assertCount(4, $events); 924 $this->assertEquals('Event 3', $events[0]['name']); 925 $this->assertEquals('Event 4', $events[1]['name']); 926 $this->assertEquals('Event 5', $events[2]['name']); 927 $this->assertEquals('Event 6', $events[3]['name']); 928 $this->assertEquals($event3->id, $result['firstid']); 929 $this->assertEquals($event6->id, $result['lastid']); 930 931 $result = core_calendar_external::get_calendar_action_events_by_timesort(10, 15); 932 $result = \external_api::clean_returnvalue( 933 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 934 $result 935 ); 936 937 $this->assertEmpty($result['events']); 938 $this->assertNull($result['firstid']); 939 $this->assertNull($result['lastid']); 940 } 941 942 /** 943 * Requesting calendar events within a given time range and a limit and offset should return 944 * the number of events up to the given limit value that have a sort time between the lower 945 * and uppper time bound (inclusive) where the result set is shifted by the offset value. 946 * 947 * If there are no events in the given time range then an empty result set should be 948 * returned. 949 */ 950 public function test_get_calendar_action_events_by_timesort_time_limit_offset() { 951 $user = $this->getDataGenerator()->create_user(); 952 $course = $this->getDataGenerator()->create_course(); 953 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 954 $moduleinstance = $generator->create_instance(['course' => $course->id]); 955 956 $this->getDataGenerator()->enrol_user($user->id, $course->id); 957 $this->resetAfterTest(true); 958 $this->setUser($user); 959 960 $params = [ 961 'type' => CALENDAR_EVENT_TYPE_ACTION, 962 'modulename' => 'assign', 963 'instance' => $moduleinstance->id, 964 'courseid' => $course->id, 965 ]; 966 967 $event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1])); 968 $event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2])); 969 $event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3])); 970 $event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4])); 971 $event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5])); 972 $event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6])); 973 $event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7])); 974 $event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8])); 975 976 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event3->id, 2); 977 $result = \external_api::clean_returnvalue( 978 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 979 $result 980 ); 981 $events = $result['events']; 982 983 $this->assertCount(2, $events); 984 $this->assertEquals('Event 4', $events[0]['name']); 985 $this->assertEquals('Event 5', $events[1]['name']); 986 $this->assertEquals($event4->id, $result['firstid']); 987 $this->assertEquals($event5->id, $result['lastid']); 988 989 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event5->id, 2); 990 $result = \external_api::clean_returnvalue( 991 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 992 $result 993 ); 994 $events = $result['events']; 995 996 $this->assertCount(2, $events); 997 $this->assertEquals('Event 6', $events[0]['name']); 998 $this->assertEquals('Event 7', $events[1]['name']); 999 $this->assertEquals($event6->id, $result['firstid']); 1000 $this->assertEquals($event7->id, $result['lastid']); 1001 1002 $result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event7->id, 2); 1003 $result = \external_api::clean_returnvalue( 1004 core_calendar_external::get_calendar_action_events_by_timesort_returns(), 1005 $result 1006 ); 1007 1008 $this->assertEmpty($result['events']); 1009 $this->assertNull($result['firstid']); 1010 $this->assertNull($result['lastid']); 1011 } 1012 1013 /** 1014 * Check that it is possible to restrict the calendar events to events where the user is not suspended in the course. 1015 */ 1016 public function test_get_calendar_action_events_by_timesort_suspended_course() { 1017 $this->resetAfterTest(); 1018 $user1 = $this->getDataGenerator()->create_user(); 1019 $user2 = $this->getDataGenerator()->create_user(); 1020 $course = $this->getDataGenerator()->create_course(); 1021 $this->setAdminUser(); 1022 $lesson = $this->getDataGenerator()->create_module('lesson', [ 1023 'name' => 'Lesson 1', 1024 'course' => $course->id, 1025 'available' => time(), 1026 'deadline' => (time() + (60 * 60 * 24 * 5)) 1027 ] 1028 ); 1029 $this->getDataGenerator()->enrol_user($user1->id, $course->id, null, 'manual', 0, 0, ENROL_USER_SUSPENDED); 1030 $this->getDataGenerator()->enrol_user($user2->id, $course->id); 1031 1032 $this->setUser($user1); 1033 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true); 1034 $this->assertEmpty($result->events); 1035 $this->setUser($user2); 1036 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true); 1037 $this->assertCount(1, $result->events); 1038 $this->assertEquals('Lesson 1 closes', $result->events[0]->name); 1039 } 1040 1041 /** 1042 * Check that it is possible to get other user's events without the permission. 1043 */ 1044 public function test_get_calendar_action_events_by_timesort_for_other_users() { 1045 $this->resetAfterTest(); 1046 // Create test users. 1047 $user1 = $this->getDataGenerator()->create_user(['email' => 'student1@localhost.com']); 1048 $user2 = $this->getDataGenerator()->create_user(['email' => 'student2@localhost.com']); 1049 // Create test course. 1050 $course = $this->getDataGenerator()->create_course(); 1051 $this->setAdminUser(); 1052 // Create test activity and make it available only for student2. 1053 $lesson = $this->getDataGenerator()->create_module('lesson', [ 1054 'name' => 'Lesson 1', 1055 'course' => $course->id, 1056 'available' => time(), 1057 'deadline' => (time() + (60 * 60 * 24 * 5)), 1058 'availability' => '{"op":"&","c":[{"type":"profile","sf":"email","op":"isequalto","v":"student2@localhost.com"}],"showc":[true]}' 1059 ] 1060 ); 1061 // Enrol. 1062 $this->getDataGenerator()->enrol_user($user1->id, $course->id); 1063 $this->getDataGenerator()->enrol_user($user2->id, $course->id); 1064 1065 // Student2 can see the event. 1066 $this->setUser($user2); 1067 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true); 1068 $this->assertCount(1, $result->events); 1069 $this->assertEquals('Lesson 1 closes', $result->events[0]->name); 1070 1071 // Student1 cannot see the event. 1072 $this->setUser($user1); 1073 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true); 1074 $this->assertEmpty($result->events); 1075 1076 // Admin, Manager, Teacher can view student2's data. 1077 $this->setAdminUser(); 1078 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true, $user2->id); 1079 $this->assertCount(1, $result->events); 1080 $this->assertEquals('Lesson 1 closes', $result->events[0]->name); 1081 1082 // Student1 will see an exception if he/she trying to view student2's data. 1083 $this->setUser($user1); 1084 $this->expectException(\required_capability_exception::class); 1085 $this->expectExceptionMessage('error/nopermission'); 1086 $result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true, $user2->id); 1087 } 1088 1089 /** 1090 * Requesting calendar events from a given course and time should return all 1091 * events with a sort time at or after the requested time. All events prior 1092 * to that time should not be return. 1093 * 1094 * If there are no events on or after the given time then an empty result set should 1095 * be returned. 1096 */ 1097 public function test_get_calendar_action_events_by_course_after_time() { 1098 $user = $this->getDataGenerator()->create_user(); 1099 $course1 = $this->getDataGenerator()->create_course(); 1100 $course2 = $this->getDataGenerator()->create_course(); 1101 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1102 $instance1 = $generator->create_instance(['course' => $course1->id]); 1103 $instance2 = $generator->create_instance(['course' => $course2->id]); 1104 $records = []; 1105 1106 $this->getDataGenerator()->enrol_user($user->id, $course1->id); 1107 $this->getDataGenerator()->enrol_user($user->id, $course2->id); 1108 $this->resetAfterTest(true); 1109 $this->setUser($user); 1110 1111 for ($i = 1; $i < 19; $i++) { 1112 $courseid = ($i < 9) ? $course1->id : $course2->id; 1113 $instance = ($i < 9) ? $instance1->id : $instance2->id; 1114 $records[] = $this->create_calendar_event( 1115 sprintf('Event %d', $i), 1116 $user->id, 1117 'user', 1118 0, 1119 1, 1120 [ 1121 'type' => CALENDAR_EVENT_TYPE_ACTION, 1122 'courseid' => $courseid, 1123 'timesort' => $i, 1124 'modulename' => 'assign', 1125 'instance' => $instance, 1126 ] 1127 ); 1128 } 1129 1130 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 5); 1131 $result = \external_api::clean_returnvalue( 1132 core_calendar_external::get_calendar_action_events_by_course_returns(), 1133 $result 1134 ); 1135 $result = $result['events']; 1136 1137 $this->assertCount(4, $result); 1138 $this->assertEquals('Event 5', $result[0]['name']); 1139 $this->assertEquals('Event 6', $result[1]['name']); 1140 $this->assertEquals('Event 7', $result[2]['name']); 1141 $this->assertEquals('Event 8', $result[3]['name']); 1142 1143 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 9); 1144 $result = \external_api::clean_returnvalue( 1145 core_calendar_external::get_calendar_action_events_by_course_returns(), 1146 $result 1147 ); 1148 $result = $result['events']; 1149 1150 $this->assertEmpty($result); 1151 } 1152 1153 /** 1154 * Requesting calendar events for a course and before a given time should return 1155 * all events with a sort time at or before the requested time (inclusive). All 1156 * events after that time should not be returned. 1157 * 1158 * If there are no events before the given time then an empty result set should be 1159 * returned. 1160 */ 1161 public function test_get_calendar_action_events_by_course_before_time() { 1162 $user = $this->getDataGenerator()->create_user(); 1163 $course1 = $this->getDataGenerator()->create_course(); 1164 $course2 = $this->getDataGenerator()->create_course(); 1165 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1166 $instance1 = $generator->create_instance(['course' => $course1->id]); 1167 $instance2 = $generator->create_instance(['course' => $course2->id]); 1168 $records = []; 1169 1170 $this->getDataGenerator()->enrol_user($user->id, $course1->id); 1171 $this->getDataGenerator()->enrol_user($user->id, $course2->id); 1172 $this->resetAfterTest(true); 1173 $this->setUser($user); 1174 1175 for ($i = 1; $i < 19; $i++) { 1176 $courseid = ($i < 9) ? $course1->id : $course2->id; 1177 $instance = ($i < 9) ? $instance1->id : $instance2->id; 1178 $records[] = $this->create_calendar_event( 1179 sprintf('Event %d', $i), 1180 $user->id, 1181 'user', 1182 0, 1183 1, 1184 [ 1185 'type' => CALENDAR_EVENT_TYPE_ACTION, 1186 'courseid' => $courseid, 1187 'timesort' => $i + 1, 1188 'modulename' => 'assign', 1189 'instance' => $instance, 1190 ] 1191 ); 1192 } 1193 1194 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 5); 1195 $result = \external_api::clean_returnvalue( 1196 core_calendar_external::get_calendar_action_events_by_course_returns(), 1197 $result 1198 ); 1199 $result = $result['events']; 1200 1201 $this->assertCount(4, $result); 1202 $this->assertEquals('Event 1', $result[0]['name']); 1203 $this->assertEquals('Event 2', $result[1]['name']); 1204 $this->assertEquals('Event 3', $result[2]['name']); 1205 $this->assertEquals('Event 4', $result[3]['name']); 1206 1207 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 1); 1208 $result = \external_api::clean_returnvalue( 1209 core_calendar_external::get_calendar_action_events_by_course_returns(), 1210 $result 1211 ); 1212 $result = $result['events']; 1213 1214 $this->assertEmpty($result); 1215 } 1216 1217 /** 1218 * Requesting calendar events for a course and within a given time range should 1219 * return all events with a sort time between the lower and upper time bound 1220 * (inclusive). 1221 * 1222 * If there are no events in the given time range then an empty result set should be 1223 * returned. 1224 */ 1225 public function test_get_calendar_action_events_by_course_time_range() { 1226 $user = $this->getDataGenerator()->create_user(); 1227 $course1 = $this->getDataGenerator()->create_course(); 1228 $course2 = $this->getDataGenerator()->create_course(); 1229 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1230 $instance1 = $generator->create_instance(['course' => $course1->id]); 1231 $instance2 = $generator->create_instance(['course' => $course2->id]); 1232 $records = []; 1233 1234 $this->getDataGenerator()->enrol_user($user->id, $course1->id); 1235 $this->getDataGenerator()->enrol_user($user->id, $course2->id); 1236 $this->resetAfterTest(true); 1237 $this->setUser($user); 1238 1239 for ($i = 1; $i < 19; $i++) { 1240 $courseid = ($i < 9) ? $course1->id : $course2->id; 1241 $instance = ($i < 9) ? $instance1->id : $instance2->id; 1242 $records[] = $this->create_calendar_event( 1243 sprintf('Event %d', $i), 1244 $user->id, 1245 'user', 1246 0, 1247 1, 1248 [ 1249 'type' => CALENDAR_EVENT_TYPE_ACTION, 1250 'courseid' => $courseid, 1251 'timesort' => $i, 1252 'modulename' => 'assign', 1253 'instance' => $instance, 1254 ] 1255 ); 1256 } 1257 1258 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 3, 6); 1259 $result = \external_api::clean_returnvalue( 1260 core_calendar_external::get_calendar_action_events_by_course_returns(), 1261 $result 1262 ); 1263 $result = $result['events']; 1264 1265 $this->assertCount(4, $result); 1266 $this->assertEquals('Event 3', $result[0]['name']); 1267 $this->assertEquals('Event 4', $result[1]['name']); 1268 $this->assertEquals('Event 5', $result[2]['name']); 1269 $this->assertEquals('Event 6', $result[3]['name']); 1270 1271 $result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 10, 15); 1272 $result = \external_api::clean_returnvalue( 1273 core_calendar_external::get_calendar_action_events_by_course_returns(), 1274 $result 1275 ); 1276 $result = $result['events']; 1277 1278 $this->assertEmpty($result); 1279 } 1280 1281 /** 1282 * Requesting calendar events for a course and within a given time range and a limit 1283 * and offset should return the number of events up to the given limit value that have 1284 * a sort time between the lower and uppper time bound (inclusive) where the result 1285 * set is shifted by the offset value. 1286 * 1287 * If there are no events in the given time range then an empty result set should be 1288 * returned. 1289 */ 1290 public function test_get_calendar_action_events_by_course_time_limit_offset() { 1291 $user = $this->getDataGenerator()->create_user(); 1292 $course1 = $this->getDataGenerator()->create_course(); 1293 $course2 = $this->getDataGenerator()->create_course(); 1294 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1295 $instance1 = $generator->create_instance(['course' => $course1->id]); 1296 $instance2 = $generator->create_instance(['course' => $course2->id]); 1297 $records = []; 1298 1299 $this->getDataGenerator()->enrol_user($user->id, $course1->id); 1300 $this->getDataGenerator()->enrol_user($user->id, $course2->id); 1301 $this->resetAfterTest(true); 1302 $this->setUser($user); 1303 1304 for ($i = 1; $i < 19; $i++) { 1305 $courseid = ($i < 9) ? $course1->id : $course2->id; 1306 $instance = ($i < 9) ? $instance1->id : $instance2->id; 1307 $records[] = $this->create_calendar_event( 1308 sprintf('Event %d', $i), 1309 $user->id, 1310 'user', 1311 0, 1312 1, 1313 [ 1314 'type' => CALENDAR_EVENT_TYPE_ACTION, 1315 'courseid' => $courseid, 1316 'timesort' => $i, 1317 'modulename' => 'assign', 1318 'instance' => $instance, 1319 ] 1320 ); 1321 } 1322 1323 $result = core_calendar_external::get_calendar_action_events_by_course( 1324 $course1->id, 2, 7, $records[2]->id, 2); 1325 $result = \external_api::clean_returnvalue( 1326 core_calendar_external::get_calendar_action_events_by_course_returns(), 1327 $result 1328 ); 1329 $result = $result['events']; 1330 1331 $this->assertCount(2, $result); 1332 $this->assertEquals('Event 4', $result[0]['name']); 1333 $this->assertEquals('Event 5', $result[1]['name']); 1334 1335 $result = core_calendar_external::get_calendar_action_events_by_course( 1336 $course1->id, 2, 7, $records[4]->id, 2); 1337 $result = \external_api::clean_returnvalue( 1338 core_calendar_external::get_calendar_action_events_by_course_returns(), 1339 $result 1340 ); 1341 $result = $result['events']; 1342 1343 $this->assertCount(2, $result); 1344 $this->assertEquals('Event 6', $result[0]['name']); 1345 $this->assertEquals('Event 7', $result[1]['name']); 1346 1347 $result = core_calendar_external::get_calendar_action_events_by_course( 1348 $course1->id, 2, 7, $records[6]->id, 2); 1349 $result = \external_api::clean_returnvalue( 1350 core_calendar_external::get_calendar_action_events_by_course_returns(), 1351 $result 1352 ); 1353 $result = $result['events']; 1354 1355 $this->assertEmpty($result); 1356 } 1357 1358 /** 1359 * Test get_calendar_action_events_by_course with search feature 1360 */ 1361 public function test_get_calendar_action_events_by_course_with_search() { 1362 // Generate data. 1363 $user = $this->getDataGenerator()->create_user(); 1364 $course = $this->getDataGenerator()->create_course(); 1365 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1366 $instance = $generator->create_instance(['course' => $course->id]); 1367 1368 // Enrol. 1369 $this->getDataGenerator()->enrol_user($user->id, $course->id); 1370 $this->resetAfterTest(true); 1371 $this->setUser($user); 1372 1373 for ($i = 1; $i < 5; $i++) { 1374 $this->create_calendar_event( 1375 sprintf('Event %d', $i), 1376 $user->id, 1377 'user', 1378 0, 1379 1, 1380 [ 1381 'type' => CALENDAR_EVENT_TYPE_ACTION, 1382 'courseid' => $course->id, 1383 'timesort' => $i, 1384 'modulename' => 'assign', 1385 'instance' => $instance->id, 1386 ] 1387 ); 1388 } 1389 1390 // No result found for fake search. 1391 $result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'Fake search'); 1392 $result = \external_api::clean_returnvalue( 1393 core_calendar_external::get_calendar_action_events_by_course_returns(), 1394 $result 1395 ); 1396 $result = $result['events']; 1397 $this->assertEmpty($result); 1398 1399 // Search for event name called 'Event 1'. 1400 $result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'Event 1'); 1401 $result = \external_api::clean_returnvalue( 1402 core_calendar_external::get_calendar_action_events_by_course_returns(), 1403 $result 1404 ); 1405 $result = $result['events']; 1406 $this->assertCount(1, $result); 1407 $this->assertEquals('Event 1', $result[0]['name']); 1408 1409 // Search for activity type called 'assign'. 1410 $result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'assign'); 1411 $result = \external_api::clean_returnvalue( 1412 core_calendar_external::get_calendar_action_events_by_course_returns(), 1413 $result 1414 ); 1415 $result = $result['events']; 1416 $this->assertCount(4, $result); 1417 $this->assertEquals('Event 1', $result[0]['name']); 1418 $this->assertEquals('Event 2', $result[1]['name']); 1419 $this->assertEquals('Event 3', $result[2]['name']); 1420 $this->assertEquals('Event 4', $result[3]['name']); 1421 } 1422 1423 /** 1424 * Test that get_action_events_by_courses will return a list of events for each 1425 * course you provided as long as the user is enrolled in the course. 1426 */ 1427 public function test_get_action_events_by_courses() { 1428 $user = $this->getDataGenerator()->create_user(); 1429 $course1 = $this->getDataGenerator()->create_course(); 1430 $course2 = $this->getDataGenerator()->create_course(); 1431 $course3 = $this->getDataGenerator()->create_course(); 1432 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1433 $instance1 = $generator->create_instance(['course' => $course1->id]); 1434 $instance2 = $generator->create_instance(['course' => $course2->id]); 1435 $instance3 = $generator->create_instance(['course' => $course3->id]); 1436 $records = []; 1437 $mapresult = function($result) { 1438 $groupedbycourse = []; 1439 foreach ($result['groupedbycourse'] as $group) { 1440 $events = $group['events']; 1441 $courseid = $group['courseid']; 1442 $groupedbycourse[$courseid] = $events; 1443 } 1444 1445 return $groupedbycourse; 1446 }; 1447 1448 $this->getDataGenerator()->enrol_user($user->id, $course1->id); 1449 $this->getDataGenerator()->enrol_user($user->id, $course2->id); 1450 $this->resetAfterTest(true); 1451 $this->setUser($user); 1452 1453 for ($i = 1; $i < 10; $i++) { 1454 if ($i < 3) { 1455 $courseid = $course1->id; 1456 $instance = $instance1->id; 1457 } else if ($i < 6) { 1458 $courseid = $course2->id; 1459 $instance = $instance2->id; 1460 } else { 1461 $courseid = $course3->id; 1462 $instance = $instance3->id; 1463 } 1464 1465 $records[] = $this->create_calendar_event( 1466 sprintf('Event %d', $i), 1467 $user->id, 1468 'user', 1469 0, 1470 1, 1471 [ 1472 'type' => CALENDAR_EVENT_TYPE_ACTION, 1473 'courseid' => $courseid, 1474 'timesort' => $i, 1475 'modulename' => 'assign', 1476 'instance' => $instance, 1477 ] 1478 ); 1479 } 1480 1481 $result = core_calendar_external::get_calendar_action_events_by_courses([], 1); 1482 $result = \external_api::clean_returnvalue( 1483 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1484 $result 1485 ); 1486 $result = $result['groupedbycourse']; 1487 1488 $this->assertEmpty($result); 1489 1490 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 3); 1491 $result = \external_api::clean_returnvalue( 1492 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1493 $result 1494 ); 1495 1496 $groupedbycourse = $mapresult($result); 1497 1498 $this->assertEmpty($groupedbycourse[$course1->id]); 1499 1500 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 1); 1501 $result = \external_api::clean_returnvalue( 1502 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1503 $result 1504 ); 1505 $groupedbycourse = $mapresult($result); 1506 1507 $this->assertCount(2, $groupedbycourse[$course1->id]); 1508 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']); 1509 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']); 1510 1511 $result = core_calendar_external::get_calendar_action_events_by_courses( 1512 [$course1->id, $course2->id], 1); 1513 $result = \external_api::clean_returnvalue( 1514 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1515 $result 1516 ); 1517 $groupedbycourse = $mapresult($result); 1518 1519 $this->assertCount(2, $groupedbycourse[$course1->id]); 1520 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']); 1521 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']); 1522 $this->assertCount(3, $groupedbycourse[$course2->id]); 1523 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']); 1524 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']); 1525 $this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']); 1526 1527 $result = core_calendar_external::get_calendar_action_events_by_courses( 1528 [$course1->id, $course2->id], 2, 4); 1529 $result = \external_api::clean_returnvalue( 1530 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1531 $result 1532 ); 1533 $groupedbycourse = $mapresult($result); 1534 1535 $this->assertCount(2, $groupedbycourse); 1536 $this->assertCount(1, $groupedbycourse[$course1->id]); 1537 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][0]['name']); 1538 $this->assertCount(2, $groupedbycourse[$course2->id]); 1539 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']); 1540 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']); 1541 1542 $result = core_calendar_external::get_calendar_action_events_by_courses( 1543 [$course1->id, $course2->id], 1, null, 1); 1544 $result = \external_api::clean_returnvalue( 1545 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1546 $result 1547 ); 1548 $groupedbycourse = $mapresult($result); 1549 1550 $this->assertCount(2, $groupedbycourse); 1551 $this->assertCount(1, $groupedbycourse[$course1->id]); 1552 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']); 1553 $this->assertCount(1, $groupedbycourse[$course2->id]); 1554 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']); 1555 } 1556 1557 /** 1558 * Test get_action_events_by_courses with search feature 1559 */ 1560 public function test_get_action_events_by_courses_with_search() { 1561 // Generate data. 1562 $user = $this->getDataGenerator()->create_user(); 1563 $course1 = $this->getDataGenerator()->create_course(); 1564 $course2 = $this->getDataGenerator()->create_course(); 1565 $course3 = $this->getDataGenerator()->create_course(); 1566 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 1567 $instance1 = $generator->create_instance(['course' => $course1->id]); 1568 $instance2 = $generator->create_instance(['course' => $course2->id]); 1569 $instance3 = $generator->create_instance(['course' => $course3->id]); 1570 1571 $this->getDataGenerator()->enrol_user($user->id, $course1->id); 1572 $this->getDataGenerator()->enrol_user($user->id, $course2->id); 1573 $this->resetAfterTest(true); 1574 $this->setUser($user); 1575 1576 $mapresult = function($result) { 1577 $groupedbycourse = []; 1578 foreach ($result['groupedbycourse'] as $group) { 1579 $events = $group['events']; 1580 $courseid = $group['courseid']; 1581 $groupedbycourse[$courseid] = $events; 1582 } 1583 1584 return $groupedbycourse; 1585 }; 1586 1587 for ($i = 1; $i < 10; $i++) { 1588 if ($i < 3) { 1589 $courseid = $course1->id; 1590 $instance = $instance1->id; 1591 } else if ($i < 6) { 1592 $courseid = $course2->id; 1593 $instance = $instance2->id; 1594 } else { 1595 $courseid = $course3->id; 1596 $instance = $instance3->id; 1597 } 1598 1599 $records[] = $this->create_calendar_event( 1600 sprintf('Event %d', $i), 1601 $user->id, 1602 'user', 1603 0, 1604 1, 1605 [ 1606 'type' => CALENDAR_EVENT_TYPE_ACTION, 1607 'courseid' => $courseid, 1608 'timesort' => $i, 1609 'modulename' => 'assign', 1610 'instance' => $instance, 1611 ] 1612 ); 1613 } 1614 1615 // No result found for fake search. 1616 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id], 1617 1, null, 20, 'Fake search'); 1618 $result = \external_api::clean_returnvalue( 1619 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1620 $result 1621 ); 1622 $groupedbycourse = $mapresult($result); 1623 1624 $this->assertEmpty($groupedbycourse[$course1->id]); 1625 $this->assertEmpty($groupedbycourse[$course2->id]); 1626 $this->assertArrayNotHasKey($course3->id, $groupedbycourse); 1627 1628 // Search for event name called 'Event 1'. 1629 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id], 1630 1, null, 20, 'Event 1'); 1631 $result = \external_api::clean_returnvalue( 1632 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1633 $result 1634 ); 1635 $groupedbycourse = $mapresult($result); 1636 1637 $this->assertArrayNotHasKey($course3->id, $groupedbycourse); 1638 $this->assertCount(2, $groupedbycourse); 1639 $this->assertCount(1, $groupedbycourse[$course1->id]); 1640 $this->assertCount(0, $groupedbycourse[$course2->id]); 1641 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']); 1642 1643 // Search for activity type called 'assign'. 1644 $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id], 1645 1, null, 20, 'assign'); 1646 $result = \external_api::clean_returnvalue( 1647 core_calendar_external::get_calendar_action_events_by_courses_returns(), 1648 $result 1649 ); 1650 $groupedbycourse = $mapresult($result); 1651 1652 $this->assertArrayNotHasKey($course3->id, $groupedbycourse); 1653 $this->assertCount(2, $groupedbycourse); 1654 $this->assertCount(2, $groupedbycourse[$course1->id]); 1655 $this->assertCount(3, $groupedbycourse[$course2->id]); 1656 $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']); 1657 $this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']); 1658 $this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']); 1659 $this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']); 1660 $this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']); 1661 } 1662 1663 /** 1664 * Test for deleting module events. 1665 */ 1666 public function test_delete_calendar_events_for_modules() { 1667 $this->resetAfterTest(); 1668 $this->setAdminUser(); 1669 $course = $this->getDataGenerator()->create_course(); 1670 $nexttime = time() + DAYSECS; 1671 $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'duedate' => $nexttime]); 1672 $events = calendar_get_events(time(), $nexttime, true, true, true); 1673 $this->assertCount(1, $events); 1674 $params = []; 1675 foreach ($events as $event) { 1676 $params[] = [ 1677 'eventid' => $event->id, 1678 'repeat' => false 1679 ]; 1680 } 1681 1682 $this->expectException(\moodle_exception::class); 1683 core_calendar_external::delete_calendar_events($params); 1684 } 1685 1686 /** 1687 * Updating the event start day should change the date value but leave 1688 * the time of day unchanged. 1689 */ 1690 public function test_update_event_start_day() { 1691 $generator = $this->getDataGenerator(); 1692 $user = $generator->create_user(); 1693 $roleid = $generator->create_role(); 1694 $context = \context_system::instance(); 1695 $originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00'); 1696 $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00'); 1697 $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00'); 1698 1699 $generator->role_assign($roleid, $user->id, $context->id); 1700 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true); 1701 1702 $this->setUser($user); 1703 $this->resetAfterTest(true); 1704 1705 $event = $this->create_calendar_event( 1706 'Test event', 1707 $user->id, 1708 'user', 1709 0, 1710 null, 1711 [ 1712 'courseid' => 0, 1713 'timestart' => $originalstarttime->getTimestamp() 1714 ] 1715 ); 1716 1717 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp()); 1718 $result = \external_api::clean_returnvalue( 1719 core_calendar_external::update_event_start_day_returns(), 1720 $result 1721 ); 1722 1723 $this->assertEquals($expected->getTimestamp(), $result['event']['timestart']); 1724 } 1725 1726 /** 1727 * A user should not be able to edit an event that they don't have 1728 * capabilities for. 1729 */ 1730 public function test_update_event_start_day_no_permission() { 1731 $generator = $this->getDataGenerator(); 1732 $user = $generator->create_user(); 1733 $roleid = $generator->create_role(); 1734 $context = \context_system::instance(); 1735 $originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00'); 1736 $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00'); 1737 $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00'); 1738 1739 $generator->role_assign($roleid, $user->id, $context->id); 1740 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true); 1741 1742 $this->setUser($user); 1743 $this->resetAfterTest(true); 1744 1745 $event = $this->create_calendar_event( 1746 'Test event', 1747 $user->id, 1748 'user', 1749 0, 1750 null, 1751 [ 1752 'courseid' => 0, 1753 'timestart' => $originalstarttime->getTimestamp() 1754 ] 1755 ); 1756 1757 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true); 1758 $this->expectException(\moodle_exception::class); 1759 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp()); 1760 $result = \external_api::clean_returnvalue( 1761 core_calendar_external::update_event_start_day_returns(), 1762 $result 1763 ); 1764 } 1765 1766 /** 1767 * A user should not be able to update a module event. 1768 */ 1769 public function test_update_event_start_day_module_event() { 1770 $generator = $this->getDataGenerator(); 1771 $user = $generator->create_user(); 1772 $course = $generator->create_course(); 1773 $plugingenerator = $generator->get_plugin_generator('mod_assign'); 1774 $moduleinstance = $plugingenerator->create_instance(['course' => $course->id]); 1775 $roleid = $generator->create_role(); 1776 $context = \context_course::instance($course->id); 1777 $originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00'); 1778 $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00'); 1779 $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00'); 1780 1781 $generator->role_assign($roleid, $user->id, $context->id); 1782 $generator->enrol_user($user->id, $course->id); 1783 1784 $this->setUser($user); 1785 $this->resetAfterTest(true); 1786 1787 $event = $this->create_calendar_event( 1788 'Test event', 1789 $user->id, 1790 'user', 1791 0, 1792 null, 1793 [ 1794 'modulename' => 'assign', 1795 'instance' => $moduleinstance->id, 1796 'courseid' => $course->id, 1797 'timestart' => $originalstarttime->getTimestamp() 1798 ] 1799 ); 1800 1801 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 1802 $this->expectException(\moodle_exception::class); 1803 $result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp()); 1804 $result = \external_api::clean_returnvalue( 1805 core_calendar_external::update_event_start_day_returns(), 1806 $result 1807 ); 1808 } 1809 1810 /** 1811 * Submit a request where the time duration until is earlier than the time 1812 * start in order to get a validation error from the server. 1813 */ 1814 public function test_submit_create_update_form_validation_error() { 1815 $user = $this->getDataGenerator()->create_user(); 1816 $timestart = new \DateTime(); 1817 $interval = new \DateInterval("P1D"); // One day. 1818 $timedurationuntil = new \DateTime(); 1819 $timedurationuntil->sub($interval); 1820 $formdata = [ 1821 'id' => 0, 1822 'userid' => $user->id, 1823 'modulename' => '', 1824 'instance' => 0, 1825 'visible' => 1, 1826 'name' => 'Test', 1827 'timestart' => [ 1828 'day' => $timestart->format('j'), 1829 'month' => $timestart->format('n'), 1830 'year' => $timestart->format('Y'), 1831 'hour' => $timestart->format('G'), 1832 'minute' => 0, 1833 ], 1834 'eventtype' => 'user', 1835 'description' => [ 1836 'text' => '', 1837 'format' => 1, 1838 ], 1839 'location' => 'Test', 1840 'duration' => 1, 1841 'timedurationuntil' => [ 1842 'day' => $timedurationuntil->format('j'), 1843 'month' => $timedurationuntil->format('n'), 1844 'year' => $timedurationuntil->format('Y'), 1845 'hour' => $timedurationuntil->format('G'), 1846 'minute' => 0, 1847 ] 1848 ]; 1849 1850 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 1851 1852 $querystring = http_build_query($formdata, '', '&'); 1853 1854 $this->resetAfterTest(true); 1855 $this->setUser($user); 1856 1857 $result = \external_api::clean_returnvalue( 1858 core_calendar_external::submit_create_update_form_returns(), 1859 core_calendar_external::submit_create_update_form($querystring) 1860 ); 1861 1862 $this->assertTrue($result['validationerror']); 1863 } 1864 1865 /** 1866 * A user with the moodle/calendar:manageownentries capability at the 1867 * system context should be able to create a user event. 1868 */ 1869 public function test_submit_create_update_form_create_user_event() { 1870 $generator = $this->getDataGenerator(); 1871 $user = $generator->create_user(); 1872 $roleid = $generator->create_role(); 1873 $context = \context_system::instance(); 1874 $timestart = new \DateTime(); 1875 $interval = new \DateInterval("P1D"); // One day. 1876 $timedurationuntil = new \DateTime(); 1877 $timedurationuntil->add($interval); 1878 $formdata = [ 1879 'id' => 0, 1880 'userid' => $user->id, 1881 'modulename' => '', 1882 'instance' => 0, 1883 'visible' => 1, 1884 'name' => 'Test', 1885 'timestart' => [ 1886 'day' => $timestart->format('j'), 1887 'month' => $timestart->format('n'), 1888 'year' => $timestart->format('Y'), 1889 'hour' => $timestart->format('G'), 1890 'minute' => 0, 1891 ], 1892 'eventtype' => 'user', 1893 'description' => [ 1894 'text' => '', 1895 'format' => 1, 1896 'itemid' => 0 1897 ], 1898 'location' => 'Test', 1899 'duration' => 1, 1900 'timedurationuntil' => [ 1901 'day' => $timedurationuntil->format('j'), 1902 'month' => $timedurationuntil->format('n'), 1903 'year' => $timedurationuntil->format('Y'), 1904 'hour' => $timedurationuntil->format('G'), 1905 'minute' => 0, 1906 ] 1907 ]; 1908 1909 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 1910 $querystring = http_build_query($formdata, '', '&'); 1911 1912 $generator->role_assign($roleid, $user->id, $context->id); 1913 assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true); 1914 1915 $user->ignoresesskey = true; 1916 $this->resetAfterTest(true); 1917 $this->setUser($user); 1918 1919 $result = \external_api::clean_returnvalue( 1920 core_calendar_external::submit_create_update_form_returns(), 1921 core_calendar_external::submit_create_update_form($querystring) 1922 ); 1923 1924 $event = $result['event']; 1925 $this->assertEquals($user->id, $event['userid']); 1926 $this->assertEquals($formdata['eventtype'], $event['eventtype']); 1927 $this->assertEquals($formdata['name'], $event['name']); 1928 } 1929 1930 /** 1931 * A user without the moodle/calendar:manageownentries capability at the 1932 * system context should not be able to create a user event. 1933 */ 1934 public function test_submit_create_update_form_create_user_event_no_permission() { 1935 $generator = $this->getDataGenerator(); 1936 $user = $generator->create_user(); 1937 $roleid = $generator->create_role(); 1938 $context = \context_system::instance(); 1939 $timestart = new \DateTime(); 1940 $interval = new \DateInterval("P1D"); // One day. 1941 $timedurationuntil = new \DateTime(); 1942 $timedurationuntil->add($interval); 1943 $formdata = [ 1944 'id' => 0, 1945 'userid' => $user->id, 1946 'modulename' => '', 1947 'instance' => 0, 1948 'visible' => 1, 1949 'name' => 'Test', 1950 'timestart' => [ 1951 'day' => $timestart->format('j'), 1952 'month' => $timestart->format('n'), 1953 'year' => $timestart->format('Y'), 1954 'hour' => $timestart->format('G'), 1955 'minute' => 0, 1956 ], 1957 'eventtype' => 'user', 1958 'description' => [ 1959 'text' => '', 1960 'format' => 1, 1961 ], 1962 'location' => 'Test', 1963 'duration' => 1, 1964 'timedurationuntil' => [ 1965 'day' => $timedurationuntil->format('j'), 1966 'month' => $timedurationuntil->format('n'), 1967 'year' => $timedurationuntil->format('Y'), 1968 'hour' => $timedurationuntil->format('G'), 1969 'minute' => 0, 1970 ] 1971 ]; 1972 1973 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 1974 $querystring = http_build_query($formdata, '', '&'); 1975 1976 $generator->role_assign($roleid, $user->id, $context->id); 1977 assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true); 1978 1979 $user->ignoresesskey = true; 1980 $this->resetAfterTest(true); 1981 $this->setUser($user); 1982 1983 $this->expectException(\moodle_exception::class); 1984 1985 \external_api::clean_returnvalue( 1986 core_calendar_external::submit_create_update_form_returns(), 1987 core_calendar_external::submit_create_update_form($querystring) 1988 ); 1989 } 1990 1991 /** 1992 * A user with the moodle/calendar:manageentries capability at the 1993 * site course context should be able to create a site event. 1994 */ 1995 public function test_submit_create_update_form_create_site_event() { 1996 $generator = $this->getDataGenerator(); 1997 $user = $generator->create_user(); 1998 $context = \context_system::instance(); 1999 $roleid = $generator->create_role(); 2000 $timestart = new \DateTime(); 2001 $interval = new \DateInterval("P1D"); // One day. 2002 $timedurationuntil = new \DateTime(); 2003 $timedurationuntil->add($interval); 2004 $formdata = [ 2005 'id' => 0, 2006 'userid' => $user->id, 2007 'modulename' => '', 2008 'instance' => 0, 2009 'visible' => 1, 2010 'name' => 'Test', 2011 'timestart' => [ 2012 'day' => $timestart->format('j'), 2013 'month' => $timestart->format('n'), 2014 'year' => $timestart->format('Y'), 2015 'hour' => $timestart->format('G'), 2016 'minute' => 0, 2017 ], 2018 'eventtype' => 'site', 2019 'description' => [ 2020 'text' => '', 2021 'format' => 1, 2022 'itemid' => 0 2023 ], 2024 'location' => 'Test', 2025 'duration' => 1, 2026 'timedurationuntil' => [ 2027 'day' => $timedurationuntil->format('j'), 2028 'month' => $timedurationuntil->format('n'), 2029 'year' => $timedurationuntil->format('Y'), 2030 'hour' => $timedurationuntil->format('G'), 2031 'minute' => 0, 2032 ] 2033 ]; 2034 2035 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2036 $querystring = http_build_query($formdata, '', '&'); 2037 2038 $generator->role_assign($roleid, $user->id, $context->id); 2039 2040 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 2041 2042 $user->ignoresesskey = true; 2043 $this->resetAfterTest(true); 2044 $this->setUser($user); 2045 2046 $result = \external_api::clean_returnvalue( 2047 core_calendar_external::submit_create_update_form_returns(), 2048 core_calendar_external::submit_create_update_form($querystring) 2049 ); 2050 2051 $event = $result['event']; 2052 $this->assertEquals($user->id, $event['userid']); 2053 $this->assertEquals($formdata['eventtype'], $event['eventtype']); 2054 $this->assertEquals($formdata['name'], $event['name']); 2055 } 2056 2057 /** 2058 * A user without the moodle/calendar:manageentries capability at the 2059 * site course context should not be able to create a site event. 2060 */ 2061 public function test_submit_create_update_form_create_site_event_no_permission() { 2062 $generator = $this->getDataGenerator(); 2063 $user = $generator->create_user(); 2064 $context = \context_course::instance(SITEID); 2065 $roleid = $generator->create_role(); 2066 $timestart = new \DateTime(); 2067 $interval = new \DateInterval("P1D"); // One day. 2068 $timedurationuntil = new \DateTime(); 2069 $timedurationuntil->add($interval); 2070 $formdata = [ 2071 'id' => 0, 2072 'userid' => $user->id, 2073 'modulename' => '', 2074 'instance' => 0, 2075 'visible' => 1, 2076 'name' => 'Test', 2077 'timestart' => [ 2078 'day' => $timestart->format('j'), 2079 'month' => $timestart->format('n'), 2080 'year' => $timestart->format('Y'), 2081 'hour' => $timestart->format('G'), 2082 'minute' => 0, 2083 ], 2084 'eventtype' => 'site', 2085 'description' => [ 2086 'text' => '', 2087 'format' => 1, 2088 ], 2089 'location' => 'Test', 2090 'duration' => 1, 2091 'timedurationuntil' => [ 2092 'day' => $timedurationuntil->format('j'), 2093 'month' => $timedurationuntil->format('n'), 2094 'year' => $timedurationuntil->format('Y'), 2095 'hour' => $timedurationuntil->format('G'), 2096 'minute' => 0, 2097 ] 2098 ]; 2099 2100 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2101 $querystring = http_build_query($formdata, '', '&'); 2102 2103 $generator->role_assign($roleid, $user->id, $context->id); 2104 2105 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true); 2106 2107 $user->ignoresesskey = true; 2108 $this->resetAfterTest(true); 2109 $this->setUser($user); 2110 2111 $result = \external_api::clean_returnvalue( 2112 core_calendar_external::submit_create_update_form_returns(), 2113 core_calendar_external::submit_create_update_form($querystring) 2114 ); 2115 2116 $this->assertTrue($result['validationerror']); 2117 } 2118 2119 /** 2120 * A user that has the moodle/calendar:manageentries in a course that they 2121 * are enrolled in should be able to create a course event in that course. 2122 */ 2123 public function test_submit_create_update_form_create_course_event() { 2124 $generator = $this->getDataGenerator(); 2125 $user = $generator->create_user(); 2126 $course = $generator->create_course(); 2127 $context = \context_course::instance($course->id); 2128 $roleid = $generator->create_role(); 2129 $timestart = new \DateTime(); 2130 $interval = new \DateInterval("P1D"); // One day. 2131 $timedurationuntil = new \DateTime(); 2132 $timedurationuntil->add($interval); 2133 $formdata = [ 2134 'id' => 0, 2135 'userid' => $user->id, 2136 'modulename' => '', 2137 'instance' => 0, 2138 'visible' => 1, 2139 'name' => 'Test', 2140 'timestart' => [ 2141 'day' => $timestart->format('j'), 2142 'month' => $timestart->format('n'), 2143 'year' => $timestart->format('Y'), 2144 'hour' => $timestart->format('G'), 2145 'minute' => 0, 2146 ], 2147 'eventtype' => 'course', 2148 'courseid' => $course->id, 2149 'description' => [ 2150 'text' => '', 2151 'format' => 1, 2152 'itemid' => 0, 2153 ], 2154 'location' => 'Test', 2155 'duration' => 1, 2156 'timedurationuntil' => [ 2157 'day' => $timedurationuntil->format('j'), 2158 'month' => $timedurationuntil->format('n'), 2159 'year' => $timedurationuntil->format('Y'), 2160 'hour' => $timedurationuntil->format('G'), 2161 'minute' => 0, 2162 ] 2163 ]; 2164 2165 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2166 $querystring = http_build_query($formdata, '', '&'); 2167 2168 $generator->enrol_user($user->id, $course->id, 'student'); 2169 $generator->role_assign($roleid, $user->id, $context->id); 2170 2171 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 2172 2173 $user->ignoresesskey = true; 2174 $this->resetAfterTest(true); 2175 $this->setUser($user); 2176 2177 $result = \external_api::clean_returnvalue( 2178 core_calendar_external::submit_create_update_form_returns(), 2179 core_calendar_external::submit_create_update_form($querystring) 2180 ); 2181 2182 $event = $result['event']; 2183 $this->assertEquals($user->id, $event['userid']); 2184 $this->assertEquals($formdata['eventtype'], $event['eventtype']); 2185 $this->assertEquals($formdata['name'], $event['name']); 2186 $this->assertEquals($formdata['courseid'], $event['course']['id']); 2187 } 2188 2189 /** 2190 * A user without the moodle/calendar:manageentries capability in a course 2191 * that they are enrolled in should not be able to create a course event in that course. 2192 */ 2193 public function test_submit_create_update_form_create_course_event_no_permission() { 2194 $generator = $this->getDataGenerator(); 2195 $user = $generator->create_user(); 2196 $course = $generator->create_course(); 2197 $context = \context_course::instance($course->id); 2198 $roleid = $generator->create_role(); 2199 $timestart = new \DateTime(); 2200 $interval = new \DateInterval("P1D"); // One day. 2201 $timedurationuntil = new \DateTime(); 2202 $timedurationuntil->add($interval); 2203 $formdata = [ 2204 'id' => 0, 2205 'userid' => $user->id, 2206 'modulename' => '', 2207 'instance' => 0, 2208 'visible' => 1, 2209 'name' => 'Test', 2210 'timestart' => [ 2211 'day' => $timestart->format('j'), 2212 'month' => $timestart->format('n'), 2213 'year' => $timestart->format('Y'), 2214 'hour' => $timestart->format('G'), 2215 'minute' => 0, 2216 ], 2217 'eventtype' => 'course', 2218 'courseid' => $course->id, 2219 'description' => [ 2220 'text' => '', 2221 'format' => 1, 2222 ], 2223 'location' => 'Test', 2224 'duration' => 1, 2225 'timedurationuntil' => [ 2226 'day' => $timedurationuntil->format('j'), 2227 'month' => $timedurationuntil->format('n'), 2228 'year' => $timedurationuntil->format('Y'), 2229 'hour' => $timedurationuntil->format('G'), 2230 'minute' => 0, 2231 ] 2232 ]; 2233 2234 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2235 $querystring = http_build_query($formdata, '', '&'); 2236 2237 $generator->enrol_user($user->id, $course->id, 'student'); 2238 $generator->role_assign($roleid, $user->id, $context->id); 2239 2240 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true); 2241 2242 $user->ignoresesskey = true; 2243 $this->resetAfterTest(true); 2244 $this->setUser($user); 2245 2246 $result = \external_api::clean_returnvalue( 2247 core_calendar_external::submit_create_update_form_returns(), 2248 core_calendar_external::submit_create_update_form($querystring) 2249 ); 2250 2251 $this->assertTrue($result['validationerror']); 2252 } 2253 2254 /** 2255 * A user should not be able to create an event for a course that they are 2256 * not enrolled in. 2257 */ 2258 public function test_submit_create_update_form_create_course_event_not_enrolled() { 2259 $generator = $this->getDataGenerator(); 2260 $user = $generator->create_user(); 2261 $course = $generator->create_course(); 2262 $course2 = $generator->create_course(); 2263 $context = \context_course::instance($course->id); 2264 $roleid = $generator->create_role(); 2265 $timestart = new \DateTime(); 2266 $interval = new \DateInterval("P1D"); // One day. 2267 $timedurationuntil = new \DateTime(); 2268 $timedurationuntil->add($interval); 2269 $formdata = [ 2270 'id' => 0, 2271 'userid' => $user->id, 2272 'modulename' => '', 2273 'instance' => 0, 2274 'visible' => 1, 2275 'name' => 'Test', 2276 'timestart' => [ 2277 'day' => $timestart->format('j'), 2278 'month' => $timestart->format('n'), 2279 'year' => $timestart->format('Y'), 2280 'hour' => $timestart->format('G'), 2281 'minute' => 0, 2282 ], 2283 'eventtype' => 'course', 2284 'courseid' => $course2->id, // Not enrolled. 2285 'description' => [ 2286 'text' => '', 2287 'format' => 1, 2288 ], 2289 'location' => 'Test', 2290 'duration' => 1, 2291 'timedurationuntil' => [ 2292 'day' => $timedurationuntil->format('j'), 2293 'month' => $timedurationuntil->format('n'), 2294 'year' => $timedurationuntil->format('Y'), 2295 'hour' => $timedurationuntil->format('G'), 2296 'minute' => 0, 2297 ] 2298 ]; 2299 2300 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2301 $querystring = http_build_query($formdata, '', '&'); 2302 2303 $generator->enrol_user($user->id, $course->id, 'student'); 2304 $generator->role_assign($roleid, $user->id, $context->id); 2305 2306 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 2307 2308 $user->ignoresesskey = true; 2309 $this->resetAfterTest(true); 2310 $this->setUser($user); 2311 2312 $result = \external_api::clean_returnvalue( 2313 core_calendar_external::submit_create_update_form_returns(), 2314 core_calendar_external::submit_create_update_form($querystring) 2315 ); 2316 2317 $this->assertTrue($result['validationerror']); 2318 } 2319 2320 /** 2321 * A user should be able to create an event for a group that they are a member of in 2322 * a course in which they are enrolled and have the moodle/calendar:manageentries capability. 2323 */ 2324 public function test_submit_create_update_form_create_group_event_group_member_manage_course() { 2325 $generator = $this->getDataGenerator(); 2326 $user = $generator->create_user(); 2327 $course = $generator->create_course(); 2328 $group = $generator->create_group(array('courseid' => $course->id)); 2329 $context = \context_course::instance($course->id); 2330 $roleid = $generator->create_role(); 2331 $timestart = new \DateTime(); 2332 $interval = new \DateInterval("P1D"); // One day. 2333 $timedurationuntil = new \DateTime(); 2334 $timedurationuntil->add($interval); 2335 $formdata = [ 2336 'id' => 0, 2337 'userid' => $user->id, 2338 'modulename' => '', 2339 'instance' => 0, 2340 'visible' => 1, 2341 'name' => 'Test', 2342 'timestart' => [ 2343 'day' => $timestart->format('j'), 2344 'month' => $timestart->format('n'), 2345 'year' => $timestart->format('Y'), 2346 'hour' => $timestart->format('G'), 2347 'minute' => 0, 2348 ], 2349 'eventtype' => 'group', 2350 'groupid' => $group->id, 2351 'groupcourseid' => $course->id, 2352 'description' => [ 2353 'text' => '', 2354 'format' => 1, 2355 'itemid' => 0 2356 ], 2357 'location' => 'Test', 2358 'duration' => 1, 2359 'timedurationuntil' => [ 2360 'day' => $timedurationuntil->format('j'), 2361 'month' => $timedurationuntil->format('n'), 2362 'year' => $timedurationuntil->format('Y'), 2363 'hour' => $timedurationuntil->format('G'), 2364 'minute' => 0, 2365 ] 2366 ]; 2367 2368 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2369 $querystring = http_build_query($formdata, '', '&'); 2370 2371 $generator->enrol_user($user->id, $course->id, 'student'); 2372 $generator->role_assign($roleid, $user->id, $context->id); 2373 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]); 2374 2375 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 2376 2377 $user->ignoresesskey = true; 2378 $this->resetAfterTest(true); 2379 $this->setUser($user); 2380 2381 $result = \external_api::clean_returnvalue( 2382 core_calendar_external::submit_create_update_form_returns(), 2383 core_calendar_external::submit_create_update_form($querystring) 2384 ); 2385 2386 $event = $result['event']; 2387 $this->assertEquals($user->id, $event['userid']); 2388 $this->assertEquals($formdata['eventtype'], $event['eventtype']); 2389 $this->assertEquals($formdata['name'], $event['name']); 2390 $this->assertEquals($group->id, $event['groupid']); 2391 } 2392 2393 /** 2394 * A user should be able to create an event for a group that they are a member of in 2395 * a course in which they are enrolled and have the moodle/calendar:managegroupentries capability. 2396 */ 2397 public function test_submit_create_update_form_create_group_event_group_member_manage_group_entries() { 2398 $generator = $this->getDataGenerator(); 2399 $user = $generator->create_user(); 2400 $course = $generator->create_course(); 2401 $group = $generator->create_group(array('courseid' => $course->id)); 2402 $context = \context_course::instance($course->id); 2403 $roleid = $generator->create_role(); 2404 $timestart = new \DateTime(); 2405 $interval = new \DateInterval("P1D"); // One day. 2406 $timedurationuntil = new \DateTime(); 2407 $timedurationuntil->add($interval); 2408 $formdata = [ 2409 'id' => 0, 2410 'userid' => $user->id, 2411 'modulename' => '', 2412 'instance' => 0, 2413 'visible' => 1, 2414 'name' => 'Test', 2415 'timestart' => [ 2416 'day' => $timestart->format('j'), 2417 'month' => $timestart->format('n'), 2418 'year' => $timestart->format('Y'), 2419 'hour' => $timestart->format('G'), 2420 'minute' => 0, 2421 ], 2422 'eventtype' => 'group', 2423 'groupid' => $group->id, 2424 'groupcourseid' => $course->id, 2425 'description' => [ 2426 'text' => '', 2427 'format' => 1, 2428 'itemid' => 0 2429 ], 2430 'location' => 'Test', 2431 'duration' => 1, 2432 'timedurationuntil' => [ 2433 'day' => $timedurationuntil->format('j'), 2434 'month' => $timedurationuntil->format('n'), 2435 'year' => $timedurationuntil->format('Y'), 2436 'hour' => $timedurationuntil->format('G'), 2437 'minute' => 0, 2438 ] 2439 ]; 2440 2441 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2442 $querystring = http_build_query($formdata, '', '&'); 2443 2444 $generator->enrol_user($user->id, $course->id, 'student'); 2445 $generator->role_assign($roleid, $user->id, $context->id); 2446 $generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]); 2447 2448 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true); 2449 assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true); 2450 2451 $user->ignoresesskey = true; 2452 $this->resetAfterTest(true); 2453 $this->setUser($user); 2454 2455 $result = \external_api::clean_returnvalue( 2456 core_calendar_external::submit_create_update_form_returns(), 2457 core_calendar_external::submit_create_update_form($querystring) 2458 ); 2459 2460 $event = $result['event']; 2461 $this->assertEquals($user->id, $event['userid']); 2462 $this->assertEquals($formdata['eventtype'], $event['eventtype']); 2463 $this->assertEquals($formdata['name'], $event['name']); 2464 $this->assertEquals($group->id, $event['groupid']); 2465 } 2466 2467 /** 2468 * A user should be able to create an event for any group in a course in which 2469 * they are enrolled and have the moodle/site:accessallgroups capability. 2470 */ 2471 public function test_submit_create_update_form_create_group_event_access_all_groups() { 2472 $generator = $this->getDataGenerator(); 2473 $user = $generator->create_user(); 2474 $course = $generator->create_course(); 2475 $group = $generator->create_group(array('courseid' => $course->id)); 2476 $context = \context_course::instance($course->id); 2477 $roleid = $generator->create_role(); 2478 $timestart = new \DateTime(); 2479 $interval = new \DateInterval("P1D"); // One day. 2480 $timedurationuntil = new \DateTime(); 2481 $timedurationuntil->add($interval); 2482 $formdata = [ 2483 'id' => 0, 2484 'userid' => $user->id, 2485 'modulename' => '', 2486 'instance' => 0, 2487 'visible' => 1, 2488 'name' => 'Test', 2489 'timestart' => [ 2490 'day' => $timestart->format('j'), 2491 'month' => $timestart->format('n'), 2492 'year' => $timestart->format('Y'), 2493 'hour' => $timestart->format('G'), 2494 'minute' => 0, 2495 ], 2496 'eventtype' => 'group', 2497 'groupid' => $group->id, 2498 'groupcourseid' => $course->id, 2499 'description' => [ 2500 'text' => '', 2501 'format' => 1, 2502 'itemid' => 0 2503 ], 2504 'location' => 'Test', 2505 'duration' => 1, 2506 'timedurationuntil' => [ 2507 'day' => $timedurationuntil->format('j'), 2508 'month' => $timedurationuntil->format('n'), 2509 'year' => $timedurationuntil->format('Y'), 2510 'hour' => $timedurationuntil->format('G'), 2511 'minute' => 0, 2512 ] 2513 ]; 2514 2515 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2516 $querystring = http_build_query($formdata, '', '&'); 2517 2518 $generator->enrol_user($user->id, $course->id, 'student'); 2519 $generator->role_assign($roleid, $user->id, $context->id); 2520 2521 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 2522 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true); 2523 2524 $user->ignoresesskey = true; 2525 $this->resetAfterTest(true); 2526 $this->setUser($user); 2527 2528 $result = \external_api::clean_returnvalue( 2529 core_calendar_external::submit_create_update_form_returns(), 2530 core_calendar_external::submit_create_update_form($querystring) 2531 ); 2532 2533 $event = $result['event']; 2534 $this->assertEquals($user->id, $event['userid']); 2535 $this->assertEquals($formdata['eventtype'], $event['eventtype']); 2536 $this->assertEquals($formdata['name'], $event['name']); 2537 $this->assertEquals($group->id, $event['groupid']); 2538 } 2539 2540 /** 2541 * A user should not be able to create an event for any group that they are not a 2542 * member of in a course in which they are enrolled but don't have the 2543 * moodle/site:accessallgroups capability. 2544 */ 2545 public function test_submit_create_update_form_create_group_event_non_member_no_permission() { 2546 $generator = $this->getDataGenerator(); 2547 $user = $generator->create_user(); 2548 $course = $generator->create_course(); 2549 $group = $generator->create_group(array('courseid' => $course->id)); 2550 $context = \context_course::instance($course->id); 2551 $roleid = $generator->create_role(); 2552 $timestart = new \DateTime(); 2553 $interval = new \DateInterval("P1D"); // One day. 2554 $timedurationuntil = new \DateTime(); 2555 $timedurationuntil->add($interval); 2556 $formdata = [ 2557 'id' => 0, 2558 'userid' => $user->id, 2559 'modulename' => '', 2560 'instance' => 0, 2561 'visible' => 1, 2562 'name' => 'Test', 2563 'timestart' => [ 2564 'day' => $timestart->format('j'), 2565 'month' => $timestart->format('n'), 2566 'year' => $timestart->format('Y'), 2567 'hour' => $timestart->format('G'), 2568 'minute' => 0, 2569 ], 2570 'eventtype' => 'group', 2571 'groupid' => $group->id, 2572 'groupcourseid' => $course->id, 2573 'description' => [ 2574 'text' => '', 2575 'format' => 1, 2576 ], 2577 'location' => 'Test', 2578 'duration' => 1, 2579 'timedurationuntil' => [ 2580 'day' => $timedurationuntil->format('j'), 2581 'month' => $timedurationuntil->format('n'), 2582 'year' => $timedurationuntil->format('Y'), 2583 'hour' => $timedurationuntil->format('G'), 2584 'minute' => 0, 2585 ] 2586 ]; 2587 2588 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2589 $querystring = http_build_query($formdata, '', '&'); 2590 2591 $generator->enrol_user($user->id, $course->id, 'student'); 2592 $generator->role_assign($roleid, $user->id, $context->id); 2593 2594 assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true); 2595 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true); 2596 2597 $user->ignoresesskey = true; 2598 $this->resetAfterTest(true); 2599 $this->setUser($user); 2600 2601 $result = \external_api::clean_returnvalue( 2602 core_calendar_external::submit_create_update_form_returns(), 2603 core_calendar_external::submit_create_update_form($querystring) 2604 ); 2605 2606 $this->assertTrue($result['validationerror']); 2607 } 2608 2609 /** 2610 * A user should not be able load the calendar monthly view for a course they cannot access. 2611 */ 2612 public function test_get_calendar_monthly_view_no_course_permission() { 2613 global $USER; 2614 $this->resetAfterTest(true); 2615 $this->setAdminUser(); 2616 2617 $generator = $this->getDataGenerator(); 2618 $user1 = $generator->create_user(); 2619 $user2 = $generator->create_user(); 2620 $course = $generator->create_course(); 2621 $generator->enrol_user($user1->id, $course->id, 'student'); 2622 $name = 'Course Event (course' . $course->id . ')'; 2623 $record = new \stdClass(); 2624 $record->courseid = $course->id; 2625 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record); 2626 2627 $timestart = new \DateTime(); 2628 // Admin can load the course. 2629 $data = \external_api::clean_returnvalue( 2630 core_calendar_external::get_calendar_monthly_view_returns(), 2631 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'), 2632 $course->id, null, false, true, $timestart->format('j')) 2633 ); 2634 $this->assertEquals($data['courseid'], $course->id); 2635 // User enrolled in the course can load the course calendar. 2636 $this->setUser($user1); 2637 $data = \external_api::clean_returnvalue( 2638 core_calendar_external::get_calendar_monthly_view_returns(), 2639 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'), 2640 $course->id, null, false, true, $timestart->format('j')) 2641 ); 2642 $this->assertEquals($data['courseid'], $course->id); 2643 // User not enrolled in the course cannot load the course calendar. 2644 $this->setUser($user2); 2645 $this->expectException(\require_login_exception::class); 2646 $data = \external_api::clean_returnvalue( 2647 core_calendar_external::get_calendar_monthly_view_returns(), 2648 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'), 2649 $course->id, null, false, false, $timestart->format('j')) 2650 ); 2651 } 2652 2653 /** 2654 * Test get_calendar_monthly_view when a day parameter is provided. 2655 */ 2656 public function test_get_calendar_monthly_view_with_day_provided() { 2657 $this->resetAfterTest(); 2658 $this->setAdminUser(); 2659 2660 $timestart = new \DateTime(); 2661 $data = \external_api::clean_returnvalue( 2662 core_calendar_external::get_calendar_monthly_view_returns(), 2663 core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'), 2664 SITEID, null, false, true, $timestart->format('j')) 2665 ); 2666 $this->assertEquals($data['date']['mday'], $timestart->format('d')); 2667 } 2668 2669 /** 2670 * A user should not be able load the calendar day view for a course they cannot access. 2671 */ 2672 public function test_get_calendar_day_view_no_course_permission() { 2673 global $USER; 2674 $this->resetAfterTest(true); 2675 $this->setAdminUser(); 2676 2677 $generator = $this->getDataGenerator(); 2678 $user1 = $generator->create_user(); 2679 $user2 = $generator->create_user(); 2680 $course = $generator->create_course(); 2681 $generator->enrol_user($user1->id, $course->id, 'student'); 2682 $name = 'Course Event (course' . $course->id . ')'; 2683 $record = new \stdClass(); 2684 $record->courseid = $course->id; 2685 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record); 2686 2687 $timestart = new \DateTime(); 2688 // Admin can load the course. 2689 $data = \external_api::clean_returnvalue( 2690 core_calendar_external::get_calendar_day_view_returns(), 2691 core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'), 2692 $timestart->format('j'), $course->id, null) 2693 ); 2694 $this->assertEquals($data['courseid'], $course->id); 2695 // User enrolled in the course can load the course calendar. 2696 $this->setUser($user1); 2697 $data = \external_api::clean_returnvalue( 2698 core_calendar_external::get_calendar_day_view_returns(), 2699 core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'), 2700 $timestart->format('j'), $course->id, null) 2701 ); 2702 $this->assertEquals($data['courseid'], $course->id); 2703 // User not enrolled in the course cannot load the course calendar. 2704 $this->setUser($user2); 2705 $this->expectException(\require_login_exception::class); 2706 $data = \external_api::clean_returnvalue( 2707 core_calendar_external::get_calendar_day_view_returns(), 2708 core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'), 2709 $timestart->format('j'), $course->id, null) 2710 ); 2711 } 2712 2713 /** 2714 * A user should not be able load the calendar upcoming view for a course they cannot access. 2715 */ 2716 public function test_get_calendar_upcoming_view_no_course_permission() { 2717 global $USER; 2718 $this->resetAfterTest(true); 2719 $this->setAdminUser(); 2720 2721 $generator = $this->getDataGenerator(); 2722 $user1 = $generator->create_user(); 2723 $user2 = $generator->create_user(); 2724 $course = $generator->create_course(); 2725 $generator->enrol_user($user1->id, $course->id, 'student'); 2726 $name = 'Course Event (course' . $course->id . ')'; 2727 $record = new \stdClass(); 2728 $record->courseid = $course->id; 2729 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record); 2730 2731 // Admin can load the course. 2732 $data = \external_api::clean_returnvalue( 2733 core_calendar_external::get_calendar_upcoming_view_returns(), 2734 core_calendar_external::get_calendar_upcoming_view($course->id, null) 2735 ); 2736 $this->assertEquals($data['courseid'], $course->id); 2737 // User enrolled in the course can load the course calendar. 2738 $this->setUser($user1); 2739 $data = \external_api::clean_returnvalue( 2740 core_calendar_external::get_calendar_upcoming_view_returns(), 2741 core_calendar_external::get_calendar_upcoming_view($course->id, null) 2742 ); 2743 $this->assertEquals($data['courseid'], $course->id); 2744 // User not enrolled in the course cannot load the course calendar. 2745 $this->setUser($user2); 2746 $this->expectException(\require_login_exception::class); 2747 $data = \external_api::clean_returnvalue( 2748 core_calendar_external::get_calendar_upcoming_view_returns(), 2749 core_calendar_external::get_calendar_upcoming_view($course->id, null) 2750 ); 2751 } 2752 2753 /** 2754 * A user should not be able load the calendar event for a course they cannot access. 2755 */ 2756 public function test_get_calendar_event_by_id_no_course_permission() { 2757 global $USER; 2758 $this->resetAfterTest(true); 2759 $this->setAdminUser(); 2760 2761 $generator = $this->getDataGenerator(); 2762 $user1 = $generator->create_user(); 2763 $user2 = $generator->create_user(); 2764 $course = $generator->create_course(); 2765 $generator->enrol_user($user1->id, $course->id, 'student'); 2766 $name = 'Course Event (course' . $course->id . ')'; 2767 $record = new \stdClass(); 2768 $record->courseid = $course->id; 2769 $courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record); 2770 2771 // Admin can load the course event. 2772 $data = \external_api::clean_returnvalue( 2773 core_calendar_external::get_calendar_event_by_id_returns(), 2774 core_calendar_external::get_calendar_event_by_id($courseevent->id) 2775 ); 2776 $this->assertEquals($data['event']['id'], $courseevent->id); 2777 // User enrolled in the course can load the course event. 2778 $this->setUser($user1); 2779 $data = \external_api::clean_returnvalue( 2780 core_calendar_external::get_calendar_event_by_id_returns(), 2781 core_calendar_external::get_calendar_event_by_id($courseevent->id) 2782 ); 2783 $this->assertEquals($data['event']['id'], $courseevent->id); 2784 // User not enrolled in the course cannot load the course event. 2785 $this->setUser($user2); 2786 $this->expectException(\moodle_exception::class); 2787 $data = \external_api::clean_returnvalue( 2788 core_calendar_external::get_calendar_event_by_id_returns(), 2789 core_calendar_external::get_calendar_event_by_id($courseevent->id) 2790 ); 2791 } 2792 2793 /** 2794 * User data for testing reading calendar events. 2795 * 2796 * @return array 2797 */ 2798 public function get_calendar_event_by_id_prevent_read_other_users_events_data_provider(): array { 2799 $syscontext = \context_system::instance(); 2800 $managerrole = 'manager'; 2801 return [ 2802 [true, false, $syscontext, $managerrole, true], 2803 [false, false, $syscontext, $managerrole, false], 2804 [false, false, null, null, true], 2805 [false, true, null, null, false], 2806 ]; 2807 } 2808 2809 /** 2810 * Prevent user from reading other user's event. 2811 * 2812 * @covers \core_calendar_external::get_calendar_event_by_id 2813 * @dataProvider get_calendar_event_by_id_prevent_read_other_users_events_data_provider 2814 * 2815 * @param bool $isadminevent Is admin's event 2816 * @param bool $isadmin Is current user admin user 2817 * @param null|stdClass $readerrolecontext Reader role context 2818 * @param null|string $readerrolename Role name 2819 * @param bool $expectexception Should the test throw exception 2820 */ 2821 public function test_get_calendar_event_by_id_prevent_read_other_users_events( 2822 bool $isadminevent, bool $isadmin, ?\stdClass $readerrolecontext, 2823 ?string $readerrolename, bool $expectexception) { 2824 global $USER, $DB; 2825 2826 $this->resetAfterTest(); 2827 $generator = $this->getDataGenerator(); 2828 2829 if ($isadminevent) { 2830 $this->setAdminUser(); 2831 } else { 2832 $user = $generator->create_user(); 2833 $this->setUser($user); 2834 } 2835 $userevent = $this->create_calendar_event('user event', $USER->id, 'user', 0, time()); 2836 $results = \external_api::clean_returnvalue( 2837 core_calendar_external::get_calendar_event_by_id_returns(), 2838 core_calendar_external::get_calendar_event_by_id($userevent->id) 2839 ); 2840 $event = reset($results); 2841 $this->assertEquals($userevent->id, $event['id']); 2842 2843 if ($isadmin) { 2844 $this->setAdminUser(); 2845 } else { 2846 $reader = $generator->create_user(); 2847 if ($readerrolename && $readerrolecontext) { 2848 $managerroleid = $DB->get_field('role', 'id', ['shortname' => $readerrolename]); 2849 role_assign($managerroleid, $reader->id, $readerrolecontext->id); 2850 } 2851 $this->setUser($reader); 2852 } 2853 2854 if ($expectexception) { 2855 // Setup if exception is expected for the test. 2856 $this->expectException(\moodle_exception::class); 2857 } 2858 \external_api::clean_returnvalue( 2859 core_calendar_external::get_calendar_event_by_id_returns(), 2860 core_calendar_external::get_calendar_event_by_id($userevent->id) 2861 ); 2862 } 2863 2864 /** 2865 * User data for testing editing or deleting calendar events. 2866 * 2867 * @return array 2868 */ 2869 public function edit_or_delete_other_users_events_data_provider(): array { 2870 $syscontext = \context_system::instance(); 2871 $managerrole = 'manager'; 2872 return [ 2873 [false, false, $syscontext, $managerrole, false], 2874 [false, true, $syscontext, $managerrole, true], 2875 [false, false, null, null, true], 2876 [true, false, null, null, false], 2877 ]; 2878 } 2879 2880 /** 2881 * Test the behavior of deleting other users' user events. 2882 * 2883 * @dataProvider edit_or_delete_other_users_events_data_provider 2884 * @covers \core_calendar_external::delete_calendar_events 2885 * @param bool $isadmin Whether the current user is admin. 2886 * @param bool $isadminevent Whether it's an admin event or not. 2887 * @param stdClass|null $writerrolecontext The reader role context. 2888 * @param string|null $writerrolename The role name. 2889 * @param bool $expectexception Whether the test should throw an exception or not. 2890 */ 2891 public function test_delete_other_users_events(bool $isadmin, bool $isadminevent, 2892 ?\stdClass $writerrolecontext, ?string $writerrolename, bool $expectexception) { 2893 global $DB, $USER; 2894 2895 $this->resetAfterTest(); 2896 $generator = $this->getDataGenerator(); 2897 2898 if ($isadminevent) { 2899 $this->setAdminUser(); 2900 $user = $USER; 2901 } else { 2902 $user = $generator->create_user(); 2903 $this->setUser($user); 2904 } 2905 $userevent = $this->create_calendar_event('user event', $user->id, 'user', 0, time()); 2906 2907 if ($isadmin) { 2908 $this->setAdminUser(); 2909 } else { 2910 $writer = $generator->create_user(); 2911 if ($writerrolename && $writerrolecontext) { 2912 $managerroleid = $DB->get_field('role', 'id', ['shortname' => $writerrolename]); 2913 role_assign($managerroleid, $writer->id, $writerrolecontext->id); 2914 } 2915 $this->setUser($writer); 2916 } 2917 2918 if ($expectexception) { 2919 $this->expectException(\moodle_exception::class); 2920 } 2921 $events = [ 2922 ['eventid' => $userevent->id, 'repeat' => 0] 2923 ]; 2924 core_calendar_external::delete_calendar_events($events); 2925 } 2926 2927 /** 2928 * Test the behavior of editing other users' user events 2929 * 2930 * @dataProvider edit_or_delete_other_users_events_data_provider 2931 * @covers \core_calendar_external::submit_create_update_form 2932 * @param bool $isadmin Whether the current user is admin. 2933 * @param bool $isadminevent Whether it's an admin event or not. 2934 * @param stdClass|null $writerrolecontext The reader role context. 2935 * @param string|null $writerrolename The role name. 2936 * @param bool $expectexception Whether the test should throw an exception or not. 2937 */ 2938 public function test_edit_other_users_events(bool $isadmin, bool $isadminevent, 2939 ?\stdClass $writerrolecontext, ?string $writerrolename, bool $expectexception) { 2940 global $DB, $USER; 2941 2942 $this->resetAfterTest(); 2943 2944 $generator = $this->getDataGenerator(); 2945 if ($isadminevent) { 2946 $this->setAdminUser(); 2947 $user = $USER; 2948 } else { 2949 $user = $generator->create_user(); 2950 } 2951 2952 $formdata = [ 2953 'id' => 0, 2954 'userid' => $user->id, 2955 'modulename' => '', 2956 'instance' => 0, 2957 'visible' => 1, 2958 'eventtype' => 'user', 2959 'name' => 'Test', 2960 'timestart' => [ 2961 'day' => 1, 2962 'month' => 1, 2963 'year' => 2021, 2964 'hour' => 1, 2965 'minute' => 0, 2966 ], 2967 'description' => [ 2968 'text' => 'xxxxx', 2969 'format' => 1, 2970 'itemid' => 0 2971 ], 2972 'location' => 'Test', 2973 'duration' => 0, 2974 ]; 2975 $formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata); 2976 2977 $querystring = http_build_query($formdata, '', '&'); 2978 2979 if ($isadmin) { 2980 $this->setAdminUser(); 2981 } else { 2982 $writer = $generator->create_user(); 2983 if ($writerrolename && $writerrolecontext) { 2984 $managerroleid = $DB->get_field('role', 'id', ['shortname' => $writerrolename]); 2985 role_assign($managerroleid, $writer->id, $writerrolecontext->id); 2986 } 2987 $this->setUser($writer); 2988 } 2989 $USER->ignoresesskey = true; 2990 2991 if ($expectexception) { 2992 $this->expectException(\moodle_exception::class); 2993 } 2994 core_calendar_external::submit_create_update_form($querystring); 2995 } 2996 2997 /** 2998 * A user should not be able load the calendar events for a category they cannot see. 2999 */ 3000 public function test_get_calendar_events_hidden_category() { 3001 global $USER; 3002 $this->resetAfterTest(true); 3003 $this->setAdminUser(); 3004 3005 $generator = $this->getDataGenerator(); 3006 $user1 = $generator->create_user(); 3007 $category = $generator->create_category(['visible' => 0]); 3008 $name = 'Category Event (category: ' . $category->id . ')'; 3009 $record = new \stdClass(); 3010 $record->categoryid = $category->id; 3011 $categoryevent = $this->create_calendar_event($name, $USER->id, 'category', 0, time(), $record); 3012 3013 $events = [ 3014 'eventids' => [$categoryevent->id] 3015 ]; 3016 $options = []; 3017 // Admin can load the category event. 3018 $data = \external_api::clean_returnvalue( 3019 core_calendar_external::get_calendar_events_returns(), 3020 core_calendar_external::get_calendar_events($events, $options) 3021 ); 3022 $this->assertEquals($data['events'][0]['id'], $categoryevent->id); 3023 // User with no special permission to see hidden categories will not see the event. 3024 $this->setUser($user1); 3025 $data = \external_api::clean_returnvalue( 3026 core_calendar_external::get_calendar_events_returns(), 3027 core_calendar_external::get_calendar_events($events, $options) 3028 ); 3029 $this->assertCount(0, $data['events']); 3030 $this->assertEquals('nopermissions', $data['warnings'][0]['warningcode']); 3031 } 3032 3033 /** 3034 * Test get_calendar_access_information for admins. 3035 */ 3036 public function test_get_calendar_access_information_for_admins() { 3037 global $CFG; 3038 $this->resetAfterTest(true); 3039 $this->setAdminUser(); 3040 3041 $CFG->calendar_adminseesall = 1; 3042 3043 $data = \external_api::clean_returnvalue( 3044 core_calendar_external::get_calendar_access_information_returns(), 3045 core_calendar_external::get_calendar_access_information() 3046 ); 3047 $this->assertTrue($data['canmanageownentries']); 3048 $this->assertTrue($data['canmanagegroupentries']); 3049 $this->assertTrue($data['canmanageentries']); 3050 } 3051 3052 /** 3053 * Test get_calendar_access_information for authenticated users. 3054 */ 3055 public function test_get_calendar_access_information_for_authenticated_users() { 3056 $this->resetAfterTest(true); 3057 $this->setUser($this->getDataGenerator()->create_user()); 3058 3059 $data = \external_api::clean_returnvalue( 3060 core_calendar_external::get_calendar_access_information_returns(), 3061 core_calendar_external::get_calendar_access_information() 3062 ); 3063 $this->assertTrue($data['canmanageownentries']); 3064 $this->assertFalse($data['canmanagegroupentries']); 3065 $this->assertFalse($data['canmanageentries']); 3066 } 3067 3068 /** 3069 * Test get_calendar_access_information for student users. 3070 */ 3071 public function test_get_calendar_access_information_for_student_users() { 3072 global $DB; 3073 $this->resetAfterTest(true); 3074 3075 $user = $this->getDataGenerator()->create_user(); 3076 $course = $this->getDataGenerator()->create_course(); 3077 $role = $DB->get_record('role', array('shortname' => 'student')); 3078 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 3079 3080 $this->setUser($user); 3081 3082 $data = \external_api::clean_returnvalue( 3083 core_calendar_external::get_calendar_access_information_returns(), 3084 core_calendar_external::get_calendar_access_information($course->id) 3085 ); 3086 $this->assertTrue($data['canmanageownentries']); 3087 $this->assertFalse($data['canmanagegroupentries']); 3088 $this->assertFalse($data['canmanageentries']); 3089 } 3090 3091 /** 3092 * Test get_calendar_access_information for teacher users. 3093 */ 3094 public function test_get_calendar_access_information_for_teacher_users() { 3095 global $DB; 3096 $this->resetAfterTest(true); 3097 3098 $user = $this->getDataGenerator()->create_user(); 3099 $course = $this->getDataGenerator()->create_course(['groupmode' => 1]); 3100 $role = $DB->get_record('role', array('shortname' => 'editingteacher')); 3101 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 3102 $this->getDataGenerator()->create_group(['courseid' => $course->id]); 3103 3104 $this->setUser($user); 3105 3106 $data = \external_api::clean_returnvalue( 3107 core_calendar_external::get_calendar_access_information_returns(), 3108 core_calendar_external::get_calendar_access_information($course->id) 3109 ); 3110 $this->assertTrue($data['canmanageownentries']); 3111 $this->assertTrue($data['canmanagegroupentries']); 3112 $this->assertTrue($data['canmanageentries']); 3113 } 3114 3115 /** 3116 * Test get_allowed_event_types for admins. 3117 */ 3118 public function test_get_allowed_event_types_for_admins() { 3119 global $CFG; 3120 $this->resetAfterTest(true); 3121 $this->setAdminUser(); 3122 $CFG->calendar_adminseesall = 1; 3123 $data = \external_api::clean_returnvalue( 3124 core_calendar_external::get_allowed_event_types_returns(), 3125 core_calendar_external::get_allowed_event_types() 3126 ); 3127 $this->assertEquals(['user', 'site', 'course', 'category'], $data['allowedeventtypes']); 3128 } 3129 /** 3130 * Test get_allowed_event_types for authenticated users. 3131 */ 3132 public function test_get_allowed_event_types_for_authenticated_users() { 3133 $this->resetAfterTest(true); 3134 $this->setUser($this->getDataGenerator()->create_user()); 3135 $data = \external_api::clean_returnvalue( 3136 core_calendar_external::get_allowed_event_types_returns(), 3137 core_calendar_external::get_allowed_event_types() 3138 ); 3139 $this->assertEquals(['user'], $data['allowedeventtypes']); 3140 } 3141 /** 3142 * Test get_allowed_event_types for student users. 3143 */ 3144 public function test_get_allowed_event_types_for_student_users() { 3145 global $DB; 3146 $this->resetAfterTest(true); 3147 $user = $this->getDataGenerator()->create_user(); 3148 $course = $this->getDataGenerator()->create_course(); 3149 $role = $DB->get_record('role', array('shortname' => 'student')); 3150 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 3151 $this->setUser($user); 3152 $data = \external_api::clean_returnvalue( 3153 core_calendar_external::get_allowed_event_types_returns(), 3154 core_calendar_external::get_allowed_event_types($course->id) 3155 ); 3156 $this->assertEquals(['user'], $data['allowedeventtypes']); 3157 } 3158 /** 3159 * Test get_allowed_event_types for teacher users. 3160 */ 3161 public function test_get_allowed_event_types_for_teacher_users() { 3162 global $DB; 3163 $this->resetAfterTest(true); 3164 $user = $this->getDataGenerator()->create_user(); 3165 $course = $this->getDataGenerator()->create_course(['groupmode' => 1]); 3166 $role = $DB->get_record('role', array('shortname' => 'editingteacher')); 3167 $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); 3168 $this->getDataGenerator()->create_group(['courseid' => $course->id]); 3169 $this->setUser($user); 3170 $data = \external_api::clean_returnvalue( 3171 core_calendar_external::get_allowed_event_types_returns(), 3172 core_calendar_external::get_allowed_event_types($course->id) 3173 ); 3174 $this->assertEquals(['user', 'course', 'group'], $data['allowedeventtypes']); 3175 } 3176 3177 /** 3178 * Test get_timestamps with string keys, with and without optional hour/minute values. 3179 */ 3180 public function test_get_timestamps_string_keys() { 3181 $this->resetAfterTest(true); 3182 $this->setAdminUser(); 3183 3184 $time1 = new \DateTime('2018-12-30 00:00:00'); 3185 $time2 = new \DateTime('2019-03-27 23:59:00'); 3186 3187 $dates = [ 3188 [ 3189 'key' => 'from', 3190 'year' => $time1->format('Y'), 3191 'month' => $time1->format('m'), 3192 'day' => $time1->format('d'), 3193 ], 3194 [ 3195 'key' => 'to', 3196 'year' => $time2->format('Y'), 3197 'month' => (int) $time2->format('m'), 3198 'day' => $time2->format('d'), 3199 'hour' => $time2->format('H'), 3200 'minute' => $time2->format('i'), 3201 ], 3202 ]; 3203 3204 $expectedtimestamps = [ 3205 'from' => $time1->getTimestamp(), 3206 'to' => $time2->getTimestamp(), 3207 ]; 3208 3209 $result = core_calendar_external::get_timestamps($dates); 3210 3211 $this->assertEquals(['timestamps'], array_keys($result)); 3212 $this->assertEquals(2, count($result['timestamps'])); 3213 3214 foreach ($result['timestamps'] as $data) { 3215 $this->assertTrue(in_array($data['key'], ['from', 'to'])); 3216 $this->assertEquals($expectedtimestamps[$data['key']], $data['timestamp']); 3217 } 3218 } 3219 3220 /** 3221 * Test get_timestamps with no keys specified, with and without optional hour/minute values. 3222 */ 3223 public function test_get_timestamps_no_keys() { 3224 $this->resetAfterTest(true); 3225 $this->setAdminUser(); 3226 3227 $time1 = new \DateTime('2018-12-30 00:00:00'); 3228 $time2 = new \DateTime('2019-03-27 23:59:00'); 3229 3230 $dates = [ 3231 [ 3232 'year' => $time1->format('Y'), 3233 'month' => $time1->format('m'), 3234 'day' => $time1->format('d'), 3235 ], 3236 [ 3237 'year' => $time2->format('Y'), 3238 'month' => (int) $time2->format('m'), 3239 'day' => $time2->format('d'), 3240 'hour' => $time2->format('H'), 3241 'minute' => $time2->format('i'), 3242 ], 3243 ]; 3244 3245 $expectedtimestamps = [ 3246 0 => $time1->getTimestamp(), 3247 1 => $time2->getTimestamp(), 3248 ]; 3249 3250 $result = core_calendar_external::get_timestamps($dates); 3251 3252 $this->assertEquals(['timestamps'], array_keys($result)); 3253 $this->assertEquals(2, count($result['timestamps'])); 3254 3255 foreach ($result['timestamps'] as $data) { 3256 $this->assertEquals($expectedtimestamps[$data['key']], $data['timestamp']); 3257 } 3258 } 3259 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body