Search moodle.org's
Developer Documentation

See Release Notes

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

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

   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   * Event factory test.
  19   *
  20   * @package    core_calendar
  21   * @copyright  2017 Cameron Ball <cameron@cameron1729.xyz>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  global $CFG;
  28  require_once($CFG->dirroot . '/calendar/lib.php');
  29  
  30  use core_calendar\local\event\factories\event_factory;
  31  use core_calendar\local\event\entities\event_interface;
  32  
  33  /**
  34   * Event factory testcase.
  35   *
  36   * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
  37   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   */
  39  class core_calendar_event_factory_testcase extends advanced_testcase {
  40      /**
  41       * Test event class getters.
  42       *
  43       * @dataProvider create_instance_testcases()
  44       * @param \stdClass $dbrow Row from the event table.
  45       * @param callable  $actioncallbackapplier     Action callback applier.
  46       * @param callable  $visibilitycallbackapplier Visibility callback applier.
  47       * @param callable  $bailoutcheck              Early bail out check function.
  48       * @param string    $expectedclass             Class the factory is expected to produce.
  49       * @param mixed     $expectedattributevalue    Expected value of the modified attribute.
  50       */
  51      public function test_create_instance(
  52          $dbrow,
  53          callable $actioncallbackapplier,
  54          callable $visibilitycallbackapplier,
  55          callable $bailoutcheck,
  56          $expectedclass,
  57          $expectedattributevalue
  58      ) {
  59          $this->resetAfterTest(true);
  60          $this->setAdminUser();
  61          $event = $this->create_event();
  62          $coursecache = [];
  63          $modulecache = [];
  64          $factory = new event_factory(
  65              $actioncallbackapplier,
  66              $visibilitycallbackapplier,
  67              $bailoutcheck,
  68              $coursecache,
  69              $modulecache
  70          );
  71          $dbrow->id = $event->id;
  72          $instance = $factory->create_instance($dbrow);
  73  
  74          if ($expectedclass) {
  75              $this->assertInstanceOf($expectedclass, $instance);
  76          }
  77  
  78          if (is_null($expectedclass)) {
  79              $this->assertNull($instance);
  80          }
  81  
  82          if ($expectedattributevalue) {
  83              $this->assertEquals($instance->testattribute, $expectedattributevalue);
  84          }
  85      }
  86  
  87      /**
  88       * Test invalid callback exception.
  89       */
  90      public function test_invalid_action_callback() {
  91          $this->resetAfterTest(true);
  92          $this->setAdminUser();
  93          $event = $this->create_event();
  94          $coursecache = [];
  95          $modulecache = [];
  96          $factory = new event_factory(
  97              function () {
  98                  return 'hello';
  99              },
 100              function () {
 101                  return true;
 102              },
 103              function () {
 104                  return false;
 105              },
 106              $coursecache,
 107              $modulecache
 108          );
 109  
 110          $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
 111          $factory->create_instance(
 112              (object)[
 113                  'id' => $event->id,
 114                  'name' => 'test',
 115                  'description' => 'Test description',
 116                  'format' => 2,
 117                  'categoryid' => 0,
 118                  'courseid' => 1,
 119                  'groupid' => 1,
 120                  'userid' => 1,
 121                  'repeatid' => 0,
 122                  'modulename' => 'assign',
 123                  'instance' => 1,
 124                  'eventtype' => 'due',
 125                  'type' => CALENDAR_EVENT_TYPE_ACTION,
 126                  'timestart' => 123456789,
 127                  'timeduration' => 12,
 128                  'timemodified' => 123456789,
 129                  'timesort' => 123456789,
 130                  'visible' => 1,
 131                  'subscriptionid' => 1,
 132                  'location' => 'Test location',
 133              ]
 134          );
 135      }
 136  
 137      /**
 138       * Test invalid callback exception.
 139       */
 140      public function test_invalid_visibility_callback() {
 141          $this->resetAfterTest(true);
 142          $this->setAdminUser();
 143          $event = $this->create_event();
 144          $coursecache = [];
 145          $modulecache = [];
 146          $factory = new event_factory(
 147              function ($event) {
 148                  return $event;
 149              },
 150              function () {
 151                  return 'asdf';
 152              },
 153              function () {
 154                  return false;
 155              },
 156              $coursecache,
 157              $modulecache
 158          );
 159  
 160          $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
 161          $factory->create_instance(
 162              (object)[
 163                  'id' => $event->id,
 164                  'name' => 'test',
 165                  'description' => 'Test description',
 166                  'format' => 2,
 167                  'categoryid' => 0,
 168                  'courseid' => 1,
 169                  'groupid' => 1,
 170                  'userid' => 1,
 171                  'repeatid' => 0,
 172                  'modulename' => 'assign',
 173                  'instance' => 1,
 174                  'eventtype' => 'due',
 175                  'type' => CALENDAR_EVENT_TYPE_ACTION,
 176                  'timestart' => 123456789,
 177                  'timeduration' => 12,
 178                  'timemodified' => 123456789,
 179                  'timesort' => 123456789,
 180                  'visible' => 1,
 181                  'subscriptionid' => 1,
 182                  'location' => 'Test location',
 183              ]
 184          );
 185      }
 186  
 187      /**
 188       * Test invalid callback exception.
 189       */
 190      public function test_invalid_bail_callback() {
 191          $this->resetAfterTest(true);
 192          $this->setAdminUser();
 193          $event = $this->create_event();
 194          $coursecache = [];
 195          $modulecache = [];
 196          $factory = new event_factory(
 197              function ($event) {
 198                  return $event;
 199              },
 200              function () {
 201                  return true;
 202              },
 203              function () {
 204                  return 'asdf';
 205              },
 206              $coursecache,
 207              $modulecache
 208          );
 209  
 210          $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
 211          $factory->create_instance(
 212              (object)[
 213                  'id' => $event->id,
 214                  'name' => 'test',
 215                  'description' => 'Test description',
 216                  'format' => 2,
 217                  'categoryid' => 0,
 218                  'courseid' => 1,
 219                  'groupid' => 1,
 220                  'userid' => 1,
 221                  'repeatid' => 0,
 222                  'modulename' => 'assign',
 223                  'instance' => 1,
 224                  'eventtype' => 'due',
 225                  'type' => CALENDAR_EVENT_TYPE_ACTION,
 226                  'timestart' => 123456789,
 227                  'timeduration' => 12,
 228                  'timemodified' => 123456789,
 229                  'timesort' => 123456789,
 230                  'visible' => 1,
 231                  'subscriptionid' => 1,
 232                  'location' => 'Test location',
 233              ]
 234          );
 235      }
 236  
 237      /**
 238       * Test the factory's course cache.
 239       */
 240      public function test_course_cache() {
 241          $this->resetAfterTest(true);
 242          $this->setAdminUser();
 243          $course = self::getDataGenerator()->create_course();
 244          $event = $this->create_event(['courseid' => $course->id]);
 245          $coursecache = [];
 246          $modulecache = [];
 247          $factory = new event_factory(
 248              function ($event) {
 249                  return $event;
 250              },
 251              function () {
 252                  return true;
 253              },
 254              function () {
 255                  return false;
 256              },
 257              $coursecache,
 258              $modulecache
 259          );
 260  
 261          $instance = $factory->create_instance(
 262              (object)[
 263                  'id' => $event->id,
 264                  'name' => 'test',
 265                  'description' => 'Test description',
 266                  'format' => 2,
 267                  'categoryid' => 0,
 268                  'courseid' => $course->id,
 269                  'groupid' => 1,
 270                  'userid' => 1,
 271                  'repeatid' => 0,
 272                  'modulename' => 'assign',
 273                  'instance' => 1,
 274                  'eventtype' => 'due',
 275                  'type' => CALENDAR_EVENT_TYPE_ACTION,
 276                  'timestart' => 123456789,
 277                  'timeduration' => 12,
 278                  'timemodified' => 123456789,
 279                  'timesort' => 123456789,
 280                  'visible' => 1,
 281                  'subscriptionid' => 1,
 282                  'location' => 'Test location',
 283              ]
 284          );
 285  
 286          $instance->get_course()->get('fullname');
 287          $this->assertArrayHasKey($course->id, $coursecache);
 288      }
 289  
 290      /**
 291       * Test the factory's module cache.
 292       */
 293      public function test_module_cache() {
 294          $this->resetAfterTest(true);
 295          $this->setAdminUser();
 296          $course = self::getDataGenerator()->create_course();
 297          $event = $this->create_event(['courseid' => $course->id]);
 298          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
 299          $assigninstance = $plugingenerator->create_instance(['course' => $course->id]);
 300  
 301          $coursecache = [];
 302          $modulecache = [];
 303          $factory = new event_factory(
 304              function ($event) {
 305                  return $event;
 306              },
 307              function () {
 308                  return true;
 309              },
 310              function () {
 311                  return false;
 312              },
 313              $coursecache,
 314              $modulecache
 315          );
 316  
 317          $instance = $factory->create_instance(
 318              (object)[
 319                  'id' => $event->id,
 320                  'name' => 'test',
 321                  'description' => 'Test description',
 322                  'format' => 2,
 323                  'categoryid' => 0,
 324                  'courseid' => 0,
 325                  'groupid' => 1,
 326                  'userid' => 1,
 327                  'repeatid' => 0,
 328                  'modulename' => 'assign',
 329                  'instance' => $assigninstance->id,
 330                  'eventtype' => 'due',
 331                  'type' => CALENDAR_EVENT_TYPE_ACTION,
 332                  'timestart' => 123456789,
 333                  'timeduration' => 12,
 334                  'timemodified' => 123456789,
 335                  'timesort' => 123456789,
 336                  'visible' => 1,
 337                  'subscriptionid' => 1,
 338                  'location' => 'Test location',
 339              ]
 340          );
 341  
 342          $instance->get_course_module()->get('course');
 343          $this->assertArrayHasKey('assign' . '_' . $assigninstance->id, $modulecache);
 344      }
 345  
 346      /**
 347       * Testcases for the create instance test.
 348       *
 349       * @return array Array of testcases.
 350       */
 351      public function create_instance_testcases() {
 352          return [
 353              'Sample event record with event exposed' => [
 354                  'dbrow' => (object)[
 355                      'name' => 'Test event',
 356                      'description' => 'Hello',
 357                      'format' => 1,
 358                      'categoryid' => 0,
 359                      'courseid' => 1,
 360                      'groupid' => 1,
 361                      'userid' => 1,
 362                      'repeatid' => 0,
 363                      'modulename' => 'Test module',
 364                      'instance' => 1,
 365                      'eventtype' => 'Due',
 366                      'type' => CALENDAR_EVENT_TYPE_ACTION,
 367                      'timestart' => 123456789,
 368                      'timeduration' => 123456789,
 369                      'timemodified' => 123456789,
 370                      'timesort' => 123456789,
 371                      'visible' => true,
 372                      'subscriptionid' => 1,
 373                      'location' => 'Test location',
 374                  ],
 375                  'actioncallbackapplier' => function(event_interface $event) {
 376                      $event->testattribute = 'Hello';
 377                      return $event;
 378                  },
 379                  'visibilitycallbackapplier' => function(event_interface $event) {
 380                      return true;
 381                  },
 382                  'bailoutcheck' => function() {
 383                      return false;
 384                  },
 385                  event_interface::class,
 386                  'Hello'
 387              ],
 388              'Sample event record with event hidden' => [
 389                  'dbrow' => (object)[
 390                      'name' => 'Test event',
 391                      'description' => 'Hello',
 392                      'format' => 1,
 393                      'categoryid' => 0,
 394                      'courseid' => 1,
 395                      'groupid' => 1,
 396                      'userid' => 1,
 397                      'repeatid' => 0,
 398                      'modulename' => 'Test module',
 399                      'instance' => 1,
 400                      'eventtype' => 'Due',
 401                      'type' => CALENDAR_EVENT_TYPE_ACTION,
 402                      'timestart' => 123456789,
 403                      'timeduration' => 123456789,
 404                      'timemodified' => 123456789,
 405                      'timesort' => 123456789,
 406                      'visible' => true,
 407                      'subscriptionid' => 1,
 408                      'location' => 'Test location',
 409                  ],
 410                  'actioncallbackapplier' => function(event_interface $event) {
 411                      $event->testattribute = 'Hello';
 412                      return $event;
 413                  },
 414                  'visibilitycallbackapplier' => function(event_interface $event) {
 415                      return false;
 416                  },
 417                  'bailoutcheck' => function() {
 418                      return false;
 419                  },
 420                  null,
 421                  null
 422              ],
 423              'Sample event record with early bail' => [
 424                  'dbrow' => (object)[
 425                      'name' => 'Test event',
 426                      'description' => 'Hello',
 427                      'format' => 1,
 428                      'categoryid' => 0,
 429                      'courseid' => 1,
 430                      'groupid' => 1,
 431                      'userid' => 1,
 432                      'repeatid' => 0,
 433                      'modulename' => 'Test module',
 434                      'instance' => 1,
 435                      'eventtype' => 'Due',
 436                      'type' => CALENDAR_EVENT_TYPE_ACTION,
 437                      'timestart' => 123456789,
 438                      'timeduration' => 123456789,
 439                      'timemodified' => 123456789,
 440                      'timesort' => 123456789,
 441                      'visible' => true,
 442                      'subscriptionid' => 1,
 443                      'location' => 'Test location',
 444                  ],
 445                  'actioncallbackapplier' => function(event_interface $event) {
 446                      $event->testattribute = 'Hello';
 447                      return $event;
 448                  },
 449                  'visibilitycallbackapplier' => function(event_interface $event) {
 450                      return true;
 451                  },
 452                  'bailoutcheck' => function() {
 453                      return true;
 454                  },
 455                  null,
 456                  null
 457              ]
 458          ];
 459      }
 460  
 461      /**
 462       * Helper function to create calendar events using the old code.
 463       *
 464       * @param array $properties A list of calendar event properties to set
 465       * @return calendar_event
 466       */
 467      protected function create_event($properties = []) {
 468          $record = new \stdClass();
 469          $record->name = 'event name';
 470          $record->eventtype = 'site';
 471          $record->timestart = time();
 472          $record->timeduration = 0;
 473          $record->timesort = 0;
 474          $record->type = 1;
 475          $record->courseid = 0;
 476          $record->categoryid = 0;
 477  
 478          foreach ($properties as $name => $value) {
 479              $record->$name = $value;
 480          }
 481  
 482          $event = new calendar_event($record);
 483          return $event->create($record, false);
 484      }
 485  }