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