Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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   * Contains the class containing unit tests for the calendar lib.
  19   *
  20   * @package    core_calendar
  21   * @copyright  2017 Mark Nelson <markn@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  require_once (__DIR__ . '/helpers.php');
  28  
  29  /**
  30   * Class contaning unit tests for the calendar lib.
  31   *
  32   * @package    core_calendar
  33   * @copyright  2017 Mark Nelson <markn@moodle.com>
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class core_calendar_lib_testcase extends advanced_testcase {
  37  
  38      /**
  39       * Tests set up
  40       */
  41      protected function setUp(): void {
  42          $this->resetAfterTest();
  43      }
  44  
  45      /**
  46       * Test that the get_events() function only returns activity events that are enabled.
  47       */
  48      public function test_get_events_with_disabled_module() {
  49          global $DB;
  50          $this->setAdminUser();
  51          $generator = $this->getDataGenerator();
  52          $course = $generator->create_course();
  53          $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  54          $assigninstance = $assigngenerator->create_instance(['course' => $course->id]);
  55          $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
  56          $lessoninstance = $lessongenerator->create_instance(['course' => $course->id]);
  57          $student = $generator->create_user();
  58          $generator->enrol_user($student->id, $course->id, 'student');
  59          $this->setUser($student);
  60          $events = [
  61              [
  62                  'name' => 'Start of assignment',
  63                  'description' => '',
  64                  'location' => 'Test',
  65                  'format' => 1,
  66                  'courseid' => $course->id,
  67                  'groupid' => 0,
  68                  'userid' => 2,
  69                  'modulename' => 'assign',
  70                  'instance' => $assigninstance->id,
  71                  'eventtype' => 'due',
  72                  'timestart' => time(),
  73                  'timeduration' => 86400,
  74                  'visible' => 1
  75              ], [
  76                  'name' => 'Start of lesson',
  77                  'description' => '',
  78                  'location' => 'Test',
  79                  'format' => 1,
  80                  'courseid' => $course->id,
  81                  'groupid' => 0,
  82                  'userid' => 2,
  83                  'modulename' => 'lesson',
  84                  'instance' => $lessoninstance->id,
  85                  'eventtype' => 'end',
  86                  'timestart' => time(),
  87                  'timeduration' => 86400,
  88                  'visible' => 1
  89              ]
  90          ];
  91          foreach ($events as $event) {
  92              calendar_event::create($event, false);
  93          }
  94          $timestart = time() - 60;
  95          $timeend = time() + 60;
  96          // Get all events.
  97          $events = calendar_get_events($timestart, $timeend, true, 0, true);
  98          $this->assertCount(2, $events);
  99          // Disable the lesson module.
 100          $modulerecord = $DB->get_record('modules', ['name' => 'lesson']);
 101          $modulerecord->visible = 0;
 102          $DB->update_record('modules', $modulerecord);
 103          // Check that we only return the assign event.
 104          $events = calendar_get_events($timestart, $timeend, true, 0, true);
 105          $this->assertCount(1, $events);
 106          $event = reset($events);
 107          $this->assertEquals('assign', $event->modulename);
 108      }
 109  
 110      public function test_get_course_cached() {
 111          // Setup some test courses.
 112          $course1 = $this->getDataGenerator()->create_course();
 113          $course2 = $this->getDataGenerator()->create_course();
 114          $course3 = $this->getDataGenerator()->create_course();
 115  
 116          // Load courses into cache.
 117          $coursecache = null;
 118          calendar_get_course_cached($coursecache, $course1->id);
 119          calendar_get_course_cached($coursecache, $course2->id);
 120          calendar_get_course_cached($coursecache, $course3->id);
 121  
 122          // Verify the cache.
 123          $this->assertArrayHasKey($course1->id, $coursecache);
 124          $cachedcourse1 = $coursecache[$course1->id];
 125          $this->assertEquals($course1->id, $cachedcourse1->id);
 126          $this->assertEquals($course1->shortname, $cachedcourse1->shortname);
 127          $this->assertEquals($course1->fullname, $cachedcourse1->fullname);
 128  
 129          $this->assertArrayHasKey($course2->id, $coursecache);
 130          $cachedcourse2 = $coursecache[$course2->id];
 131          $this->assertEquals($course2->id, $cachedcourse2->id);
 132          $this->assertEquals($course2->shortname, $cachedcourse2->shortname);
 133          $this->assertEquals($course2->fullname, $cachedcourse2->fullname);
 134  
 135          $this->assertArrayHasKey($course3->id, $coursecache);
 136          $cachedcourse3 = $coursecache[$course3->id];
 137          $this->assertEquals($course3->id, $cachedcourse3->id);
 138          $this->assertEquals($course3->shortname, $cachedcourse3->shortname);
 139          $this->assertEquals($course3->fullname, $cachedcourse3->fullname);
 140      }
 141  
 142      /**
 143       * Test the update_subscription() function.
 144       */
 145      public function test_update_subscription() {
 146          $this->resetAfterTest(true);
 147  
 148          $subscription = new stdClass();
 149          $subscription->eventtype = 'site';
 150          $subscription->name = 'test';
 151          $id = calendar_add_subscription($subscription);
 152  
 153          $subscription = calendar_get_subscription($id);
 154          $subscription->name = 'awesome';
 155          calendar_update_subscription($subscription);
 156          $sub = calendar_get_subscription($id);
 157          $this->assertEquals($subscription->name, $sub->name);
 158  
 159          $subscription = calendar_get_subscription($id);
 160          $subscription->name = 'awesome2';
 161          $subscription->pollinterval = 604800;
 162          calendar_update_subscription($subscription);
 163          $sub = calendar_get_subscription($id);
 164          $this->assertEquals($subscription->name, $sub->name);
 165          $this->assertEquals($subscription->pollinterval, $sub->pollinterval);
 166  
 167          $subscription = new stdClass();
 168          $subscription->name = 'awesome4';
 169          $this->expectException('coding_exception');
 170          calendar_update_subscription($subscription);
 171      }
 172  
 173      public function test_add_subscription() {
 174          global $DB, $CFG;
 175  
 176          require_once($CFG->dirroot . '/lib/bennu/bennu.inc.php');
 177  
 178          $this->resetAfterTest(true);
 179  
 180          // Test for Microsoft Outlook 2010.
 181          $subscription = new stdClass();
 182          $subscription->name = 'Microsoft Outlook 2010';
 183          $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
 184          $subscription->eventtype = 'site';
 185          $id = calendar_add_subscription($subscription);
 186  
 187          $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/ms_outlook_2010.ics');
 188          $ical = new iCalendar();
 189          $ical->unserialize($calendar);
 190          $this->assertEquals($ical->parser_errors, array());
 191  
 192          $sub = calendar_get_subscription($id);
 193          calendar_import_icalendar_events($ical, null, $sub->id);
 194          $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
 195          $this->assertEquals($count, 1);
 196  
 197          // Test for OSX Yosemite.
 198          $subscription = new stdClass();
 199          $subscription->name = 'OSX Yosemite';
 200          $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
 201          $subscription->eventtype = 'site';
 202          $id = calendar_add_subscription($subscription);
 203  
 204          $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/osx_yosemite.ics');
 205          $ical = new iCalendar();
 206          $ical->unserialize($calendar);
 207          $this->assertEquals($ical->parser_errors, array());
 208  
 209          $sub = calendar_get_subscription($id);
 210          calendar_import_icalendar_events($ical, null, $sub->id);
 211          $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
 212          $this->assertEquals($count, 1);
 213  
 214          // Test for Google Gmail.
 215          $subscription = new stdClass();
 216          $subscription->name = 'Google Gmail';
 217          $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
 218          $subscription->eventtype = 'site';
 219          $id = calendar_add_subscription($subscription);
 220  
 221          $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/google_gmail.ics');
 222          $ical = new iCalendar();
 223          $ical->unserialize($calendar);
 224          $this->assertEquals($ical->parser_errors, array());
 225  
 226          $sub = calendar_get_subscription($id);
 227          calendar_import_icalendar_events($ical, null, $sub->id);
 228          $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
 229          $this->assertEquals($count, 1);
 230  
 231          // Test for ICS file with repeated events.
 232          $subscription = new stdClass();
 233          $subscription->name = 'Repeated events';
 234          $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
 235          $subscription->eventtype = 'site';
 236          $id = calendar_add_subscription($subscription);
 237          $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/repeated_events.ics');
 238          $ical = new iCalendar();
 239          $ical->unserialize($calendar);
 240          $this->assertEquals($ical->parser_errors, []);
 241  
 242          $sub = calendar_get_subscription($id);
 243          $output = calendar_import_icalendar_events($ical, null, $sub->id);
 244          $this->assertStringNotContainsString('Events deleted: 17', $output);
 245          $this->assertStringContainsString('Events imported: 1', $output);
 246          $this->assertStringContainsString('Events skipped: 0', $output);
 247          $this->assertStringContainsString('Events updated: 0', $output);
 248      }
 249  
 250      /**
 251       * Test for calendar_get_legacy_events() when there are user and group overrides.
 252       */
 253      public function test_get_legacy_events_with_overrides() {
 254          $generator = $this->getDataGenerator();
 255  
 256          $course = $generator->create_course();
 257  
 258          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 259          if (!isset($params['course'])) {
 260              $params['course'] = $course->id;
 261          }
 262  
 263          $instance = $plugingenerator->create_instance($params);
 264  
 265          // Create users.
 266          $useroverridestudent = $generator->create_user();
 267          $group1student = $generator->create_user();
 268          $group2student = $generator->create_user();
 269          $group12student = $generator->create_user();
 270          $nogroupstudent = $generator->create_user();
 271  
 272          // Enrol users.
 273          $generator->enrol_user($useroverridestudent->id, $course->id, 'student');
 274          $generator->enrol_user($group1student->id, $course->id, 'student');
 275          $generator->enrol_user($group2student->id, $course->id, 'student');
 276          $generator->enrol_user($group12student->id, $course->id, 'student');
 277          $generator->enrol_user($nogroupstudent->id, $course->id, 'student');
 278  
 279          // Create groups.
 280          $group1 = $generator->create_group(['courseid' => $course->id]);
 281          $group2 = $generator->create_group(['courseid' => $course->id]);
 282  
 283          // Add members to groups.
 284          $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
 285          $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
 286          $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
 287          $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
 288          $now = time();
 289  
 290          // Events with the same module name, instance and event type.
 291          $events = [
 292              [
 293                  'name' => 'Assignment 1 due date',
 294                  'description' => '',
 295                  'location' => 'Test',
 296                  'format' => 0,
 297                  'courseid' => $course->id,
 298                  'groupid' => 0,
 299                  'userid' => 2,
 300                  'modulename' => 'assign',
 301                  'instance' => $instance->id,
 302                  'eventtype' => 'due',
 303                  'timestart' => $now,
 304                  'timeduration' => 0,
 305                  'visible' => 1
 306              ], [
 307                  'name' => 'Assignment 1 due date - User override',
 308                  'description' => '',
 309                  'location' => 'Test',
 310                  'format' => 1,
 311                  'courseid' => 0,
 312                  'groupid' => 0,
 313                  'userid' => $useroverridestudent->id,
 314                  'modulename' => 'assign',
 315                  'instance' => $instance->id,
 316                  'eventtype' => 'due',
 317                  'timestart' => $now + 86400,
 318                  'timeduration' => 0,
 319                  'visible' => 1,
 320                  'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
 321              ], [
 322                  'name' => 'Assignment 1 due date - Group A override',
 323                  'description' => '',
 324                  'location' => 'Test',
 325                  'format' => 1,
 326                  'courseid' => $course->id,
 327                  'groupid' => $group1->id,
 328                  'userid' => 2,
 329                  'modulename' => 'assign',
 330                  'instance' => $instance->id,
 331                  'eventtype' => 'due',
 332                  'timestart' => $now + (2 * 86400),
 333                  'timeduration' => 0,
 334                  'visible' => 1,
 335                  'priority' => 1,
 336              ], [
 337                  'name' => 'Assignment 1 due date - Group B override',
 338                  'description' => '',
 339                  'location' => 'Test',
 340                  'format' => 1,
 341                  'courseid' => $course->id,
 342                  'groupid' => $group2->id,
 343                  'userid' => 2,
 344                  'modulename' => 'assign',
 345                  'instance' => $instance->id,
 346                  'eventtype' => 'due',
 347                  'timestart' => $now + (3 * 86400),
 348                  'timeduration' => 0,
 349                  'visible' => 1,
 350                  'priority' => 2,
 351              ],
 352          ];
 353  
 354          foreach ($events as $event) {
 355              calendar_event::create($event, false);
 356          }
 357  
 358          $timestart = $now - 100;
 359          $timeend = $now + (3 * 86400);
 360          $groups = [$group1->id, $group2->id];
 361  
 362          // Get user override events.
 363          $this->setUser($useroverridestudent);
 364          $events = calendar_get_legacy_events($timestart, $timeend, $useroverridestudent->id, $groups, $course->id);
 365          $this->assertCount(1, $events);
 366          $event = reset($events);
 367          $this->assertEquals('Assignment 1 due date - User override', $event->name);
 368  
 369          // Get event for user with override but with the timestart and timeend parameters only covering the original event.
 370          $events = calendar_get_legacy_events($timestart, $now, $useroverridestudent->id, $groups, $course->id);
 371          $this->assertCount(0, $events);
 372  
 373          // Get events for user that does not belong to any group and has no user override events.
 374          $this->setUser($nogroupstudent);
 375          $events = calendar_get_legacy_events($timestart, $timeend, $nogroupstudent->id, $groups, $course->id);
 376          $this->assertCount(1, $events);
 377          $event = reset($events);
 378          $this->assertEquals('Assignment 1 due date', $event->name);
 379  
 380          // Get events for user that belongs to groups A and B and has no user override events.
 381          $this->setUser($group12student);
 382          $events = calendar_get_legacy_events($timestart, $timeend, $group12student->id, $groups, $course->id);
 383          $this->assertCount(1, $events);
 384          $event = reset($events);
 385          $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
 386  
 387          // Get events for user that belongs to group A and has no user override events.
 388          $this->setUser($group1student);
 389          $events = calendar_get_legacy_events($timestart, $timeend, $group1student->id, $groups, $course->id);
 390          $this->assertCount(1, $events);
 391          $event = reset($events);
 392          $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
 393  
 394          // Add repeating events.
 395          $repeatingevents = [
 396              [
 397                  'name' => 'Repeating site event',
 398                  'description' => '',
 399                  'location' => 'Test',
 400                  'format' => 1,
 401                  'courseid' => SITEID,
 402                  'groupid' => 0,
 403                  'userid' => 2,
 404                  'repeatid' => $event->id,
 405                  'modulename' => '0',
 406                  'instance' => 0,
 407                  'eventtype' => 'site',
 408                  'timestart' => $now + 86400,
 409                  'timeduration' => 0,
 410                  'visible' => 1,
 411              ],
 412              [
 413                  'name' => 'Repeating site event',
 414                  'description' => '',
 415                  'location' => 'Test',
 416                  'format' => 1,
 417                  'courseid' => SITEID,
 418                  'groupid' => 0,
 419                  'userid' => 2,
 420                  'repeatid' => $event->id,
 421                  'modulename' => '0',
 422                  'instance' => 0,
 423                  'eventtype' => 'site',
 424                  'timestart' => $now + (2 * 86400),
 425                  'timeduration' => 0,
 426                  'visible' => 1,
 427              ],
 428          ];
 429  
 430          foreach ($repeatingevents as $event) {
 431              calendar_event::create($event, false);
 432          }
 433  
 434          // Make sure repeating events are not filtered out.
 435          $events = calendar_get_legacy_events($timestart, $timeend, true, true, true);
 436          $this->assertCount(3, $events);
 437      }
 438  
 439      public function test_calendar_get_default_courses() {
 440          global $USER, $CFG;
 441  
 442          $this->resetAfterTest(true);
 443  
 444          $generator = $this->getDataGenerator();
 445          $user = $generator->create_user();
 446          $course1 = $generator->create_course();
 447          $course2 = $generator->create_course();
 448          $course3 = $generator->create_course();
 449          $context = context_course::instance($course1->id);
 450  
 451          $this->setAdminUser();
 452          $admin = clone $USER;
 453  
 454          $teacher = $generator->create_user();
 455          $generator->enrol_user($teacher->id, $course1->id, 'teacher');
 456          $generator->enrol_user($admin->id, $course1->id, 'teacher');
 457  
 458          $CFG->calendar_adminseesall = false;
 459  
 460          $courses = calendar_get_default_courses();
 461          // Only enrolled in one course.
 462          $this->assertCount(1, $courses);
 463          $courses = calendar_get_default_courses($course2->id);
 464          // Enrolled course + current course.
 465          $this->assertCount(2, $courses);
 466          $CFG->calendar_adminseesall = true;
 467          $courses = calendar_get_default_courses();
 468          // All courses + SITE.
 469          $this->assertCount(4, $courses);
 470          $courses = calendar_get_default_courses($course2->id);
 471          // All courses + SITE.
 472          $this->assertCount(4, $courses);
 473  
 474          $this->setUser($teacher);
 475  
 476          $CFG->calendar_adminseesall = false;
 477  
 478          $courses = calendar_get_default_courses();
 479          // Only enrolled in one course.
 480          $this->assertCount(1, $courses);
 481          $courses = calendar_get_default_courses($course2->id);
 482          // Enrolled course only (ignore current).
 483          $this->assertCount(1, $courses);
 484          // This setting should not affect teachers.
 485          $CFG->calendar_adminseesall = true;
 486          $courses = calendar_get_default_courses();
 487          // Only enrolled in one course.
 488          $this->assertCount(1, $courses);
 489          $courses = calendar_get_default_courses($course2->id);
 490          // Enrolled course only (ignore current).
 491          $this->assertCount(1, $courses);
 492  
 493          // Now, log out and test again.
 494          $this->setUser();
 495  
 496          $CFG->calendar_adminseesall = false;
 497  
 498          $courses = calendar_get_default_courses(null, '*', false, $teacher->id);
 499          // Only enrolled in one course.
 500          $this->assertCount(1, $courses);
 501          $courses = calendar_get_default_courses($course2->id, '*', false, $teacher->id);
 502          // Enrolled course only (ignore current).
 503          $this->assertCount(1, $courses);
 504          // This setting should not affect teachers.
 505          $CFG->calendar_adminseesall = true;
 506          $courses = calendar_get_default_courses(null, '*', false, $teacher->id);
 507          // Only enrolled in one course.
 508          $this->assertCount(1, $courses);
 509          $courses = calendar_get_default_courses($course2->id, '*', false, $teacher->id);
 510          // Enrolled course only (ignore current).
 511          $this->assertCount(1, $courses);
 512  
 513      }
 514  
 515      /**
 516       * Confirm that the skip events flag causes the calendar_get_view function
 517       * to avoid querying for the calendar events.
 518       */
 519      public function test_calendar_get_view_skip_events() {
 520          $this->resetAfterTest(true);
 521          $this->setAdminUser();
 522  
 523          $generator = $this->getDataGenerator();
 524          $user = $generator->create_user();
 525          $skipnavigation = true;
 526          $skipevents = true;
 527          $event = create_event([
 528              'eventtype' => 'user',
 529              'userid' => $user->id
 530          ]);
 531  
 532          $this->setUser($user);
 533          $calendar = \calendar_information::create(time() - 10, SITEID, null);
 534  
 535          list($data, $template) = calendar_get_view($calendar, 'day', $skipnavigation, $skipevents);
 536          $this->assertEmpty($data->events);
 537  
 538          $skipevents = false;
 539          list($data, $template) = calendar_get_view($calendar, 'day', $skipnavigation, $skipevents);
 540  
 541          $this->assertEquals($event->id, $data->events[0]->id);
 542      }
 543  
 544      public function test_calendar_get_allowed_event_types_course() {
 545          $generator = $this->getDataGenerator();
 546          $user = $generator->create_user();
 547          $course1 = $generator->create_course(); // Has capability.
 548          $course2 = $generator->create_course(); // Doesn't have capability.
 549          $course3 = $generator->create_course(); // Not enrolled.
 550          $context1 = context_course::instance($course1->id);
 551          $context2 = context_course::instance($course2->id);
 552          $context3 = context_course::instance($course3->id);
 553          $roleid = $generator->create_role();
 554          $contexts = [$context1, $context2, $context3];
 555          $enrolledcourses = [$course1, $course2];
 556  
 557          foreach ($enrolledcourses as $course) {
 558              $generator->enrol_user($user->id, $course->id, 'student');
 559          }
 560  
 561          foreach ($contexts as $context) {
 562              $generator->role_assign($roleid, $user->id, $context->id);
 563          }
 564  
 565          $this->setUser($user);
 566  
 567          // In general for all courses, they don't have the ability to add course events yet.
 568          $types = calendar_get_allowed_event_types();
 569          $this->assertFalse($types['course']);
 570  
 571          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
 572          assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context2, true);
 573  
 574          // The user only has the correct capability in course 1 so that is the only
 575          // one that should be in the results.
 576          $types = calendar_get_allowed_event_types($course1->id);
 577          $this->assertTrue($types['course']);
 578  
 579          // If calling function without specified course,  there is still a course where they have it.
 580          $types = calendar_get_allowed_event_types();
 581          $this->assertTrue($types['course']);
 582  
 583          assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context1, true);
 584  
 585          // The user only now has the correct capability in both course 1 and 2 so we
 586          // expect both to be in the results.
 587          $types = calendar_get_allowed_event_types($course3->id);
 588          $this->assertFalse($types['course']);
 589  
 590          // They now do not have permission in any course.
 591          $types = calendar_get_allowed_event_types();
 592          $this->assertFalse($types['course']);
 593      }
 594  
 595      public function test_calendar_get_allowed_event_types_group_no_acces_to_diff_groups() {
 596          $generator = $this->getDataGenerator();
 597          $user = $generator->create_user();
 598          $course = $generator->create_course();
 599          $context = context_course::instance($course->id);
 600          $roleid = $generator->create_role();
 601  
 602          $generator->enrol_user($user->id, $course->id, 'student');
 603          $generator->role_assign($roleid, $user->id, $context->id);
 604  
 605          $this->setUser($user);
 606  
 607          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 608          assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
 609  
 610          // The user has the correct capability in the course but they aren't a member
 611          // of any of the groups and don't have the accessallgroups capability.
 612          $types = calendar_get_allowed_event_types($course->id);
 613          $this->assertTrue($types['course']);
 614          $this->assertFalse($types['group']);
 615  
 616          // Same result applies when not providing a specific course as they are only on one course.
 617          $types = calendar_get_allowed_event_types();
 618          $this->assertTrue($types['course']);
 619          $this->assertFalse($types['group']);
 620      }
 621  
 622      public function test_calendar_get_allowed_event_types_group_no_groups() {
 623          $generator = $this->getDataGenerator();
 624          $user = $generator->create_user();
 625          $course = $generator->create_course();
 626          $context = context_course::instance($course->id);
 627          $roleid = $generator->create_role();
 628          $generator->enrol_user($user->id, $course->id, 'student');
 629          $generator->role_assign($roleid, $user->id, $context->id);
 630          $this->setUser($user);
 631          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 632          // The user has the correct capability in the course but there are
 633          // no groups so we shouldn't see a group type.
 634          $types = calendar_get_allowed_event_types($course->id);
 635          $this->assertTrue($types['course']);
 636          $this->assertFalse($types['group']);
 637  
 638          // Same result applies when not providing a specific course as they are only on one course.
 639          $types = calendar_get_allowed_event_types();
 640          $this->assertTrue($types['course']);
 641          $this->assertFalse($types['group']);
 642      }
 643  
 644      public function test_calendar_get_allowed_event_types_group_access_all_groups() {
 645          $generator = $this->getDataGenerator();
 646          $user = $generator->create_user();
 647          $course1 = $generator->create_course();
 648          $course2 = $generator->create_course();
 649          $generator->create_group(array('courseid' => $course1->id));
 650          $generator->create_group(array('courseid' => $course2->id));
 651          $context1 = context_course::instance($course1->id);
 652          $context2 = context_course::instance($course2->id);
 653          $roleid = $generator->create_role();
 654          $generator->enrol_user($user->id, $course1->id, 'student');
 655          $generator->enrol_user($user->id, $course2->id, 'student');
 656          $generator->role_assign($roleid, $user->id, $context1->id);
 657          $generator->role_assign($roleid, $user->id, $context2->id);
 658          $this->setUser($user);
 659          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
 660          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context2, true);
 661          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context1, true);
 662          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context2, true);
 663          // The user has the correct capability in the course and has
 664          // the accessallgroups capability.
 665          $types = calendar_get_allowed_event_types($course1->id);
 666          $this->assertTrue($types['group']);
 667  
 668          // Same result applies when not providing a specific course as they are only on one course.
 669          $types = calendar_get_allowed_event_types();
 670          $this->assertTrue($types['group']);
 671      }
 672  
 673      public function test_calendar_get_allowed_event_types_group_no_access_all_groups() {
 674          $generator = $this->getDataGenerator();
 675          $user = $generator->create_user();
 676          $course = $generator->create_course();
 677          $context = context_course::instance($course->id);
 678          $group1 = $generator->create_group(array('courseid' => $course->id));
 679          $group2 = $generator->create_group(array('courseid' => $course->id));
 680          $roleid = $generator->create_role();
 681          $generator->enrol_user($user->id, $course->id, 'student');
 682          $generator->role_assign($roleid, $user->id, $context->id);
 683          $generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user->id));
 684          $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user->id));
 685          $this->setUser($user);
 686          assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
 687          // The user has the correct capability in the course but can't access
 688          // groups that they are not a member of.
 689          $types = calendar_get_allowed_event_types($course->id);
 690          $this->assertFalse($types['group']);
 691  
 692          // Same result applies when not providing a specific course as they are only on one course.
 693          $types = calendar_get_allowed_event_types();
 694          $this->assertFalse($types['group']);
 695  
 696          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 697          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
 698          $types = calendar_get_allowed_event_types($course->id);
 699          $this->assertTrue($types['group']);
 700  
 701          // Same result applies when not providing a specific course as they are only on one course.
 702          $types = calendar_get_allowed_event_types();
 703          $this->assertTrue($types['group']);
 704      }
 705  
 706      public function test_calendar_get_allowed_event_types_group_cap_no_groups() {
 707          $generator = $this->getDataGenerator();
 708          $user = $generator->create_user();
 709          $course = $generator->create_course();
 710          $context = context_course::instance($course->id);
 711          $roleid = $generator->create_role();
 712          $group = $generator->create_group(['courseid' => $course->id]);
 713          $generator->enrol_user($user->id, $course->id, 'student');
 714          $generator->role_assign($roleid, $user->id, $context->id);
 715          assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
 716  
 717          $this->setUser($user);
 718          $types = calendar_get_allowed_event_types($course->id);
 719          $this->assertFalse($types['course']);
 720          $this->assertFalse($types['group']);
 721  
 722          // Check without specifying a course (same result as user only has one course).
 723          $types = calendar_get_allowed_event_types();
 724          $this->assertFalse($types['course']);
 725          $this->assertFalse($types['group']);
 726      }
 727  
 728      public function test_calendar_get_allowed_event_types_group_cap_has_group() {
 729          $generator = $this->getDataGenerator();
 730          $user = $generator->create_user();
 731          $course = $generator->create_course();
 732          $context = context_course::instance($course->id);
 733          $roleid = $generator->create_role();
 734          $group = $generator->create_group(['courseid' => $course->id]);
 735          $generator->enrol_user($user->id, $course->id, 'student');
 736          $generator->role_assign($roleid, $user->id, $context->id);
 737          groups_add_member($group, $user);
 738          assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
 739  
 740          $this->setUser($user);
 741          $types = calendar_get_allowed_event_types($course->id);
 742          $this->assertFalse($types['course']);
 743          $this->assertTrue($types['group']);
 744  
 745          // Check without specifying a course (same result as user only has one course).
 746          $types = calendar_get_allowed_event_types();
 747          $this->assertFalse($types['course']);
 748          $this->assertTrue($types['group']);
 749      }
 750  
 751      public function test_calendar_get_allowed_event_types_group_cap_access_all_groups() {
 752          $generator = $this->getDataGenerator();
 753          $user = $generator->create_user();
 754          $course = $generator->create_course();
 755          $context = context_course::instance($course->id);
 756          $roleid = $generator->create_role();
 757          $group = $generator->create_group(['courseid' => $course->id]);
 758          $generator->enrol_user($user->id, $course->id, 'student');
 759          $generator->role_assign($roleid, $user->id, $context->id);
 760          assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
 761          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
 762  
 763          $this->setUser($user);
 764          $types = calendar_get_allowed_event_types($course->id);
 765          $this->assertFalse($types['course']);
 766          $this->assertTrue($types['group']);
 767  
 768          // Check without specifying a course (same result as user only has one course).
 769          $types = calendar_get_allowed_event_types();
 770          $this->assertFalse($types['course']);
 771          $this->assertTrue($types['group']);
 772      }
 773  
 774      /**
 775       * This is a setup helper function that create some users, courses, groups and group memberships.
 776       * This is useful to prepare the environment for testing the calendar_set_filters function.
 777       *
 778       * @return array An array of ($users, $courses, $coursegroups)
 779       */
 780      protected function setup_test_calendar_set_filters() {
 781          $generator = $this->getDataGenerator();
 782  
 783          // Create some users.
 784          $users = [];
 785          $users[] = $generator->create_user();
 786          $users[] = $generator->create_user();
 787          $users[] = $generator->create_user();
 788  
 789          // Create some courses.
 790          $courses = [];
 791          $courses[] = $generator->create_course();
 792          $courses[] = $generator->create_course();
 793          $courses[] = $generator->create_course();
 794          $courses[] = $generator->create_course();
 795  
 796          // Create some groups.
 797          $coursegroups = [];
 798          $coursegroups[$courses[0]->id] = [];
 799          $coursegroups[$courses[0]->id][] = $generator->create_group(['courseid' => $courses[0]->id]);
 800          $coursegroups[$courses[0]->id][] = $generator->create_group(['courseid' => $courses[0]->id]);
 801          $coursegroups[$courses[2]->id] = [];
 802          $coursegroups[$courses[2]->id][] = $generator->create_group(['courseid' => $courses[2]->id]);
 803          $coursegroups[$courses[2]->id][] = $generator->create_group(['courseid' => $courses[2]->id]);
 804          $coursegroups[$courses[3]->id] = [];
 805          $coursegroups[$courses[3]->id][] = $generator->create_group(['courseid' => $courses[3]->id]);
 806          $coursegroups[$courses[3]->id][] = $generator->create_group(['courseid' => $courses[3]->id]);
 807  
 808          // Create some enrolments and group memberships.
 809          $generator->enrol_user($users[0]->id, $courses[0]->id, 'student');
 810          $generator->create_group_member(['groupid' => $coursegroups[$courses[0]->id][0]->id, 'userid' => $users[0]->id]);
 811          $generator->enrol_user($users[1]->id, $courses[0]->id, 'student');
 812          $generator->create_group_member(['groupid' => $coursegroups[$courses[0]->id][1]->id, 'userid' => $users[1]->id]);
 813          $generator->enrol_user($users[0]->id, $courses[1]->id, 'student');
 814          $generator->enrol_user($users[0]->id, $courses[2]->id, 'student');
 815  
 816          return array($users, $courses, $coursegroups);
 817      }
 818  
 819      /**
 820       * This function tests calendar_set_filters for the case when user is not logged in.
 821       */
 822      public function test_calendar_set_filters_not_logged_in() {
 823          $this->resetAfterTest();
 824  
 825          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 826  
 827          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[0]->id);
 828          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses);
 829  
 830          $this->assertEqualsCanonicalizing(
 831                  [$courses[0]->id, $courses[1]->id, $courses[2]->id, SITEID],
 832                  array_values($courseids));
 833          $this->assertFalse($groupids);
 834          $this->assertFalse($userid);
 835      }
 836  
 837      /**
 838       * This function tests calendar_set_filters for the case when no one is logged in, but a user id is provided.
 839       */
 840      public function test_calendar_set_filters_not_logged_in_with_user() {
 841          $this->resetAfterTest();
 842  
 843          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 844  
 845          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[1]->id);
 846          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false, $users[1]);
 847  
 848          $this->assertEquals(array($courses[0]->id, SITEID), array_values($courseids));
 849          $this->assertEquals(array($coursegroups[$courses[0]->id][1]->id), $groupids);
 850          $this->assertEquals($users[1]->id, $userid);
 851  
 852          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[0]->id);
 853          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false, $users[0]);
 854  
 855          $this->assertEqualsCanonicalizing(
 856                  [$courses[0]->id, $courses[1]->id, $courses[2]->id, SITEID],
 857                  array_values($courseids));
 858          $this->assertEquals(array($coursegroups[$courses[0]->id][0]->id), $groupids);
 859          $this->assertEquals($users[0]->id, $userid);
 860  
 861      }
 862  
 863      /**
 864       * This function tests calendar_set_filters for the case when user is logged in, but no user id is provided.
 865       */
 866      public function test_calendar_set_filters_logged_in_no_user() {
 867          $this->resetAfterTest();
 868  
 869          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 870  
 871          $this->setUser($users[0]);
 872          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[0]->id);
 873          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false);
 874          $this->assertEqualsCanonicalizing([$courses[0]->id, $courses[1]->id, $courses[2]->id, SITEID], array_values($courseids));
 875          $this->assertEquals(array($coursegroups[$courses[0]->id][0]->id), $groupids);
 876          $this->assertEquals($users[0]->id, $userid);
 877      }
 878  
 879      /**
 880       * This function tests calendar_set_filters for the case when a user is logged in, but another user id is provided.
 881       */
 882      public function test_calendar_set_filters_logged_in_another_user() {
 883          $this->resetAfterTest();
 884  
 885          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 886  
 887          $this->setUser($users[0]);
 888          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[1]->id);
 889          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false, $users[1]);
 890  
 891          $this->assertEquals(array($courses[0]->id, SITEID), array_values($courseids));
 892          $this->assertEquals(array($coursegroups[$courses[0]->id][1]->id), $groupids);
 893          $this->assertEquals($users[1]->id, $userid);
 894      }
 895  
 896      /**
 897       *  Test for calendar_view_event_allowed for course event types.
 898       */
 899      public function test_calendar_view_event_allowed_course_event() {
 900          global $USER;
 901  
 902          $this->setAdminUser();
 903  
 904          $generator = $this->getDataGenerator();
 905  
 906          // A student in a course.
 907          $student = $generator->create_user();
 908          // Some user not enrolled in any course.
 909          $someuser = $generator->create_user();
 910  
 911          // A course with manual enrolments.
 912          $manualcourse = $generator->create_course();
 913  
 914          // Enrol the student to the manual enrolment course.
 915          $generator->enrol_user($student->id, $manualcourse->id);
 916  
 917          // A course that allows guest access.
 918          $guestcourse = $generator->create_course(
 919              (object)[
 920                  'shortname' => 'guestcourse',
 921                  'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
 922                  'enrol_guest_password_0' => ''
 923              ]);
 924  
 925          $manualevent = (object)[
 926              'name' => 'Manual course event',
 927              'description' => '',
 928              'format' => 1,
 929              'categoryid' => 0,
 930              'courseid' => $manualcourse->id,
 931              'groupid' => 0,
 932              'userid' => $USER->id,
 933              'modulename' => 0,
 934              'instance' => 0,
 935              'eventtype' => 'course',
 936              'timestart' => time(),
 937              'timeduration' => 86400,
 938              'visible' => 1
 939          ];
 940          $caleventmanual = calendar_event::create($manualevent, false);
 941  
 942          // Create a course event for the course with guest access.
 943          $guestevent = clone $manualevent;
 944          $guestevent->name = 'Guest course event';
 945          $guestevent->courseid = $guestcourse->id;
 946          $caleventguest = calendar_event::create($guestevent, false);
 947  
 948          // Viewing as admin.
 949          $this->assertTrue(calendar_view_event_allowed($caleventmanual));
 950          $this->assertTrue(calendar_view_event_allowed($caleventguest));
 951  
 952          // Viewing as someone enrolled in a course.
 953          $this->setUser($student);
 954          $this->assertTrue(calendar_view_event_allowed($caleventmanual));
 955  
 956          // Viewing as someone not enrolled in any course.
 957          $this->setUser($someuser);
 958          // Viewing as someone not enrolled in a course without guest access on.
 959          $this->assertFalse(calendar_view_event_allowed($caleventmanual));
 960          // Viewing as someone not enrolled in a course with guest access on.
 961          $this->assertTrue(calendar_view_event_allowed($caleventguest));
 962      }
 963  
 964      /**
 965       *  Test for calendar_get_export_token for current user.
 966       */
 967      public function test_calendar_get_export_token_for_current_user() {
 968          global $USER, $DB, $CFG;
 969  
 970          $this->setAdminUser();
 971  
 972          // Get my token.
 973          $authtoken = calendar_get_export_token($USER);
 974          $expected = sha1($USER->id . $DB->get_field('user', 'password', ['id' => $USER->id]) . $CFG->calendar_exportsalt);
 975  
 976          $this->assertEquals($expected, $authtoken);
 977      }
 978  
 979      /**
 980       *  Test for calendar_get_export_token for another user.
 981       */
 982      public function test_calendar_get_export_token_for_another_user() {
 983          global $CFG;
 984  
 985          // Get any user token.
 986          $generator = $this->getDataGenerator();
 987          $user = $generator->create_user();
 988  
 989          // Get other user token.
 990          $authtoken = calendar_get_export_token($user);
 991          $expected = sha1($user->id . $user->password . $CFG->calendar_exportsalt);
 992  
 993          $this->assertEquals($expected, $authtoken);
 994      }
 995  
 996      /**
 997       *  Test calendar_can_manage_user_event for different users.
 998       *
 999       * @covers ::calendar_can_manage_user_event
1000       */
1001      public function test_calendar_can_manage_user_event() {
1002          global $DB, $USER;
1003          $generator = $this->getDataGenerator();
1004          $sitecontext = context_system::instance();
1005          $this->resetAfterTest();
1006          $this->setAdminUser();
1007          $user1 = $generator->create_user();
1008          $user2 = $generator->create_user();
1009          $adminevent = create_event([
1010              'eventtype' => 'user',
1011              'userid' => $USER->id,
1012          ]);
1013  
1014          $this->setUser($user1);
1015          $user1event = create_event([
1016              'name' => 'user1 event',
1017              'eventtype' => 'user',
1018              'userid' => $user1->id,
1019          ]);
1020          $this->setUser($user2);
1021          $user2event = create_event([
1022              'name' => 'user2 event',
1023              'eventtype' => 'user',
1024              'userid' => $user2->id,
1025          ]);
1026          $this->setUser($user1);
1027          $result = calendar_can_manage_user_event($user1event);
1028          $this->assertEquals(true, $result);
1029          $result = calendar_can_manage_user_event($user2event);
1030          $this->assertEquals(false, $result);
1031  
1032          $sitemanager = $generator->create_user();
1033  
1034          $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
1035          role_assign($managerroleid, $sitemanager->id, $sitecontext->id);
1036  
1037          $this->setUser($sitemanager);
1038  
1039          $result = calendar_can_manage_user_event($user1event);
1040          $this->assertEquals(true, $result);
1041          $result = calendar_can_manage_user_event($adminevent);
1042          $this->assertEquals(false, $result);
1043      }
1044  }