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  namespace core_calendar;
  18  
  19  use core_calendar\local\event\container;
  20  
  21  defined('MOODLE_INTERNAL') || die();
  22  
  23  require_once (__DIR__ . '/helpers.php');
  24  
  25  /**
  26   * Class contaning unit tests for the calendar local API.
  27   *
  28   * @package    core_calendar
  29   * @copyright  2017 Mark Nelson <markn@moodle.com>
  30   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   */
  32  class local_api_test extends \advanced_testcase {
  33  
  34      /**
  35       * Tests set up
  36       */
  37      protected function setUp(): void {
  38          $this->resetAfterTest();
  39      }
  40  
  41      /**
  42       * Create a feedback activity instance and a calendar event for
  43       * that instance.
  44       *
  45       * @param array $feedbackproperties Properties to set on the feedback activity
  46       * @param array $eventproperties Properties to set on the calendar event
  47       * @return array The feedback activity and the calendar event
  48       */
  49      protected function create_feedback_activity_and_event(array $feedbackproperties = [], array $eventproperties = []) {
  50          $generator = $this->getDataGenerator();
  51          $course = $generator->create_course();
  52          $mapper = container::get_event_mapper();
  53          $feedbackgenerator = $generator->get_plugin_generator('mod_feedback');
  54          $feedback = $feedbackgenerator->create_instance(array_merge(
  55              ['course' => $course->id],
  56              $feedbackproperties
  57          ));
  58  
  59          $event = create_event(array_merge(
  60              [
  61                  'courseid' => $course->id,
  62                  'modulename' => 'feedback',
  63                  'instance' => $feedback->id
  64              ],
  65               $eventproperties
  66          ));
  67          $event = $mapper->from_legacy_event_to_event($event);
  68  
  69          return [$feedback, $event];
  70      }
  71  
  72      /**
  73       * Requesting calendar events from a given time should return all events with a sort
  74       * time at or after the requested time. All events prior to that time should not
  75       * be return.
  76       *
  77       * If there are no events on or after the given time then an empty result set should
  78       * be returned.
  79       */
  80      public function test_get_calendar_action_events_by_timesort_after_time() {
  81          $user = $this->getDataGenerator()->create_user();
  82          $course = $this->getDataGenerator()->create_course();
  83          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  84          $moduleinstance = $generator->create_instance(['course' => $course->id]);
  85  
  86          $this->getDataGenerator()->enrol_user($user->id, $course->id);
  87          $this->resetAfterTest(true);
  88          $this->setAdminUser();
  89  
  90          $params = [
  91              'type' => CALENDAR_EVENT_TYPE_ACTION,
  92              'courseid' => $course->id,
  93              'modulename' => 'assign',
  94              'instance' => $moduleinstance->id,
  95              'userid' => $user->id,
  96              'eventtype' => 'user',
  97              'repeats' => 0,
  98              'timestart' => 1,
  99          ];
 100  
 101          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 102          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 103          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 104          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 105          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 106          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 107          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 108          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 109  
 110          $this->setUser($user);
 111          $result = \core_calendar\local\api::get_action_events_by_timesort(5);
 112  
 113          $this->assertCount(4, $result);
 114          $this->assertEquals('Event 5', $result[0]->get_name());
 115          $this->assertEquals('Event 6', $result[1]->get_name());
 116          $this->assertEquals('Event 7', $result[2]->get_name());
 117          $this->assertEquals('Event 8', $result[3]->get_name());
 118  
 119          $result = \core_calendar\local\api::get_action_events_by_timesort(9);
 120  
 121          $this->assertEmpty($result);
 122  
 123          $this->setAdminUser();
 124          $result = \core_calendar\local\api::get_action_events_by_timesort(5, null, null, 20, false, $user);
 125          $this->assertCount(4, $result);
 126      }
 127  
 128      /**
 129       * Requesting calendar events before a given time should return all events with a sort
 130       * time at or before the requested time (inclusive). All events after that time
 131       * should not be returned.
 132       *
 133       * If there are no events before the given time then an empty result set should be
 134       * returned.
 135       */
 136      public function test_get_calendar_action_events_by_timesort_before_time() {
 137          $user = $this->getDataGenerator()->create_user();
 138          $course = $this->getDataGenerator()->create_course();
 139          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 140          $moduleinstance = $generator->create_instance(['course' => $course->id]);
 141  
 142          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 143          $this->resetAfterTest(true);
 144          $this->setAdminUser();
 145  
 146          $params = [
 147              'type' => CALENDAR_EVENT_TYPE_ACTION,
 148              'courseid' => $course->id,
 149              'modulename' => 'assign',
 150              'instance' => $moduleinstance->id,
 151              'userid' => 1,
 152              'eventtype' => 'user',
 153              'repeats' => 0,
 154              'timestart' => 1,
 155          ];
 156  
 157          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 2]));
 158          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 3]));
 159          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 4]));
 160          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 5]));
 161          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 6]));
 162          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 7]));
 163          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 8]));
 164          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 9]));
 165  
 166          $this->setUser($user);
 167          $result = \core_calendar\local\api::get_action_events_by_timesort(null, 5);
 168  
 169          $this->assertCount(4, $result);
 170          $this->assertEquals('Event 1', $result[0]->get_name());
 171          $this->assertEquals('Event 2', $result[1]->get_name());
 172          $this->assertEquals('Event 3', $result[2]->get_name());
 173          $this->assertEquals('Event 4', $result[3]->get_name());
 174  
 175          $result = \core_calendar\local\api::get_action_events_by_timesort(null, 1);
 176  
 177          $this->assertEmpty($result);
 178      }
 179  
 180      /**
 181       * Requesting calendar events within a given time range should return all events with
 182       * a sort time between the lower and upper time bound (inclusive).
 183       *
 184       * If there are no events in the given time range then an empty result set should be
 185       * returned.
 186       */
 187      public function test_get_calendar_action_events_by_timesort_time_range() {
 188          $user = $this->getDataGenerator()->create_user();
 189          $course = $this->getDataGenerator()->create_course();
 190          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 191          $moduleinstance = $generator->create_instance(['course' => $course->id]);
 192  
 193          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 194          $this->resetAfterTest(true);
 195          $this->setAdminUser();
 196  
 197          $params = [
 198              'type' => CALENDAR_EVENT_TYPE_ACTION,
 199              'courseid' => $course->id,
 200              'modulename' => 'assign',
 201              'instance' => $moduleinstance->id,
 202              'userid' => 1,
 203              'eventtype' => 'user',
 204              'repeats' => 0,
 205              'timestart' => 1,
 206          ];
 207  
 208          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 209          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 210          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 211          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 212          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 213          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 214          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 215          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 216  
 217          $this->setUser($user);
 218          $result = \core_calendar\local\api::get_action_events_by_timesort(3, 6);
 219  
 220          $this->assertCount(4, $result);
 221          $this->assertEquals('Event 3', $result[0]->get_name());
 222          $this->assertEquals('Event 4', $result[1]->get_name());
 223          $this->assertEquals('Event 5', $result[2]->get_name());
 224          $this->assertEquals('Event 6', $result[3]->get_name());
 225  
 226          $result = \core_calendar\local\api::get_action_events_by_timesort(10, 15);
 227  
 228          $this->assertEmpty($result);
 229      }
 230  
 231      /**
 232       * Requesting calendar events within a given time range and a limit and offset should return
 233       * the number of events up to the given limit value that have a sort time between the lower
 234       * and uppper time bound (inclusive) where the result set is shifted by the offset value.
 235       *
 236       * If there are no events in the given time range then an empty result set should be
 237       * returned.
 238       */
 239      public function test_get_calendar_action_events_by_timesort_time_limit_offset() {
 240          $user = $this->getDataGenerator()->create_user();
 241          $course = $this->getDataGenerator()->create_course();
 242          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 243          $moduleinstance = $generator->create_instance(['course' => $course->id]);
 244  
 245          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 246          $this->resetAfterTest(true);
 247          $this->setAdminUser();
 248  
 249          $params = [
 250              'type' => CALENDAR_EVENT_TYPE_ACTION,
 251              'courseid' => $course->id,
 252              'modulename' => 'assign',
 253              'instance' => $moduleinstance->id,
 254              'userid' => 1,
 255              'eventtype' => 'user',
 256              'repeats' => 0,
 257              'timestart' => 1,
 258          ];
 259  
 260          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 261          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 262          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 263          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 264          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 265          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 266          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 267          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 268  
 269          $this->setUser($user);
 270          $result = \core_calendar\local\api::get_action_events_by_timesort(2, 7, $event3->id, 2);
 271  
 272          $this->assertCount(2, $result);
 273          $this->assertEquals('Event 4', $result[0]->get_name());
 274          $this->assertEquals('Event 5', $result[1]->get_name());
 275  
 276          $result = \core_calendar\local\api::get_action_events_by_timesort(2, 7, $event5->id, 2);
 277  
 278          $this->assertCount(2, $result);
 279          $this->assertEquals('Event 6', $result[0]->get_name());
 280          $this->assertEquals('Event 7', $result[1]->get_name());
 281  
 282          $result = \core_calendar\local\api::get_action_events_by_timesort(2, 7, $event7->id, 2);
 283  
 284          $this->assertEmpty($result);
 285      }
 286  
 287      /**
 288       * Test get_calendar_action_events_by_timesort with search feature.
 289       */
 290      public function test_get_calendar_action_events_by_timesort_with_search() {
 291          // Generate data.
 292          $user = $this->getDataGenerator()->create_user();
 293          $course = $this->getDataGenerator()->create_course();
 294          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 295          $moduleinstance = $generator->create_instance(['course' => $course->id]);
 296  
 297          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 298          $this->resetAfterTest(true);
 299          $this->setAdminUser();
 300  
 301          $params = [
 302              'type' => CALENDAR_EVENT_TYPE_ACTION,
 303              'courseid' => $course->id,
 304              'modulename' => 'assign',
 305              'instance' => $moduleinstance->id,
 306              'userid' => 1,
 307              'eventtype' => 'user',
 308              'repeats' => 0,
 309              'timestart' => 1,
 310          ];
 311  
 312          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 313          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 314          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 315          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 316          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 317          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 318          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 319          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 320  
 321          $this->setUser($user);
 322  
 323          // No result found for fake search.
 324          $result = \core_calendar\local\api::get_action_events_by_timesort(0, null, null, 6, false, null, 'Fake search');
 325          $this->assertEmpty($result);
 326  
 327          // Search for event name called 'Event 1'.
 328          $result = \core_calendar\local\api::get_action_events_by_timesort(0, 8, null, 20, false, null, 'Event 1');
 329          $this->assertCount(1, $result);
 330          $this->assertEquals('Event 1', $result[0]->get_name());
 331  
 332          // Search for activity type called 'assign'.
 333          $result = \core_calendar\local\api::get_action_events_by_timesort(0, 8, null, 20, false, null, 'assign');
 334          $this->assertCount(8, $result);
 335          $this->assertEquals('Event 1', $result[0]->get_name());
 336          $this->assertEquals('Event 2', $result[1]->get_name());
 337          $this->assertEquals('Event 3', $result[2]->get_name());
 338          $this->assertEquals('Event 4', $result[3]->get_name());
 339          $this->assertEquals('Event 5', $result[4]->get_name());
 340          $this->assertEquals('Event 6', $result[5]->get_name());
 341          $this->assertEquals('Event 7', $result[6]->get_name());
 342          $this->assertEquals('Event 8', $result[7]->get_name());
 343      }
 344  
 345      /**
 346       * Requesting calendar events from a given course and time should return all
 347       * events with a sort time at or after the requested time. All events prior
 348       * to that time should not be return.
 349       *
 350       * If there are no events on or after the given time then an empty result set should
 351       * be returned.
 352       */
 353      public function test_get_calendar_action_events_by_course_after_time() {
 354          $user = $this->getDataGenerator()->create_user();
 355          $course1 = $this->getDataGenerator()->create_course();
 356          $course2 = $this->getDataGenerator()->create_course();
 357          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 358          $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
 359          $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
 360  
 361          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 362          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 363          $this->resetAfterTest(true);
 364          $this->setUser($user);
 365  
 366          $params = [
 367              'type' => CALENDAR_EVENT_TYPE_ACTION,
 368              'modulename' => 'assign',
 369              'instance' => $moduleinstance1->id,
 370              'userid' => $user->id,
 371              'courseid' => $course1->id,
 372              'eventtype' => 'user',
 373              'repeats' => 0,
 374              'timestart' => 1,
 375          ];
 376  
 377          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 378          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 379          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 380          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 381          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 382          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 383          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 384          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 385  
 386          $params['courseid'] = $course2->id;
 387          $params['instance'] = $moduleinstance2->id;
 388          $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 1]));
 389          $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 2]));
 390          $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 3]));
 391          $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 4]));
 392          $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 5]));
 393          $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 6]));
 394          $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 7]));
 395          $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 8]));
 396  
 397          $result = \core_calendar\local\api::get_action_events_by_course($course1, 5);
 398  
 399          $this->assertCount(4, $result);
 400          $this->assertEquals('Event 5', $result[0]->get_name());
 401          $this->assertEquals('Event 6', $result[1]->get_name());
 402          $this->assertEquals('Event 7', $result[2]->get_name());
 403          $this->assertEquals('Event 8', $result[3]->get_name());
 404  
 405          $result = \core_calendar\local\api::get_action_events_by_course($course1, 9);
 406  
 407          $this->assertEmpty($result);
 408      }
 409  
 410      /**
 411       * Requesting calendar events for a course and before a given time should return
 412       * all events with a sort time at or before the requested time (inclusive). All
 413       * events after that time should not be returned.
 414       *
 415       * If there are no events before the given time then an empty result set should be
 416       * returned.
 417       */
 418      public function test_get_calendar_action_events_by_course_before_time() {
 419          $user = $this->getDataGenerator()->create_user();
 420          $course1 = $this->getDataGenerator()->create_course();
 421          $course2 = $this->getDataGenerator()->create_course();
 422          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 423          $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
 424          $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
 425  
 426          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 427          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 428          $this->resetAfterTest(true);
 429          $this->setUser($user);
 430  
 431          $params = [
 432              'type' => CALENDAR_EVENT_TYPE_ACTION,
 433              'modulename' => 'assign',
 434              'instance' => $moduleinstance1->id,
 435              'userid' => $user->id,
 436              'courseid' => $course1->id,
 437              'eventtype' => 'user',
 438              'repeats' => 0,
 439              'timestart' => 1,
 440          ];
 441  
 442          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 2]));
 443          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 3]));
 444          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 4]));
 445          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 5]));
 446          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 6]));
 447          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 7]));
 448          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 8]));
 449          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 9]));
 450  
 451          $params['courseid'] = $course2->id;
 452          $params['instance'] = $moduleinstance2->id;
 453          $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 2]));
 454          $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 3]));
 455          $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 4]));
 456          $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 5]));
 457          $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 6]));
 458          $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 7]));
 459          $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 8]));
 460          $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 9]));
 461  
 462          $result = \core_calendar\local\api::get_action_events_by_course($course1, null, 5);
 463  
 464          $this->assertCount(4, $result);
 465          $this->assertEquals('Event 1', $result[0]->get_name());
 466          $this->assertEquals('Event 2', $result[1]->get_name());
 467          $this->assertEquals('Event 3', $result[2]->get_name());
 468          $this->assertEquals('Event 4', $result[3]->get_name());
 469  
 470          $result = \core_calendar\local\api::get_action_events_by_course($course1, null, 1);
 471  
 472          $this->assertEmpty($result);
 473      }
 474  
 475      /**
 476       * Requesting calendar events for a course and within a given time range should
 477       * return all events with a sort time between the lower and upper time bound
 478       * (inclusive).
 479       *
 480       * If there are no events in the given time range then an empty result set should be
 481       * returned.
 482       */
 483      public function test_get_calendar_action_events_by_course_time_range() {
 484          $user = $this->getDataGenerator()->create_user();
 485          $course1 = $this->getDataGenerator()->create_course();
 486          $course2 = $this->getDataGenerator()->create_course();
 487          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 488          $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
 489          $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
 490  
 491          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 492          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 493          $this->resetAfterTest(true);
 494          $this->setUser($user);
 495  
 496          $params = [
 497              'type' => CALENDAR_EVENT_TYPE_ACTION,
 498              'modulename' => 'assign',
 499              'instance' => $moduleinstance1->id,
 500              'userid' => $user->id,
 501              'courseid' => $course1->id,
 502              'eventtype' => 'user',
 503              'repeats' => 0,
 504              'timestart' => 1,
 505          ];
 506  
 507          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 508          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 509          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 510          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 511          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 512          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 513          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 514          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 515  
 516          $params['courseid'] = $course2->id;
 517          $params['instance'] = $moduleinstance2->id;
 518          $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 1]));
 519          $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 2]));
 520          $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 3]));
 521          $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 4]));
 522          $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 5]));
 523          $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 6]));
 524          $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 7]));
 525          $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 8]));
 526  
 527          $result = \core_calendar\local\api::get_action_events_by_course($course1, 3, 6);
 528  
 529          $this->assertCount(4, $result);
 530          $this->assertEquals('Event 3', $result[0]->get_name());
 531          $this->assertEquals('Event 4', $result[1]->get_name());
 532          $this->assertEquals('Event 5', $result[2]->get_name());
 533          $this->assertEquals('Event 6', $result[3]->get_name());
 534  
 535          $result = \core_calendar\local\api::get_action_events_by_course($course1, 10, 15);
 536  
 537          $this->assertEmpty($result);
 538      }
 539  
 540      /**
 541       * Requesting calendar events for a course and within a given time range and a limit
 542       * and offset should return the number of events up to the given limit value that have
 543       * a sort time between the lower and uppper time bound (inclusive) where the result
 544       * set is shifted by the offset value.
 545       *
 546       * If there are no events in the given time range then an empty result set should be
 547       * returned.
 548       */
 549      public function test_get_calendar_action_events_by_course_time_limit_offset() {
 550          $user = $this->getDataGenerator()->create_user();
 551          $course1 = $this->getDataGenerator()->create_course();
 552          $course2 = $this->getDataGenerator()->create_course();
 553          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 554          $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
 555          $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
 556  
 557          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 558          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 559          $this->resetAfterTest(true);
 560          $this->setUser($user);
 561  
 562          $params = [
 563              'type' => CALENDAR_EVENT_TYPE_ACTION,
 564              'modulename' => 'assign',
 565              'instance' => $moduleinstance1->id,
 566              'userid' => $user->id,
 567              'courseid' => $course1->id,
 568              'eventtype' => 'user',
 569              'repeats' => 0,
 570              'timestart' => 1,
 571          ];
 572  
 573          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 574          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 575          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 576          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 577          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 578          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 579          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 580          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 581  
 582          $params['courseid'] = $course2->id;
 583          $params['instance'] = $moduleinstance2->id;
 584          $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 1]));
 585          $event10 = create_event(array_merge($params, ['name' => 'Event 10', 'timesort' => 2]));
 586          $event11 = create_event(array_merge($params, ['name' => 'Event 11', 'timesort' => 3]));
 587          $event12 = create_event(array_merge($params, ['name' => 'Event 12', 'timesort' => 4]));
 588          $event13 = create_event(array_merge($params, ['name' => 'Event 13', 'timesort' => 5]));
 589          $event14 = create_event(array_merge($params, ['name' => 'Event 14', 'timesort' => 6]));
 590          $event15 = create_event(array_merge($params, ['name' => 'Event 15', 'timesort' => 7]));
 591          $event16 = create_event(array_merge($params, ['name' => 'Event 16', 'timesort' => 8]));
 592  
 593          $result = \core_calendar\local\api::get_action_events_by_course($course1, 2, 7, $event3->id, 2);
 594  
 595          $this->assertCount(2, $result);
 596          $this->assertEquals('Event 4', $result[0]->get_name());
 597          $this->assertEquals('Event 5', $result[1]->get_name());
 598  
 599          $result = \core_calendar\local\api::get_action_events_by_course($course1, 2, 7, $event5->id, 2);
 600  
 601          $this->assertCount(2, $result);
 602          $this->assertEquals('Event 6', $result[0]->get_name());
 603          $this->assertEquals('Event 7', $result[1]->get_name());
 604  
 605          $result = \core_calendar\local\api::get_action_events_by_course($course1, 2, 7, $event7->id, 2);
 606  
 607          $this->assertEmpty($result);
 608      }
 609  
 610      /**
 611       * Test that get_action_events_by_courses will return a list of events for each
 612       * course you provided as long as the user is enrolled in the course.
 613       */
 614      public function test_get_action_events_by_courses() {
 615          $user = $this->getDataGenerator()->create_user();
 616          $course1 = $this->getDataGenerator()->create_course();
 617          $course2 = $this->getDataGenerator()->create_course();
 618          $course3 = $this->getDataGenerator()->create_course();
 619          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 620          $moduleinstance1 = $generator->create_instance(['course' => $course1->id]);
 621          $moduleinstance2 = $generator->create_instance(['course' => $course2->id]);
 622          $moduleinstance3 = $generator->create_instance(['course' => $course3->id]);
 623  
 624          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 625          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 626          $this->getDataGenerator()->enrol_user($user->id, $course3->id);
 627          $this->resetAfterTest(true);
 628          $this->setUser($user);
 629  
 630          $params = [
 631              'type' => CALENDAR_EVENT_TYPE_ACTION,
 632              'modulename' => 'assign',
 633              'instance' => $moduleinstance1->id,
 634              'userid' => $user->id,
 635              'courseid' => $course1->id,
 636              'eventtype' => 'user',
 637              'repeats' => 0,
 638              'timestart' => 1,
 639          ];
 640  
 641          $event1 = create_event(array_merge($params, ['name' => 'Event 1', 'timesort' => 1]));
 642          $event2 = create_event(array_merge($params, ['name' => 'Event 2', 'timesort' => 2]));
 643  
 644          $params['courseid'] = $course2->id;
 645          $params['instance'] = $moduleinstance2->id;
 646          $event3 = create_event(array_merge($params, ['name' => 'Event 3', 'timesort' => 3]));
 647          $event4 = create_event(array_merge($params, ['name' => 'Event 4', 'timesort' => 4]));
 648          $event5 = create_event(array_merge($params, ['name' => 'Event 5', 'timesort' => 5]));
 649  
 650          $params['courseid'] = $course3->id;
 651          $params['instance'] = $moduleinstance3->id;
 652          $event6 = create_event(array_merge($params, ['name' => 'Event 6', 'timesort' => 6]));
 653          $event7 = create_event(array_merge($params, ['name' => 'Event 7', 'timesort' => 7]));
 654          $event8 = create_event(array_merge($params, ['name' => 'Event 8', 'timesort' => 8]));
 655          $event9 = create_event(array_merge($params, ['name' => 'Event 9', 'timesort' => 9]));
 656  
 657          $result = \core_calendar\local\api::get_action_events_by_courses([], 1);
 658  
 659          $this->assertEmpty($result);
 660  
 661          $result = \core_calendar\local\api::get_action_events_by_courses([$course1], 3);
 662  
 663          $this->assertEmpty($result[$course1->id]);
 664  
 665          $result = \core_calendar\local\api::get_action_events_by_courses([$course1], 1);
 666  
 667          $this->assertCount(2, $result[$course1->id]);
 668          $this->assertEquals('Event 1', $result[$course1->id][0]->get_name());
 669          $this->assertEquals('Event 2', $result[$course1->id][1]->get_name());
 670  
 671          $result = \core_calendar\local\api::get_action_events_by_courses([$course1, $course2], 1);
 672  
 673          $this->assertCount(2, $result[$course1->id]);
 674          $this->assertEquals('Event 1', $result[$course1->id][0]->get_name());
 675          $this->assertEquals('Event 2', $result[$course1->id][1]->get_name());
 676          $this->assertCount(3, $result[$course2->id]);
 677          $this->assertEquals('Event 3', $result[$course2->id][0]->get_name());
 678          $this->assertEquals('Event 4', $result[$course2->id][1]->get_name());
 679          $this->assertEquals('Event 5', $result[$course2->id][2]->get_name());
 680  
 681          $result = \core_calendar\local\api::get_action_events_by_courses([$course1, $course2], 2, 4);
 682  
 683          $this->assertCount(1, $result[$course1->id]);
 684          $this->assertEquals('Event 2', $result[$course1->id][0]->get_name());
 685          $this->assertCount(2, $result[$course2->id]);
 686          $this->assertEquals('Event 3', $result[$course2->id][0]->get_name());
 687          $this->assertEquals('Event 4', $result[$course2->id][1]->get_name());
 688  
 689          $result = \core_calendar\local\api::get_action_events_by_courses([$course1, $course2, $course3], 1, null, 1);
 690  
 691          $this->assertCount(1, $result[$course1->id]);
 692          $this->assertEquals('Event 1', $result[$course1->id][0]->get_name());
 693          $this->assertCount(1, $result[$course2->id]);
 694          $this->assertEquals('Event 3', $result[$course2->id][0]->get_name());
 695          $this->assertCount(1, $result[$course3->id]);
 696          $this->assertEquals('Event 6', $result[$course3->id][0]->get_name());
 697      }
 698  
 699      /**
 700       * Test that the get_legacy_events() function only returns activity events that are enabled.
 701       */
 702      public function test_get_legacy_events_with_disabled_module() {
 703          global $DB;
 704  
 705          $this->setAdminUser();
 706  
 707          $course = $this->getDataGenerator()->create_course();
 708  
 709          $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 710          $assigninstance = $assigngenerator->create_instance(['course' => $course->id]);
 711  
 712          $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
 713          $lessoninstance = $lessongenerator->create_instance(['course' => $course->id]);
 714          $student = $this->getDataGenerator()->create_user();
 715          $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
 716          $this->setUser($student);
 717          $events = [
 718              [
 719                  'name' => 'Start of assignment',
 720                  'description' => '',
 721                  'location' => 'Test',
 722                  'format' => 1,
 723                  'courseid' => $course->id,
 724                  'groupid' => 0,
 725                  'userid' => 2,
 726                  'modulename' => 'assign',
 727                  'instance' => $assigninstance->id,
 728                  'eventtype' => 'due',
 729                  'timestart' => time(),
 730                  'timeduration' => 86400,
 731                  'visible' => 1
 732              ], [
 733                  'name' => 'Start of lesson',
 734                  'description' => '',
 735                  'location' => 'Test',
 736                  'format' => 1,
 737                  'courseid' => $course->id,
 738                  'groupid' => 0,
 739                  'userid' => 2,
 740                  'modulename' => 'lesson',
 741                  'instance' => $lessoninstance->id,
 742                  'eventtype' => 'end',
 743                  'timestart' => time(),
 744                  'timeduration' => 86400,
 745                  'visible' => 1
 746              ]
 747          ];
 748          foreach ($events as $event) {
 749              \calendar_event::create($event, false);
 750          }
 751          $timestart = time() - 60;
 752          $timeend = time() + 60;
 753  
 754          // Get all events.
 755          $events = calendar_get_legacy_events($timestart, $timeend, true, 0, true);
 756          $this->assertCount(2, $events);
 757  
 758          // Disable the lesson module.
 759          $modulerecord = $DB->get_record('modules', ['name' => 'lesson']);
 760          $modulerecord->visible = 0;
 761          $DB->update_record('modules', $modulerecord);
 762  
 763          // Check that we only return the assign event.
 764          $events = calendar_get_legacy_events($timestart, $timeend, true, 0, true);
 765          $this->assertCount(1, $events);
 766          $event = reset($events);
 767          $this->assertEquals('assign', $event->modulename);
 768      }
 769  
 770      /**
 771       * Test for \core_calendar\local\api::get_legacy_events() when there are user and group overrides.
 772       */
 773      public function test_get_legacy_events_with_overrides() {
 774          $generator = $this->getDataGenerator();
 775  
 776          $course = $generator->create_course();
 777  
 778          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 779          if (!isset($params['course'])) {
 780              $params['course'] = $course->id;
 781          }
 782  
 783          $instance = $plugingenerator->create_instance($params);
 784  
 785          // Create users.
 786          $useroverridestudent = $generator->create_user();
 787          $group1student = $generator->create_user();
 788          $group2student = $generator->create_user();
 789          $group12student = $generator->create_user();
 790          $nogroupstudent = $generator->create_user();
 791  
 792          // Enrol users.
 793          $generator->enrol_user($useroverridestudent->id, $course->id, 'student');
 794          $generator->enrol_user($group1student->id, $course->id, 'student');
 795          $generator->enrol_user($group2student->id, $course->id, 'student');
 796          $generator->enrol_user($group12student->id, $course->id, 'student');
 797          $generator->enrol_user($nogroupstudent->id, $course->id, 'student');
 798  
 799          // Create groups.
 800          $group1 = $generator->create_group(['courseid' => $course->id]);
 801          $group2 = $generator->create_group(['courseid' => $course->id]);
 802  
 803          // Add members to groups.
 804          $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
 805          $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
 806          $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
 807          $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
 808          $now = time();
 809  
 810          // Events with the same module name, instance and event type.
 811          $events = [
 812              [
 813                  'name' => 'Assignment 1 due date',
 814                  'description' => '',
 815                  'location' => 'Test',
 816                  'format' => 0,
 817                  'courseid' => $course->id,
 818                  'groupid' => 0,
 819                  'userid' => 2,
 820                  'modulename' => 'assign',
 821                  'instance' => $instance->id,
 822                  'eventtype' => 'due',
 823                  'timestart' => $now,
 824                  'timeduration' => 0,
 825                  'visible' => 1
 826              ], [
 827                  'name' => 'Assignment 1 due date - User override',
 828                  'description' => '',
 829                  'location' => 'Test',
 830                  'format' => 1,
 831                  'courseid' => 0,
 832                  'groupid' => 0,
 833                  'userid' => $useroverridestudent->id,
 834                  'modulename' => 'assign',
 835                  'instance' => $instance->id,
 836                  'eventtype' => 'due',
 837                  'timestart' => $now + 86400,
 838                  'timeduration' => 0,
 839                  'visible' => 1,
 840                  'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
 841              ], [
 842                  'name' => 'Assignment 1 due date - Group A override',
 843                  'description' => '',
 844                  'location' => 'Test',
 845                  'format' => 1,
 846                  'courseid' => $course->id,
 847                  'groupid' => $group1->id,
 848                  'userid' => 2,
 849                  'modulename' => 'assign',
 850                  'instance' => $instance->id,
 851                  'eventtype' => 'due',
 852                  'timestart' => $now + (2 * 86400),
 853                  'timeduration' => 0,
 854                  'visible' => 1,
 855                  'priority' => 1,
 856              ], [
 857                  'name' => 'Assignment 1 due date - Group B override',
 858                  'description' => '',
 859                  'location' => 'Test',
 860                  'format' => 1,
 861                  'courseid' => $course->id,
 862                  'groupid' => $group2->id,
 863                  'userid' => 2,
 864                  'modulename' => 'assign',
 865                  'instance' => $instance->id,
 866                  'eventtype' => 'due',
 867                  'timestart' => $now + (3 * 86400),
 868                  'timeduration' => 0,
 869                  'visible' => 1,
 870                  'priority' => 2,
 871              ],
 872          ];
 873  
 874          foreach ($events as $event) {
 875              \calendar_event::create($event, false);
 876          }
 877  
 878          $timestart = $now - 100;
 879          $timeend = $now + (3 * 86400);
 880          $groups = [$group1->id, $group2->id];
 881  
 882          // Get user override events.
 883          $this->setUser($useroverridestudent);
 884          $events = calendar_get_legacy_events($timestart, $timeend, $useroverridestudent->id, $groups, $course->id);
 885          $this->assertCount(1, $events);
 886          $event = reset($events);
 887          $this->assertEquals('Assignment 1 due date - User override', $event->name);
 888  
 889          // Get event for user with override but with the timestart and timeend parameters only covering the original event.
 890          $events = calendar_get_legacy_events($timestart, $now, $useroverridestudent->id, $groups, $course->id);
 891          $this->assertCount(0, $events);
 892  
 893          // Get events for user that does not belong to any group and has no user override events.
 894          $this->setUser($nogroupstudent);
 895          $events = calendar_get_legacy_events($timestart, $timeend, $nogroupstudent->id, $groups, $course->id);
 896          $this->assertCount(1, $events);
 897          $event = reset($events);
 898          $this->assertEquals('Assignment 1 due date', $event->name);
 899  
 900          // Get events for user that belongs to groups A and B and has no user override events.
 901          $this->setUser($group12student);
 902          $events = calendar_get_legacy_events($timestart, $timeend, $group12student->id, $groups, $course->id);
 903          $this->assertCount(1, $events);
 904          $event = reset($events);
 905          $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
 906  
 907          // Get events for user that belongs to group A and has no user override events.
 908          $this->setUser($group1student);
 909          $events = calendar_get_legacy_events($timestart, $timeend, $group1student->id, $groups, $course->id);
 910          $this->assertCount(1, $events);
 911          $event = reset($events);
 912          $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
 913  
 914          // Add repeating events.
 915          $repeatingevents = [
 916              [
 917                  'name' => 'Repeating site event',
 918                  'description' => '',
 919                  'location' => 'Test',
 920                  'format' => 1,
 921                  'courseid' => SITEID,
 922                  'groupid' => 0,
 923                  'userid' => 2,
 924                  'repeatid' => $event->id,
 925                  'modulename' => '0',
 926                  'instance' => 0,
 927                  'eventtype' => 'site',
 928                  'timestart' => $now + 86400,
 929                  'timeduration' => 0,
 930                  'visible' => 1,
 931              ],
 932              [
 933                  'name' => 'Repeating site event',
 934                  'description' => '',
 935                  'location' => 'Test',
 936                  'format' => 1,
 937                  'courseid' => SITEID,
 938                  'groupid' => 0,
 939                  'userid' => 2,
 940                  'repeatid' => $event->id,
 941                  'modulename' => '0',
 942                  'instance' => 0,
 943                  'eventtype' => 'site',
 944                  'timestart' => $now + (2 * 86400),
 945                  'timeduration' => 0,
 946                  'visible' => 1,
 947              ],
 948          ];
 949  
 950          foreach ($repeatingevents as $event) {
 951              \calendar_event::create($event, false);
 952          }
 953  
 954          // Make sure repeating events are not filtered out.
 955          $events = calendar_get_legacy_events($timestart, $timeend, true, true, true);
 956          $this->assertCount(3, $events);
 957      }
 958  
 959      /**
 960       * Setting the start date on the calendar event should update the date
 961       * of the event but should leave the time of day unchanged.
 962       */
 963      public function test_update_event_start_day_updates_date() {
 964          $generator = $this->getDataGenerator();
 965          $user = $generator->create_user();
 966          $roleid = $generator->create_role();
 967          $context = \context_system::instance();
 968          $originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
 969          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
 970          $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
 971          $mapper = container::get_event_mapper();
 972  
 973          $generator->role_assign($roleid, $user->id, $context->id);
 974          assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
 975  
 976          $this->setUser($user);
 977          $this->resetAfterTest(true);
 978  
 979          $event = create_event([
 980              'name' => 'Test event',
 981              'userid' => $user->id,
 982              'eventtype' => 'user',
 983              'repeats' => 0,
 984              'timestart' => $originalstarttime->getTimestamp(),
 985          ]);
 986          $event = $mapper->from_legacy_event_to_event($event);
 987  
 988          $newEvent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
 989          $actual = $newEvent->get_times()->get_start_time();
 990  
 991          $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
 992      }
 993  
 994      /**
 995       * A user should not be able to update the start date of the event
 996       * that they don't have the capabilities to modify.
 997       */
 998      public function test_update_event_start_day_no_permission() {
 999          $generator = $this->getDataGenerator();
1000          $user = $generator->create_user();
1001          $roleid = $generator->create_role();
1002          $context = \context_system::instance();
1003          $originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1004          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
1005          $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
1006          $mapper = container::get_event_mapper();
1007  
1008          $generator->role_assign($roleid, $user->id, $context->id);
1009  
1010          $this->setUser($user);
1011          $this->resetAfterTest(true);
1012  
1013          $event = create_event([
1014              'name' => 'Test event',
1015              'userid' => $user->id,
1016              'eventtype' => 'user',
1017              'repeats' => 0,
1018              'timestart' => $originalstarttime->getTimestamp(),
1019          ]);
1020          $event = $mapper->from_legacy_event_to_event($event);
1021  
1022          assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
1023          $this->expectException('moodle_exception');
1024          $newEvent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1025      }
1026  
1027      /**
1028       * Updating the start day of an event with no maximum cutoff should
1029       * update the corresponding activity property.
1030       *
1031       * Note: This test uses the feedback activity because it requires
1032       * module callbacks to be in place to test.
1033       */
1034      public function test_update_event_start_day_activity_event_no_max() {
1035          global $CFG, $DB;
1036          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1037  
1038          $this->resetAfterTest(true);
1039          $this->setAdminUser();
1040          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1041          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
1042          $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
1043          list($feedback, $event) = $this->create_feedback_activity_and_event(
1044              [
1045                  'timeopen' => $timeopen->getTimestamp(),
1046                  'timeclose' => 0
1047              ],
1048              [
1049                  'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1050                  'timestart' => $timeopen->getTimestamp()
1051              ]
1052          );
1053          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1054          $actual = $newevent->get_times()->get_start_time();
1055          $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1056  
1057          $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1058          $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
1059      }
1060  
1061      /**
1062       * Updating the start day of an event belonging to an activity to a value
1063       * less than the maximum cutoff should update the corresponding activity
1064       * property.
1065       *
1066       * Note: This test uses the feedback activity because it requires
1067       * module callbacks to be in place to test.
1068       */
1069      public function test_update_event_start_day_activity_event_less_than_max() {
1070          global $CFG, $DB;
1071          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1072  
1073          $this->resetAfterTest(true);
1074          $this->setAdminUser();
1075          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1076          $timeclose = new \DateTimeImmutable('2019-01-1T15:00:00+08:00');
1077          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
1078          $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
1079          list($feedback, $event) = $this->create_feedback_activity_and_event(
1080              [
1081                  'timeopen' => $timeopen->getTimestamp(),
1082                  'timeclose' => $timeclose->getTimestamp()
1083              ],
1084              [
1085                  'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1086                  'timestart' => $timeopen->getTimestamp()
1087              ]
1088          );
1089  
1090          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1091          $actual = $newevent->get_times()->get_start_time();
1092          $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1093  
1094          $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1095          $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
1096      }
1097  
1098      /**
1099       * Updating the start day of an event belonging to an activity to a value
1100       * equal to the maximum cutoff should update the corresponding activity
1101       * property.
1102       *
1103       * Note: This test uses the feedback activity because it requires
1104       * module callbacks to be in place to test.
1105       */
1106      public function test_update_event_start_day_activity_event_equal_to_max() {
1107          global $CFG, $DB;
1108          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1109  
1110          $this->resetAfterTest(true);
1111          $this->setAdminUser();
1112          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1113          $timeclose = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
1114          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
1115          list($feedback, $event) = $this->create_feedback_activity_and_event(
1116              [
1117                  'timeopen' => $timeopen->getTimestamp(),
1118                  'timeclose' => $timeclose->getTimestamp(),
1119              ],
1120              [
1121                  'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1122                  'timestart' => $timeopen->getTimestamp()
1123              ]
1124          );
1125  
1126          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1127          $actual = $newevent->get_times()->get_start_time();
1128          $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1129  
1130          $this->assertEquals($timeclose->getTimestamp(), $actual->getTimestamp());
1131          $this->assertEquals($timeclose->getTimestamp(), $feedback->timeopen);
1132      }
1133  
1134      /**
1135       * Updating the start day of an event belonging to an activity to a value
1136       * after the maximum cutoff should not update the corresponding activity
1137       * property. Instead it should throw an exception.
1138       *
1139       * Note: This test uses the feedback activity because it requires
1140       * module callbacks to be in place to test.
1141       */
1142      public function test_update_event_start_day_activity_event_after_max() {
1143          global $CFG, $DB;
1144          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1145  
1146          $this->resetAfterTest(true);
1147          $this->setAdminUser();
1148          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1149          $timeclose = new \DateTimeImmutable('2017-02-2T15:00:00+08:00');
1150          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
1151          list($feedback, $event) = $this->create_feedback_activity_and_event(
1152              [
1153                  'timeopen' => $timeopen->getTimestamp(),
1154                  'timeclose' => $timeclose->getTimestamp(),
1155              ],
1156              [
1157                  'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1158                  'timestart' => $timeopen->getTimestamp()
1159              ]
1160          );
1161  
1162          $this->expectException('moodle_exception');
1163          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1164      }
1165  
1166      /**
1167       * Updating the start day of an event with no minimum cutoff should
1168       * update the corresponding activity property.
1169       *
1170       * Note: This test uses the feedback activity because it requires
1171       * module callbacks to be in place to test.
1172       */
1173      public function test_update_event_start_day_activity_event_no_min() {
1174          global $CFG, $DB;
1175          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1176  
1177          $this->resetAfterTest(true);
1178          $this->setAdminUser();
1179          $timeclose = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1180          $newstartdate = new \DateTimeImmutable('2016-02-2T10:00:00+08:00');
1181          $expected = new \DateTimeImmutable('2016-02-2T15:00:00+08:00');
1182          list($feedback, $event) = $this->create_feedback_activity_and_event(
1183              [
1184                  'timeopen' => 0,
1185                  'timeclose' => $timeclose->getTimestamp()
1186              ],
1187              [
1188                  'eventtype' => FEEDBACK_EVENT_TYPE_OPEN,
1189                  'timestart' => $timeclose->getTimestamp()
1190              ]
1191          );
1192  
1193          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1194          $actual = $newevent->get_times()->get_start_time();
1195          $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1196  
1197          $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1198          $this->assertEquals($expected->getTimestamp(), $feedback->timeopen);
1199      }
1200  
1201      /**
1202       * Updating the start day of an event belonging to an activity to a value
1203       * greater than the minimum cutoff should update the corresponding activity
1204       * property.
1205       *
1206       * Note: This test uses the feedback activity because it requires
1207       * module callbacks to be in place to test.
1208       */
1209      public function test_update_event_start_day_activity_event_greater_than_min() {
1210          global $CFG, $DB;
1211          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1212  
1213          $this->resetAfterTest(true);
1214          $this->setAdminUser();
1215          $timeopen = new \DateTimeImmutable('2016-01-1T15:00:00+08:00');
1216          $timeclose = new \DateTimeImmutable('2019-01-1T15:00:00+08:00');
1217          $newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
1218          $expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
1219          list($feedback, $event) = $this->create_feedback_activity_and_event(
1220              [
1221                  'timeopen' => $timeopen->getTimestamp(),
1222                  'timeclose' => $timeclose->getTimestamp()
1223              ],
1224              [
1225                  'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
1226                  'timestart' => $timeclose->getTimestamp()
1227              ]
1228          );
1229  
1230          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1231          $actual = $newevent->get_times()->get_start_time();
1232          $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1233  
1234          $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1235          $this->assertEquals($expected->getTimestamp(), $feedback->timeclose);
1236      }
1237  
1238      /**
1239       * Updating the start day of an event belonging to an activity to a value
1240       * equal to the minimum cutoff should update the corresponding activity
1241       * property.
1242       *
1243       * Note: This test uses the feedback activity because it requires
1244       * module callbacks to be in place to test.
1245       */
1246      public function test_update_event_start_day_activity_event_equal_to_min() {
1247          global $CFG, $DB;
1248          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1249  
1250          $this->resetAfterTest(true);
1251          $this->setAdminUser();
1252          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1253          $timeclose = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
1254          $newstartdate = new \DateTimeImmutable('2017-01-1T10:00:00+08:00');
1255          $expected = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1256          list($feedback, $event) = $this->create_feedback_activity_and_event(
1257              [
1258                  'timeopen' => $timeopen->getTimestamp(),
1259                  'timeclose' => $timeclose->getTimestamp(),
1260              ],
1261              [
1262                  'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
1263                  'timestart' => $timeclose->getTimestamp()
1264              ]
1265          );
1266  
1267          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1268          $actual = $newevent->get_times()->get_start_time();
1269          $feedback = $DB->get_record('feedback', ['id' => $feedback->id]);
1270  
1271          $this->assertEquals($expected->getTimestamp(), $actual->getTimestamp());
1272          $this->assertEquals($expected->getTimestamp(), $feedback->timeclose);
1273      }
1274  
1275      /**
1276       * Updating the start day of an event belonging to an activity to a value
1277       * before the minimum cutoff should not update the corresponding activity
1278       * property. Instead it should throw an exception.
1279       *
1280       * Note: This test uses the feedback activity because it requires
1281       * module callbacks to be in place to test.
1282       */
1283      public function test_update_event_start_day_activity_event_before_min() {
1284          global $CFG, $DB;
1285          require_once($CFG->dirroot . '/mod/feedback/lib.php');
1286  
1287          $this->resetAfterTest(true);
1288          $this->setAdminUser();
1289          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1290          $timeclose = new \DateTimeImmutable('2017-02-2T15:00:00+08:00');
1291          $newstartdate = new \DateTimeImmutable('2016-02-2T10:00:00+08:00');
1292          list($feedback, $event) = $this->create_feedback_activity_and_event(
1293              [
1294                  'timeopen' => $timeopen->getTimestamp(),
1295                  'timeclose' => $timeclose->getTimestamp(),
1296              ],
1297              [
1298                  'eventtype' => FEEDBACK_EVENT_TYPE_CLOSE,
1299                  'timestart' => $timeclose->getTimestamp()
1300              ]
1301          );
1302  
1303          $this->expectException('moodle_exception');
1304          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1305      }
1306  
1307      /**
1308       * Updating the start day of an overridden event belonging to an activity
1309       * should result in an exception. This is to prevent the drag and drop
1310       * of override events.
1311       *
1312       * Note: This test uses the quiz activity because it requires
1313       * module callbacks to be in place and override event support to test.
1314       */
1315      public function test_update_event_start_day_activity_event_override() {
1316          global $CFG, $DB;
1317          require_once($CFG->dirroot . '/calendar/lib.php');
1318          require_once($CFG->dirroot . '/mod/quiz/lib.php');
1319  
1320          $this->resetAfterTest(true);
1321          $this->setAdminUser();
1322          $mapper = container::get_event_mapper();
1323          $timeopen = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
1324          $newstartdate = new \DateTimeImmutable('2016-02-2T10:00:00+08:00');
1325          $generator = $this->getDataGenerator();
1326          $user = $generator->create_user();
1327          $course = $generator->create_course();
1328          $quizgenerator = $generator->get_plugin_generator('mod_quiz');
1329          $quiz = $quizgenerator->create_instance([
1330              'course' => $course->id,
1331              'timeopen' => $timeopen->getTimestamp(),
1332          ]);
1333          $event = create_event([
1334              'courseid' => $course->id,
1335              'userid' => $user->id,
1336              'modulename' => 'quiz',
1337              'instance' => $quiz->id,
1338              'eventtype' => QUIZ_EVENT_TYPE_OPEN,
1339              'timestart' => $timeopen->getTimestamp()
1340          ]);
1341          $event = $mapper->from_legacy_event_to_event($event);
1342          $record = (object) [
1343              'quiz' => $quiz->id,
1344              'userid' => $user->id
1345          ];
1346  
1347          $DB->insert_record('quiz_overrides', $record);
1348  
1349          $this->expectException('moodle_exception');
1350          $newevent = \core_calendar\local\api::update_event_start_day($event, $newstartdate);
1351      }
1352  }