Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

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

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  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_events_from_ical($ical, $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_events_from_ical($ical, $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_events_from_ical($ical, $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_events_from_ical($ical, $sub->id);
 245          $this->assertArrayHasKey('eventsimported', $output);
 246          $this->assertArrayHasKey('eventsskipped', $output);
 247          $this->assertArrayHasKey('eventsupdated', $output);
 248          $this->assertArrayHasKey('eventsdeleted', $output);
 249          $this->assertEquals(1, $output['eventsimported']);
 250          $this->assertEquals(0, $output['eventsskipped']);
 251          $this->assertEquals(0, $output['eventsupdated']);
 252          $this->assertEquals(0, $output['eventsdeleted']);
 253      }
 254  
 255      /**
 256       * Test for calendar_get_legacy_events() when there are user and group overrides.
 257       */
 258      public function test_get_legacy_events_with_overrides() {
 259          $generator = $this->getDataGenerator();
 260  
 261          $course = $generator->create_course();
 262  
 263          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 264          if (!isset($params['course'])) {
 265              $params['course'] = $course->id;
 266          }
 267  
 268          $instance = $plugingenerator->create_instance($params);
 269  
 270          // Create users.
 271          $useroverridestudent = $generator->create_user();
 272          $group1student = $generator->create_user();
 273          $group2student = $generator->create_user();
 274          $group12student = $generator->create_user();
 275          $nogroupstudent = $generator->create_user();
 276  
 277          // Enrol users.
 278          $generator->enrol_user($useroverridestudent->id, $course->id, 'student');
 279          $generator->enrol_user($group1student->id, $course->id, 'student');
 280          $generator->enrol_user($group2student->id, $course->id, 'student');
 281          $generator->enrol_user($group12student->id, $course->id, 'student');
 282          $generator->enrol_user($nogroupstudent->id, $course->id, 'student');
 283  
 284          // Create groups.
 285          $group1 = $generator->create_group(['courseid' => $course->id]);
 286          $group2 = $generator->create_group(['courseid' => $course->id]);
 287  
 288          // Add members to groups.
 289          $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
 290          $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
 291          $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
 292          $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
 293          $now = time();
 294  
 295          // Events with the same module name, instance and event type.
 296          $events = [
 297              [
 298                  'name' => 'Assignment 1 due date',
 299                  'description' => '',
 300                  'location' => 'Test',
 301                  'format' => 0,
 302                  'courseid' => $course->id,
 303                  'groupid' => 0,
 304                  'userid' => 2,
 305                  'modulename' => 'assign',
 306                  'instance' => $instance->id,
 307                  'eventtype' => 'due',
 308                  'timestart' => $now,
 309                  'timeduration' => 0,
 310                  'visible' => 1
 311              ], [
 312                  'name' => 'Assignment 1 due date - User override',
 313                  'description' => '',
 314                  'location' => 'Test',
 315                  'format' => 1,
 316                  'courseid' => 0,
 317                  'groupid' => 0,
 318                  'userid' => $useroverridestudent->id,
 319                  'modulename' => 'assign',
 320                  'instance' => $instance->id,
 321                  'eventtype' => 'due',
 322                  'timestart' => $now + 86400,
 323                  'timeduration' => 0,
 324                  'visible' => 1,
 325                  'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
 326              ], [
 327                  'name' => 'Assignment 1 due date - Group A override',
 328                  'description' => '',
 329                  'location' => 'Test',
 330                  'format' => 1,
 331                  'courseid' => $course->id,
 332                  'groupid' => $group1->id,
 333                  'userid' => 2,
 334                  'modulename' => 'assign',
 335                  'instance' => $instance->id,
 336                  'eventtype' => 'due',
 337                  'timestart' => $now + (2 * 86400),
 338                  'timeduration' => 0,
 339                  'visible' => 1,
 340                  'priority' => 1,
 341              ], [
 342                  'name' => 'Assignment 1 due date - Group B override',
 343                  'description' => '',
 344                  'location' => 'Test',
 345                  'format' => 1,
 346                  'courseid' => $course->id,
 347                  'groupid' => $group2->id,
 348                  'userid' => 2,
 349                  'modulename' => 'assign',
 350                  'instance' => $instance->id,
 351                  'eventtype' => 'due',
 352                  'timestart' => $now + (3 * 86400),
 353                  'timeduration' => 0,
 354                  'visible' => 1,
 355                  'priority' => 2,
 356              ],
 357          ];
 358  
 359          foreach ($events as $event) {
 360              \calendar_event::create($event, false);
 361          }
 362  
 363          $timestart = $now - 100;
 364          $timeend = $now + (3 * 86400);
 365          $groups = [$group1->id, $group2->id];
 366  
 367          // Get user override events.
 368          $this->setUser($useroverridestudent);
 369          $events = calendar_get_legacy_events($timestart, $timeend, $useroverridestudent->id, $groups, $course->id);
 370          $this->assertCount(1, $events);
 371          $event = reset($events);
 372          $this->assertEquals('Assignment 1 due date - User override', $event->name);
 373  
 374          // Get event for user with override but with the timestart and timeend parameters only covering the original event.
 375          $events = calendar_get_legacy_events($timestart, $now, $useroverridestudent->id, $groups, $course->id);
 376          $this->assertCount(0, $events);
 377  
 378          // Get events for user that does not belong to any group and has no user override events.
 379          $this->setUser($nogroupstudent);
 380          $events = calendar_get_legacy_events($timestart, $timeend, $nogroupstudent->id, $groups, $course->id);
 381          $this->assertCount(1, $events);
 382          $event = reset($events);
 383          $this->assertEquals('Assignment 1 due date', $event->name);
 384  
 385          // Get events for user that belongs to groups A and B and has no user override events.
 386          $this->setUser($group12student);
 387          $events = calendar_get_legacy_events($timestart, $timeend, $group12student->id, $groups, $course->id);
 388          $this->assertCount(1, $events);
 389          $event = reset($events);
 390          $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
 391  
 392          // Get events for user that belongs to group A and has no user override events.
 393          $this->setUser($group1student);
 394          $events = calendar_get_legacy_events($timestart, $timeend, $group1student->id, $groups, $course->id);
 395          $this->assertCount(1, $events);
 396          $event = reset($events);
 397          $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
 398  
 399          // Add repeating events.
 400          $repeatingevents = [
 401              [
 402                  'name' => 'Repeating site event',
 403                  'description' => '',
 404                  'location' => 'Test',
 405                  'format' => 1,
 406                  'courseid' => SITEID,
 407                  'groupid' => 0,
 408                  'userid' => 2,
 409                  'repeatid' => $event->id,
 410                  'modulename' => '0',
 411                  'instance' => 0,
 412                  'eventtype' => 'site',
 413                  'timestart' => $now + 86400,
 414                  'timeduration' => 0,
 415                  'visible' => 1,
 416              ],
 417              [
 418                  'name' => 'Repeating site event',
 419                  'description' => '',
 420                  'location' => 'Test',
 421                  'format' => 1,
 422                  'courseid' => SITEID,
 423                  'groupid' => 0,
 424                  'userid' => 2,
 425                  'repeatid' => $event->id,
 426                  'modulename' => '0',
 427                  'instance' => 0,
 428                  'eventtype' => 'site',
 429                  'timestart' => $now + (2 * 86400),
 430                  'timeduration' => 0,
 431                  'visible' => 1,
 432              ],
 433          ];
 434  
 435          foreach ($repeatingevents as $event) {
 436              \calendar_event::create($event, false);
 437          }
 438  
 439          // Make sure repeating events are not filtered out.
 440          $events = calendar_get_legacy_events($timestart, $timeend, true, true, true);
 441          $this->assertCount(3, $events);
 442      }
 443  
 444      public function test_calendar_get_default_courses() {
 445          global $USER, $CFG;
 446  
 447          $this->resetAfterTest(true);
 448  
 449          $generator = $this->getDataGenerator();
 450          $user = $generator->create_user();
 451          $course1 = $generator->create_course();
 452          $course2 = $generator->create_course();
 453          $course3 = $generator->create_course();
 454          $context = \context_course::instance($course1->id);
 455  
 456          $this->setAdminUser();
 457          $admin = clone $USER;
 458  
 459          $teacher = $generator->create_user();
 460          $generator->enrol_user($teacher->id, $course1->id, 'teacher');
 461          $generator->enrol_user($admin->id, $course1->id, 'teacher');
 462  
 463          $CFG->calendar_adminseesall = false;
 464  
 465          $courses = calendar_get_default_courses();
 466          // Only enrolled in one course.
 467          $this->assertCount(1, $courses);
 468          $courses = calendar_get_default_courses($course2->id);
 469          // Enrolled course + current course.
 470          $this->assertCount(2, $courses);
 471          $CFG->calendar_adminseesall = true;
 472          $courses = calendar_get_default_courses();
 473          // All courses + SITE.
 474          $this->assertCount(4, $courses);
 475          $courses = calendar_get_default_courses($course2->id);
 476          // All courses + SITE.
 477          $this->assertCount(4, $courses);
 478  
 479          $this->setUser($teacher);
 480  
 481          $CFG->calendar_adminseesall = false;
 482  
 483          $courses = calendar_get_default_courses();
 484          // Only enrolled in one course.
 485          $this->assertCount(1, $courses);
 486          $courses = calendar_get_default_courses($course2->id);
 487          // Enrolled course only (ignore current).
 488          $this->assertCount(1, $courses);
 489          // This setting should not affect teachers.
 490          $CFG->calendar_adminseesall = true;
 491          $courses = calendar_get_default_courses();
 492          // Only enrolled in one course.
 493          $this->assertCount(1, $courses);
 494          $courses = calendar_get_default_courses($course2->id);
 495          // Enrolled course only (ignore current).
 496          $this->assertCount(1, $courses);
 497  
 498          // Now, log out and test again.
 499          $this->setUser();
 500  
 501          $CFG->calendar_adminseesall = false;
 502  
 503          $courses = calendar_get_default_courses(null, '*', false, $teacher->id);
 504          // Only enrolled in one course.
 505          $this->assertCount(1, $courses);
 506          $courses = calendar_get_default_courses($course2->id, '*', false, $teacher->id);
 507          // Enrolled course only (ignore current).
 508          $this->assertCount(1, $courses);
 509          // This setting should not affect teachers.
 510          $CFG->calendar_adminseesall = true;
 511          $courses = calendar_get_default_courses(null, '*', false, $teacher->id);
 512          // Only enrolled in one course.
 513          $this->assertCount(1, $courses);
 514          $courses = calendar_get_default_courses($course2->id, '*', false, $teacher->id);
 515          // Enrolled course only (ignore current).
 516          $this->assertCount(1, $courses);
 517  
 518      }
 519  
 520      /**
 521       * Confirm that the skip events flag causes the calendar_get_view function
 522       * to avoid querying for the calendar events.
 523       */
 524      public function test_calendar_get_view_skip_events() {
 525          $this->resetAfterTest(true);
 526          $this->setAdminUser();
 527  
 528          $generator = $this->getDataGenerator();
 529          $user = $generator->create_user();
 530          $skipnavigation = true;
 531          $skipevents = true;
 532          $event = create_event([
 533              'eventtype' => 'user',
 534              'userid' => $user->id
 535          ]);
 536  
 537          $this->setUser($user);
 538          $calendar = \calendar_information::create(time() - 10, SITEID, null);
 539  
 540          list($data, $template) = calendar_get_view($calendar, 'day', $skipnavigation, $skipevents);
 541          $this->assertEmpty($data->events);
 542  
 543          $skipevents = false;
 544          list($data, $template) = calendar_get_view($calendar, 'day', $skipnavigation, $skipevents);
 545  
 546          $this->assertEquals($event->id, $data->events[0]->id);
 547      }
 548  
 549      public function test_calendar_get_allowed_event_types_course() {
 550          $generator = $this->getDataGenerator();
 551          $user = $generator->create_user();
 552          $course1 = $generator->create_course(); // Has capability.
 553          $course2 = $generator->create_course(); // Doesn't have capability.
 554          $course3 = $generator->create_course(); // Not enrolled.
 555          $context1 = \context_course::instance($course1->id);
 556          $context2 = \context_course::instance($course2->id);
 557          $context3 = \context_course::instance($course3->id);
 558          $roleid = $generator->create_role();
 559          $contexts = [$context1, $context2, $context3];
 560          $enrolledcourses = [$course1, $course2];
 561  
 562          foreach ($enrolledcourses as $course) {
 563              $generator->enrol_user($user->id, $course->id, 'student');
 564          }
 565  
 566          foreach ($contexts as $context) {
 567              $generator->role_assign($roleid, $user->id, $context->id);
 568          }
 569  
 570          $this->setUser($user);
 571  
 572          // In general for all courses, they don't have the ability to add course events yet.
 573          $types = calendar_get_allowed_event_types();
 574          $this->assertFalse($types['course']);
 575  
 576          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
 577          assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context2, true);
 578  
 579          // The user only has the correct capability in course 1 so that is the only
 580          // one that should be in the results.
 581          $types = calendar_get_allowed_event_types($course1->id);
 582          $this->assertTrue($types['course']);
 583  
 584          // If calling function without specified course,  there is still a course where they have it.
 585          $types = calendar_get_allowed_event_types();
 586          $this->assertTrue($types['course']);
 587  
 588          assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context1, true);
 589  
 590          // The user only now has the correct capability in both course 1 and 2 so we
 591          // expect both to be in the results.
 592          $types = calendar_get_allowed_event_types($course3->id);
 593          $this->assertFalse($types['course']);
 594  
 595          // They now do not have permission in any course.
 596          $types = calendar_get_allowed_event_types();
 597          $this->assertFalse($types['course']);
 598      }
 599  
 600      public function test_calendar_get_allowed_event_types_group_no_acces_to_diff_groups() {
 601          $generator = $this->getDataGenerator();
 602          $user = $generator->create_user();
 603          $course = $generator->create_course();
 604          $context = \context_course::instance($course->id);
 605          $roleid = $generator->create_role();
 606  
 607          $generator->enrol_user($user->id, $course->id, 'student');
 608          $generator->role_assign($roleid, $user->id, $context->id);
 609  
 610          $this->setUser($user);
 611  
 612          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 613          assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
 614  
 615          // The user has the correct capability in the course but they aren't a member
 616          // of any of the groups and don't have the accessallgroups capability.
 617          $types = calendar_get_allowed_event_types($course->id);
 618          $this->assertTrue($types['course']);
 619          $this->assertFalse($types['group']);
 620  
 621          // Same result applies when not providing a specific course as they are only on one course.
 622          $types = calendar_get_allowed_event_types();
 623          $this->assertTrue($types['course']);
 624          $this->assertFalse($types['group']);
 625      }
 626  
 627      public function test_calendar_get_allowed_event_types_group_no_groups() {
 628          $generator = $this->getDataGenerator();
 629          $user = $generator->create_user();
 630          $course = $generator->create_course();
 631          $context = \context_course::instance($course->id);
 632          $roleid = $generator->create_role();
 633          $generator->enrol_user($user->id, $course->id, 'student');
 634          $generator->role_assign($roleid, $user->id, $context->id);
 635          $this->setUser($user);
 636          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 637          // The user has the correct capability in the course but there are
 638          // no groups so we shouldn't see a group type.
 639          $types = calendar_get_allowed_event_types($course->id);
 640          $this->assertTrue($types['course']);
 641          $this->assertFalse($types['group']);
 642  
 643          // Same result applies when not providing a specific course as they are only on one course.
 644          $types = calendar_get_allowed_event_types();
 645          $this->assertTrue($types['course']);
 646          $this->assertFalse($types['group']);
 647      }
 648  
 649      public function test_calendar_get_allowed_event_types_group_access_all_groups() {
 650          $generator = $this->getDataGenerator();
 651          $user = $generator->create_user();
 652          $course1 = $generator->create_course();
 653          $course2 = $generator->create_course();
 654          $generator->create_group(array('courseid' => $course1->id));
 655          $generator->create_group(array('courseid' => $course2->id));
 656          $context1 = \context_course::instance($course1->id);
 657          $context2 = \context_course::instance($course2->id);
 658          $roleid = $generator->create_role();
 659          $generator->enrol_user($user->id, $course1->id, 'student');
 660          $generator->enrol_user($user->id, $course2->id, 'student');
 661          $generator->role_assign($roleid, $user->id, $context1->id);
 662          $generator->role_assign($roleid, $user->id, $context2->id);
 663          $this->setUser($user);
 664          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context1, true);
 665          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context2, true);
 666          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context1, true);
 667          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context2, true);
 668          // The user has the correct capability in the course and has
 669          // the accessallgroups capability.
 670          $types = calendar_get_allowed_event_types($course1->id);
 671          $this->assertTrue($types['group']);
 672  
 673          // Same result applies when not providing a specific course as they are only on one course.
 674          $types = calendar_get_allowed_event_types();
 675          $this->assertTrue($types['group']);
 676      }
 677  
 678      public function test_calendar_get_allowed_event_types_group_no_access_all_groups() {
 679          $generator = $this->getDataGenerator();
 680          $user = $generator->create_user();
 681          $course = $generator->create_course();
 682          $context = \context_course::instance($course->id);
 683          $group1 = $generator->create_group(array('courseid' => $course->id));
 684          $group2 = $generator->create_group(array('courseid' => $course->id));
 685          $roleid = $generator->create_role();
 686          $generator->enrol_user($user->id, $course->id, 'student');
 687          $generator->role_assign($roleid, $user->id, $context->id);
 688          $generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user->id));
 689          $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user->id));
 690          $this->setUser($user);
 691          assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);
 692          // The user has the correct capability in the course but can't access
 693          // groups that they are not a member of.
 694          $types = calendar_get_allowed_event_types($course->id);
 695          $this->assertFalse($types['group']);
 696  
 697          // Same result applies when not providing a specific course as they are only on one course.
 698          $types = calendar_get_allowed_event_types();
 699          $this->assertFalse($types['group']);
 700  
 701          assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);
 702          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
 703          $types = calendar_get_allowed_event_types($course->id);
 704          $this->assertTrue($types['group']);
 705  
 706          // Same result applies when not providing a specific course as they are only on one course.
 707          $types = calendar_get_allowed_event_types();
 708          $this->assertTrue($types['group']);
 709      }
 710  
 711      public function test_calendar_get_allowed_event_types_group_cap_no_groups() {
 712          $generator = $this->getDataGenerator();
 713          $user = $generator->create_user();
 714          $course = $generator->create_course();
 715          $context = \context_course::instance($course->id);
 716          $roleid = $generator->create_role();
 717          $group = $generator->create_group(['courseid' => $course->id]);
 718          $generator->enrol_user($user->id, $course->id, 'student');
 719          $generator->role_assign($roleid, $user->id, $context->id);
 720          assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
 721  
 722          $this->setUser($user);
 723          $types = calendar_get_allowed_event_types($course->id);
 724          $this->assertFalse($types['course']);
 725          $this->assertFalse($types['group']);
 726  
 727          // Check without specifying a course (same result as user only has one course).
 728          $types = calendar_get_allowed_event_types();
 729          $this->assertFalse($types['course']);
 730          $this->assertFalse($types['group']);
 731      }
 732  
 733      public function test_calendar_get_allowed_event_types_group_cap_has_group() {
 734          $generator = $this->getDataGenerator();
 735          $user = $generator->create_user();
 736          $course = $generator->create_course();
 737          $context = \context_course::instance($course->id);
 738          $roleid = $generator->create_role();
 739          $group = $generator->create_group(['courseid' => $course->id]);
 740          $generator->enrol_user($user->id, $course->id, 'student');
 741          $generator->role_assign($roleid, $user->id, $context->id);
 742          groups_add_member($group, $user);
 743          assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
 744  
 745          $this->setUser($user);
 746          $types = calendar_get_allowed_event_types($course->id);
 747          $this->assertFalse($types['course']);
 748          $this->assertTrue($types['group']);
 749  
 750          // Check without specifying a course (same result as user only has one course).
 751          $types = calendar_get_allowed_event_types();
 752          $this->assertFalse($types['course']);
 753          $this->assertTrue($types['group']);
 754      }
 755  
 756      public function test_calendar_get_allowed_event_types_group_cap_access_all_groups() {
 757          $generator = $this->getDataGenerator();
 758          $user = $generator->create_user();
 759          $course = $generator->create_course();
 760          $context = \context_course::instance($course->id);
 761          $roleid = $generator->create_role();
 762          $group = $generator->create_group(['courseid' => $course->id]);
 763          $generator->enrol_user($user->id, $course->id, 'student');
 764          $generator->role_assign($roleid, $user->id, $context->id);
 765          assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);
 766          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);
 767  
 768          $this->setUser($user);
 769          $types = calendar_get_allowed_event_types($course->id);
 770          $this->assertFalse($types['course']);
 771          $this->assertTrue($types['group']);
 772  
 773          // Check without specifying a course (same result as user only has one course).
 774          $types = calendar_get_allowed_event_types();
 775          $this->assertFalse($types['course']);
 776          $this->assertTrue($types['group']);
 777      }
 778  
 779      /**
 780       * This is a setup helper function that create some users, courses, groups and group memberships.
 781       * This is useful to prepare the environment for testing the calendar_set_filters function.
 782       *
 783       * @return array An array of ($users, $courses, $coursegroups)
 784       */
 785      protected function setup_test_calendar_set_filters() {
 786          $generator = $this->getDataGenerator();
 787  
 788          // Create some users.
 789          $users = [];
 790          $users[] = $generator->create_user();
 791          $users[] = $generator->create_user();
 792          $users[] = $generator->create_user();
 793  
 794          // Create some courses.
 795          $courses = [];
 796          $courses[] = $generator->create_course();
 797          $courses[] = $generator->create_course();
 798          $courses[] = $generator->create_course();
 799          $courses[] = $generator->create_course();
 800  
 801          // Create some groups.
 802          $coursegroups = [];
 803          $coursegroups[$courses[0]->id] = [];
 804          $coursegroups[$courses[0]->id][] = $generator->create_group(['courseid' => $courses[0]->id]);
 805          $coursegroups[$courses[0]->id][] = $generator->create_group(['courseid' => $courses[0]->id]);
 806          $coursegroups[$courses[2]->id] = [];
 807          $coursegroups[$courses[2]->id][] = $generator->create_group(['courseid' => $courses[2]->id]);
 808          $coursegroups[$courses[2]->id][] = $generator->create_group(['courseid' => $courses[2]->id]);
 809          $coursegroups[$courses[3]->id] = [];
 810          $coursegroups[$courses[3]->id][] = $generator->create_group(['courseid' => $courses[3]->id]);
 811          $coursegroups[$courses[3]->id][] = $generator->create_group(['courseid' => $courses[3]->id]);
 812  
 813          // Create some enrolments and group memberships.
 814          $generator->enrol_user($users[0]->id, $courses[0]->id, 'student');
 815          $generator->create_group_member(['groupid' => $coursegroups[$courses[0]->id][0]->id, 'userid' => $users[0]->id]);
 816          $generator->enrol_user($users[1]->id, $courses[0]->id, 'student');
 817          $generator->create_group_member(['groupid' => $coursegroups[$courses[0]->id][1]->id, 'userid' => $users[1]->id]);
 818          $generator->enrol_user($users[0]->id, $courses[1]->id, 'student');
 819          $generator->enrol_user($users[0]->id, $courses[2]->id, 'student');
 820  
 821          return array($users, $courses, $coursegroups);
 822      }
 823  
 824      /**
 825       * This function tests calendar_set_filters for the case when user is not logged in.
 826       */
 827      public function test_calendar_set_filters_not_logged_in() {
 828          $this->resetAfterTest();
 829  
 830          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 831  
 832          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[0]->id);
 833          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses);
 834  
 835          $this->assertEqualsCanonicalizing(
 836                  [$courses[0]->id, $courses[1]->id, $courses[2]->id, SITEID],
 837                  array_values($courseids));
 838          $this->assertFalse($groupids);
 839          $this->assertFalse($userid);
 840      }
 841  
 842      /**
 843       * This function tests calendar_set_filters for the case when no one is logged in, but a user id is provided.
 844       */
 845      public function test_calendar_set_filters_not_logged_in_with_user() {
 846          $this->resetAfterTest();
 847  
 848          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 849  
 850          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[1]->id);
 851          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false, $users[1]);
 852  
 853          $this->assertEquals(array($courses[0]->id, SITEID), array_values($courseids));
 854          $this->assertEquals(array($coursegroups[$courses[0]->id][1]->id), $groupids);
 855          $this->assertEquals($users[1]->id, $userid);
 856  
 857          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[0]->id);
 858          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false, $users[0]);
 859  
 860          $this->assertEqualsCanonicalizing(
 861                  [$courses[0]->id, $courses[1]->id, $courses[2]->id, SITEID],
 862                  array_values($courseids));
 863          $this->assertEquals(array($coursegroups[$courses[0]->id][0]->id), $groupids);
 864          $this->assertEquals($users[0]->id, $userid);
 865  
 866      }
 867  
 868      /**
 869       * This function tests calendar_set_filters for the case when user is logged in, but no user id is provided.
 870       */
 871      public function test_calendar_set_filters_logged_in_no_user() {
 872          $this->resetAfterTest();
 873  
 874          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 875  
 876          $this->setUser($users[0]);
 877          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[0]->id);
 878          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false);
 879          $this->assertEqualsCanonicalizing([$courses[0]->id, $courses[1]->id, $courses[2]->id, SITEID], array_values($courseids));
 880          $this->assertEquals(array($coursegroups[$courses[0]->id][0]->id), $groupids);
 881          $this->assertEquals($users[0]->id, $userid);
 882      }
 883  
 884      /**
 885       * This function tests calendar_set_filters for the case when a user is logged in, but another user id is provided.
 886       */
 887      public function test_calendar_set_filters_logged_in_another_user() {
 888          $this->resetAfterTest();
 889  
 890          list($users, $courses, $coursegroups) = $this->setup_test_calendar_set_filters();
 891  
 892          $this->setUser($users[0]);
 893          $defaultcourses = calendar_get_default_courses(null, '*', false, $users[1]->id);
 894          list($courseids, $groupids, $userid) = calendar_set_filters($defaultcourses, false, $users[1]);
 895  
 896          $this->assertEquals(array($courses[0]->id, SITEID), array_values($courseids));
 897          $this->assertEquals(array($coursegroups[$courses[0]->id][1]->id), $groupids);
 898          $this->assertEquals($users[1]->id, $userid);
 899      }
 900  
 901      /**
 902       *  Test for calendar_view_event_allowed for course event types.
 903       */
 904      public function test_calendar_view_event_allowed_course_event() {
 905          global $USER;
 906  
 907          $this->setAdminUser();
 908  
 909          $generator = $this->getDataGenerator();
 910  
 911          // A student in a course.
 912          $student = $generator->create_user();
 913          // Some user not enrolled in any course.
 914          $someuser = $generator->create_user();
 915  
 916          // A course with manual enrolments.
 917          $manualcourse = $generator->create_course();
 918  
 919          // Enrol the student to the manual enrolment course.
 920          $generator->enrol_user($student->id, $manualcourse->id);
 921  
 922          // A course that allows guest access.
 923          $guestcourse = $generator->create_course(
 924              (object)[
 925                  'shortname' => 'guestcourse',
 926                  'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
 927                  'enrol_guest_password_0' => ''
 928              ]);
 929  
 930          $manualevent = (object)[
 931              'name' => 'Manual course event',
 932              'description' => '',
 933              'format' => 1,
 934              'categoryid' => 0,
 935              'courseid' => $manualcourse->id,
 936              'groupid' => 0,
 937              'userid' => $USER->id,
 938              'modulename' => 0,
 939              'instance' => 0,
 940              'eventtype' => 'course',
 941              'timestart' => time(),
 942              'timeduration' => 86400,
 943              'visible' => 1
 944          ];
 945          $caleventmanual = \calendar_event::create($manualevent, false);
 946  
 947          // Create a course event for the course with guest access.
 948          $guestevent = clone $manualevent;
 949          $guestevent->name = 'Guest course event';
 950          $guestevent->courseid = $guestcourse->id;
 951          $caleventguest = \calendar_event::create($guestevent, false);
 952  
 953          // Viewing as admin.
 954          $this->assertTrue(calendar_view_event_allowed($caleventmanual));
 955          $this->assertTrue(calendar_view_event_allowed($caleventguest));
 956  
 957          // Viewing as someone enrolled in a course.
 958          $this->setUser($student);
 959          $this->assertTrue(calendar_view_event_allowed($caleventmanual));
 960  
 961          // Viewing as someone not enrolled in any course.
 962          $this->setUser($someuser);
 963          // Viewing as someone not enrolled in a course without guest access on.
 964          $this->assertFalse(calendar_view_event_allowed($caleventmanual));
 965          // Viewing as someone not enrolled in a course with guest access on.
 966          $this->assertTrue(calendar_view_event_allowed($caleventguest));
 967      }
 968  
 969      /**
 970       *  Test for calendar_get_export_token for current user.
 971       */
 972      public function test_calendar_get_export_token_for_current_user() {
 973          global $USER, $DB, $CFG;
 974  
 975          $this->setAdminUser();
 976  
 977          // Get my token.
 978          $authtoken = calendar_get_export_token($USER);
 979          $expected = sha1($USER->id . $DB->get_field('user', 'password', ['id' => $USER->id]) . $CFG->calendar_exportsalt);
 980  
 981          $this->assertEquals($expected, $authtoken);
 982      }
 983  
 984      /**
 985       *  Test for calendar_get_export_token for another user.
 986       */
 987      public function test_calendar_get_export_token_for_another_user() {
 988          global $CFG;
 989  
 990          // Get any user token.
 991          $generator = $this->getDataGenerator();
 992          $user = $generator->create_user();
 993  
 994          // Get other user token.
 995          $authtoken = calendar_get_export_token($user);
 996          $expected = sha1($user->id . $user->password . $CFG->calendar_exportsalt);
 997  
 998          $this->assertEquals($expected, $authtoken);
 999      }
1000  
1001      /**
1002       *  Test calendar_can_manage_user_event for different users.
1003       *
1004       * @covers ::calendar_can_manage_user_event
1005       */
1006      public function test_calendar_can_manage_user_event() {
1007          global $DB, $USER;
1008          $generator = $this->getDataGenerator();
1009          $sitecontext = \context_system::instance();
1010          $this->resetAfterTest();
1011          $this->setAdminUser();
1012          $user1 = $generator->create_user();
1013          $user2 = $generator->create_user();
1014          $adminevent = create_event([
1015              'eventtype' => 'user',
1016              'userid' => $USER->id,
1017          ]);
1018  
1019          $this->setUser($user1);
1020          $user1event = create_event([
1021              'name' => 'user1 event',
1022              'eventtype' => 'user',
1023              'userid' => $user1->id,
1024          ]);
1025          $this->setUser($user2);
1026          $user2event = create_event([
1027              'name' => 'user2 event',
1028              'eventtype' => 'user',
1029              'userid' => $user2->id,
1030          ]);
1031          $this->setUser($user1);
1032          $result = calendar_can_manage_user_event($user1event);
1033          $this->assertEquals(true, $result);
1034          $result = calendar_can_manage_user_event($user2event);
1035          $this->assertEquals(false, $result);
1036  
1037          $sitemanager = $generator->create_user();
1038  
1039          $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
1040          role_assign($managerroleid, $sitemanager->id, $sitecontext->id);
1041  
1042          $this->setUser($sitemanager);
1043  
1044          $result = calendar_can_manage_user_event($user1event);
1045          $this->assertEquals(true, $result);
1046          $result = calendar_can_manage_user_event($adminevent);
1047          $this->assertEquals(false, $result);
1048      }
1049  }