Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

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

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