Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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