1<?php 2// This file is part of Moodle - http://moodle.org/ 3// 4// Moodle is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// Moodle is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17/** 18 * Raw event retrieval strategy tests. 19 * 20 * @package core_calendar 21 * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25defined('MOODLE_INTERNAL') || die(); 26 27global $CFG; 28require_once($CFG->dirroot . '/calendar/tests/helpers.php'); 29 30use core_calendar\local\event\strategies\raw_event_retrieval_strategy; 31 32/** 33 * Raw event retrieval strategy testcase. 34 * 35 * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz> 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38class core_calendar_raw_event_retrieval_strategy_testcase extends advanced_testcase { 39 /** 40 * Test retrieval strategy when module is disabled. 41 */ 42 public function test_get_raw_events_with_disabled_module() { 43 global $DB; 44 45 $this->resetAfterTest(); 46 $retrievalstrategy = new raw_event_retrieval_strategy(); 47 $generator = $this->getDataGenerator(); 48 $course = $generator->create_course(); 49 $student = $generator->create_user(); 50 $generator->enrol_user($student->id, $course->id, 'student'); 51 $this->setUser($student); 52 $events = [ 53 [ 54 'name' => 'Start of assignment', 55 'description' => '', 56 'location' => 'Test', 57 'format' => 1, 58 'courseid' => $course->id, 59 'groupid' => 0, 60 'userid' => 2, 61 'modulename' => 'assign', 62 'instance' => 1, 63 'eventtype' => 'due', 64 'timestart' => time(), 65 'timeduration' => 86400, 66 'visible' => 1 67 ], [ 68 'name' => 'Start of lesson', 69 'description' => '', 70 'location' => 'Test', 71 'format' => 1, 72 'courseid' => $course->id, 73 'groupid' => 0, 74 'userid' => 2, 75 'modulename' => 'lesson', 76 'instance' => 1, 77 'eventtype' => 'end', 78 'timestart' => time(), 79 'timeduration' => 86400, 80 'visible' => 1 81 ] 82 ]; 83 84 foreach ($events as $event) { 85 calendar_event::create($event, false); 86 } 87 88 // Get all events. 89 $events = $retrievalstrategy->get_raw_events(null, [0], null); 90 $this->assertCount(2, $events); 91 92 // Disable the lesson module. 93 $DB->set_field('modules', 'visible', 0, ['name' => 'lesson']); 94 95 // Check that we only return the assign event. 96 $events = $retrievalstrategy->get_raw_events(null, [0], null); 97 $this->assertCount(1, $events); 98 $event = reset($events); 99 $this->assertEquals('assign', $event->modulename); 100 101 // Now, log out and repeat the above test in the reverse order. 102 $this->setUser(); 103 104 // Check that we only return the assign event (given that the lesson module is still disabled). 105 $events = $retrievalstrategy->get_raw_events([$student->id], [0], null); 106 $this->assertCount(1, $events); 107 $event = reset($events); 108 $this->assertEquals('assign', $event->modulename); 109 110 // Enable the lesson module. 111 $DB->set_field('modules', 'visible', 1, ['name' => 'lesson']); 112 113 // Get all events. 114 $events = $retrievalstrategy->get_raw_events(null, [0], null); 115 $this->assertCount(2, $events); 116 } 117 118 /** 119 * Test retrieval strategy when there are overrides. 120 */ 121 public function test_get_raw_event_strategy_with_overrides() { 122 $this->resetAfterTest(); 123 124 $retrievalstrategy = new raw_event_retrieval_strategy(); 125 $generator = $this->getDataGenerator(); 126 $course = $generator->create_course(); 127 $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 128 129 $instance = $plugingenerator->create_instance(['course' => $course->id]); 130 131 // Create users. 132 $useroverridestudent = $generator->create_user(); 133 $group1student = $generator->create_user(); 134 $group2student = $generator->create_user(); 135 $group12student = $generator->create_user(); 136 $nogroupstudent = $generator->create_user(); 137 138 // Enrol users. 139 $generator->enrol_user($useroverridestudent->id, $course->id, 'student'); 140 $generator->enrol_user($group1student->id, $course->id, 'student'); 141 $generator->enrol_user($group2student->id, $course->id, 'student'); 142 $generator->enrol_user($group12student->id, $course->id, 'student'); 143 144 $generator->enrol_user($nogroupstudent->id, $course->id, 'student'); 145 146 // Create groups. 147 $group1 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 1']); 148 $group2 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 2']); 149 150 // Add members to groups. 151 $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]); 152 $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]); 153 $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]); 154 $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]); 155 156 $now = time(); 157 158 // Events with the same module name, instance and event type. 159 $events = [ 160 [ 161 'name' => 'Assignment 1 due date', 162 'description' => '', 163 'location' => 'Test', 164 'format' => 0, 165 'courseid' => $course->id, 166 'groupid' => 0, 167 'userid' => 2, 168 'modulename' => 'assign', 169 'instance' => $instance->id, 170 'eventtype' => 'due', 171 'timestart' => $now, 172 'timeduration' => 0, 173 'visible' => 1 174 ], [ 175 'name' => 'Assignment 1 due date - User override', 176 'description' => '', 177 'location' => 'Test', 178 'format' => 1, 179 'courseid' => 0, 180 'groupid' => 0, 181 'userid' => $useroverridestudent->id, 182 'modulename' => 'assign', 183 'instance' => $instance->id, 184 'eventtype' => 'due', 185 'timestart' => $now + 86400, 186 'timeduration' => 0, 187 'visible' => 1, 188 'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY 189 ], [ 190 'name' => 'Assignment 1 due date - Group A override', 191 'description' => '', 192 'location' => 'Test', 193 'format' => 1, 194 'courseid' => $course->id, 195 'groupid' => $group1->id, 196 'userid' => 2, 197 'modulename' => 'assign', 198 'instance' => $instance->id, 199 'eventtype' => 'due', 200 'timestart' => $now + (2 * 86400), 201 'timeduration' => 0, 202 'visible' => 1, 203 'priority' => 1, 204 ], [ 205 'name' => 'Assignment 1 due date - Group B override', 206 'description' => '', 207 'location' => 'Test', 208 'format' => 1, 209 'courseid' => $course->id, 210 'groupid' => $group2->id, 211 'userid' => 2, 212 'modulename' => 'assign', 213 'instance' => $instance->id, 214 'eventtype' => 'due', 215 'timestart' => $now + (3 * 86400), 216 'timeduration' => 0, 217 'visible' => 1, 218 'priority' => 2, 219 ], 220 ]; 221 222 foreach ($events as $event) { 223 calendar_event::create($event, false); 224 } 225 226 $groups = [$group1->id, $group2->id]; 227 228 // Do the following tests multiple times when logged in with different users. Also run the whole set when logged out. 229 // In any cases, the tests should not depend on the logged-in user. 230 foreach ([$useroverridestudent, $nogroupstudent, $group12student, $group1student, null] as $login) { 231 $this->setUser($login); 232 233 // Get user override events. 234 $events = $retrievalstrategy->get_raw_events([$useroverridestudent->id], $groups, [$course->id]); 235 $this->assertCount(1, $events); 236 $event = reset($events); 237 $this->assertEquals('Assignment 1 due date - User override', $event->name); 238 239 // Get events for user that does not belong to any group and has no user override events. 240 $events = $retrievalstrategy->get_raw_events([$nogroupstudent->id], $groups, [$course->id]); 241 $this->assertCount(1, $events); 242 $event = reset($events); 243 $this->assertEquals('Assignment 1 due date', $event->name); 244 245 // Get events for user that belongs to groups A and B and has no user override events. 246 $events = $retrievalstrategy->get_raw_events([$group12student->id], $groups, [$course->id]); 247 $this->assertCount(1, $events); 248 $event = reset($events); 249 $this->assertEquals('Assignment 1 due date - Group A override', $event->name); 250 251 // Get events for user that belongs to group A and has no user override events. 252 $events = $retrievalstrategy->get_raw_events([$group1student->id], $groups, [$course->id]); 253 $this->assertCount(1, $events); 254 $event = reset($events); 255 $this->assertEquals('Assignment 1 due date - Group A override', $event->name); 256 } 257 258 // Add repeating events. 259 $repeatingevents = [ 260 [ 261 'name' => 'Repeating site event', 262 'description' => '', 263 'location' => 'Test', 264 'format' => 1, 265 'courseid' => SITEID, 266 'groupid' => 0, 267 'userid' => 2, 268 'repeatid' => 1, 269 'modulename' => '0', 270 'instance' => 0, 271 'eventtype' => 'site', 272 'timestart' => $now + 86400, 273 'timeduration' => 0, 274 'visible' => 1, 275 ], 276 [ 277 'name' => 'Repeating site event', 278 'description' => '', 279 'location' => 'Test', 280 'format' => 1, 281 'courseid' => SITEID, 282 'groupid' => 0, 283 'userid' => 2, 284 'repeatid' => 1, 285 'modulename' => '0', 286 'instance' => 0, 287 'eventtype' => 'site', 288 'timestart' => $now + (2 * 86400), 289 'timeduration' => 0, 290 'visible' => 1, 291 ], 292 ]; 293 294 foreach ($repeatingevents as $event) { 295 calendar_event::create($event, false); 296 } 297 298 // Make sure repeating events are not filtered out. 299 $events = $retrievalstrategy->get_raw_events(); 300 $this->assertCount(3, $events); 301 } 302 303 /** 304 * Test retrieval strategy with category specifications. 305 */ 306 public function test_get_raw_events_category() { 307 $this->resetAfterTest(); 308 $retrievalstrategy = new raw_event_retrieval_strategy(); 309 $generator = $this->getDataGenerator(); 310 $category1 = $generator->create_category(); 311 $category2 = $generator->create_category(); 312 $events = [ 313 [ 314 'name' => 'E1', 315 'eventtype' => 'category', 316 'description' => '', 317 'location' => 'Test', 318 'format' => 1, 319 'categoryid' => $category1->id, 320 'userid' => 2, 321 'timestart' => time(), 322 ], 323 [ 324 'name' => 'E2', 325 'eventtype' => 'category', 326 'description' => '', 327 'location' => 'Test', 328 'format' => 1, 329 'categoryid' => $category2->id, 330 'userid' => 2, 331 'timestart' => time() + 1, 332 ], 333 ]; 334 335 foreach ($events as $event) { 336 calendar_event::create($event, false); 337 } 338 339 // Get all events. 340 $events = $retrievalstrategy->get_raw_events(null, null, null, null); 341 $this->assertCount(2, $events); 342 343 $event = array_shift($events); 344 $this->assertEquals('E1', $event->name); 345 $event = array_shift($events); 346 $this->assertEquals('E2', $event->name); 347 348 // Get events for C1 events. 349 $events = $retrievalstrategy->get_raw_events(null, null, null, [$category1->id]); 350 $this->assertCount(1, $events); 351 352 $event = array_shift($events); 353 $this->assertEquals('E1', $event->name); 354 355 // Get events for C2 events. 356 $events = $retrievalstrategy->get_raw_events(null, null, null, [$category2->id]); 357 $this->assertCount(1, $events); 358 359 $event = array_shift($events); 360 $this->assertEquals('E2', $event->name); 361 362 // Get events for several categories. 363 $events = $retrievalstrategy->get_raw_events(null, null, null, [$category1->id, $category2->id]); 364 $this->assertCount(2, $events); 365 } 366 367 public function test_get_raw_events_for_multiple_users() { 368 $this->resetAfterTest(); 369 370 $generator = $this->getDataGenerator(); 371 372 // Create users. 373 $user1 = $generator->create_user(); 374 $user2 = $generator->create_user(); 375 $user3 = $generator->create_user(); 376 377 // Create user events. 378 $events = [ 379 [ 380 'name' => 'User1 Event', 381 'eventtype' => 'user', 382 'userid' => $user1->id, 383 'timestart' => time(), 384 ], [ 385 'name' => 'User2 Event', 386 'eventtype' => 'user', 387 'userid' => $user2->id, 388 'timestart' => time(), 389 ], [ 390 'name' => 'User3 Event', 391 'eventtype' => 'user', 392 'userid' => $user3->id, 393 'timestart' => time(), 394 ] 395 ]; 396 foreach ($events as $event) { 397 calendar_event::create($event, false); 398 } 399 400 $retrievalstrategy = new raw_event_retrieval_strategy(); 401 402 // Get all events. 403 $events = $retrievalstrategy->get_raw_events([$user1->id, $user2->id]); 404 $this->assertCount(2, $events); 405 $this->assertEqualsCanonicalizing( 406 ['User1 Event', 'User2 Event'], 407 array_column($events, 'name')); 408 } 409 410 public function test_get_raw_events_for_groups_with_no_members() { 411 $this->resetAfterTest(); 412 413 $generator = $this->getDataGenerator(); 414 415 $course = $generator->create_course(); 416 417 // Create groups. 418 $group1 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 1']); 419 $group2 = $generator->create_group(['courseid' => $course->id, 'name' => 'Group 2']); 420 421 // Create group events. 422 $events = [ 423 [ 424 'name' => 'Group 1 Event', 425 'eventtype' => 'group', 426 'groupid' => $group1->id, 427 'timestart' => time(), 428 ], [ 429 'name' => 'Group 2 Event', 430 'eventtype' => 'group', 431 'groupid' => $group2->id, 432 'timestart' => time(), 433 ] 434 ]; 435 foreach ($events as $event) { 436 calendar_event::create($event, false); 437 } 438 439 $retrievalstrategy = new raw_event_retrieval_strategy; 440 441 // Get group eventsl. 442 $events = $retrievalstrategy->get_raw_events(null, [$group1->id, $group2->id]); 443 $this->assertCount(2, $events); 444 $this->assertEqualsCanonicalizing( 445 ['Group 1 Event', 'Group 2 Event'], 446 array_column($events, 'name')); 447 } 448 449 /** 450 * Test retrieval strategy with empty filters. 451 * This covers a edge case not covered elsewhere to ensure its SQL is cross 452 * db compatible. The test is ensuring we don't get a DML Exception with 453 * the filters setup this way. 454 */ 455 public function test_get_raw_events_with_empty_user_and_category_lists() { 456 $retrievalstrategy = new raw_event_retrieval_strategy; 457 $retrievalstrategy->get_raw_events([], null, null, []); 458 } 459} 460