Search moodle.org's
Developer Documentation

See Release Notes

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

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

   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   * Events tests.
  19   *
  20   * @package mod_data
  21   * @category test
  22   * @copyright 2014 Mark Nelson <markn@moodle.com>
  23   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace mod_data\event;
  27  
  28  use mod_data\local\importer\preset_existing_importer;
  29  use mod_data\manager;
  30  use mod_data\preset;
  31  
  32  class events_test extends \advanced_testcase {
  33  
  34      /**
  35       * Test set up.
  36       *
  37       * This is executed before running any test in this file.
  38       */
  39      public function setUp(): void {
  40          $this->resetAfterTest();
  41      }
  42  
  43      /**
  44       * Test the field created event.
  45       */
  46      public function test_field_created() {
  47          $this->setAdminUser();
  48  
  49          // Create a course we are going to add a data module to.
  50          $course = $this->getDataGenerator()->create_course();
  51  
  52          // The generator used to create a data module.
  53          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
  54  
  55          // Create a data module.
  56          $data = $generator->create_instance(array('course' => $course->id));
  57  
  58          // Now we want to create a field.
  59          $field = data_get_field_new('text', $data);
  60          $fielddata = new \stdClass();
  61          $fielddata->name = 'Test';
  62          $fielddata->description = 'Test description';
  63          $field->define_field($fielddata);
  64  
  65          // Trigger and capture the event for creating a field.
  66          $sink = $this->redirectEvents();
  67          $field->insert_field();
  68          $events = $sink->get_events();
  69          $event = reset($events);
  70  
  71          // Check that the event data is valid.
  72          $this->assertInstanceOf('\mod_data\event\field_created', $event);
  73          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
  74          $url = new \moodle_url('/mod/data/field.php', array('d' => $data->id));
  75          $this->assertEquals($url, $event->get_url());
  76      }
  77  
  78      /**
  79       * Test the field updated event.
  80       */
  81      public function test_field_updated() {
  82          $this->setAdminUser();
  83  
  84          // Create a course we are going to add a data module to.
  85          $course = $this->getDataGenerator()->create_course();
  86  
  87          // The generator used to create a data module.
  88          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
  89  
  90          // Create a data module.
  91          $data = $generator->create_instance(array('course' => $course->id));
  92  
  93          // Now we want to create a field.
  94          $field = data_get_field_new('text', $data);
  95          $fielddata = new \stdClass();
  96          $fielddata->name = 'Test';
  97          $fielddata->description = 'Test description';
  98          $field->define_field($fielddata);
  99          $field->insert_field();
 100  
 101          // Trigger and capture the event for updating the field.
 102          $sink = $this->redirectEvents();
 103          $field->update_field();
 104          $events = $sink->get_events();
 105          $event = reset($events);
 106  
 107          // Check that the event data is valid.
 108          $this->assertInstanceOf('\mod_data\event\field_updated', $event);
 109          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 110          $url = new \moodle_url('/mod/data/field.php', array('d' => $data->id));
 111          $this->assertEquals($url, $event->get_url());
 112      }
 113  
 114      /**
 115       * Test the field deleted event.
 116       */
 117      public function test_field_deleted() {
 118          $this->setAdminUser();
 119  
 120          // Create a course we are going to add a data module to.
 121          $course = $this->getDataGenerator()->create_course();
 122  
 123          // The generator used to create a data module.
 124          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 125  
 126          // Create a data module.
 127          $data = $generator->create_instance(array('course' => $course->id));
 128  
 129          // Now we want to create a field.
 130          $field = data_get_field_new('text', $data);
 131          $fielddata = new \stdClass();
 132          $fielddata->name = 'Test';
 133          $fielddata->description = 'Test description';
 134          $field->define_field($fielddata);
 135          $field->insert_field();
 136  
 137          // Trigger and capture the event for deleting the field.
 138          $sink = $this->redirectEvents();
 139          $field->delete_field();
 140          $events = $sink->get_events();
 141          $event = reset($events);
 142  
 143          // Check that the event data is valid.
 144          $this->assertInstanceOf('\mod_data\event\field_deleted', $event);
 145          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 146          $url = new \moodle_url('/mod/data/field.php', array('d' => $data->id));
 147          $this->assertEquals($url, $event->get_url());
 148      }
 149  
 150      /**
 151       * Test the record created event.
 152       */
 153      public function test_record_created() {
 154          // Create a course we are going to add a data module to.
 155          $course = $this->getDataGenerator()->create_course();
 156  
 157          // The generator used to create a data module.
 158          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 159  
 160          // Create a data module.
 161          $data = $generator->create_instance(array('course' => $course->id));
 162  
 163          // Trigger and capture the event for creating the record.
 164          $sink = $this->redirectEvents();
 165          $recordid = data_add_record($data);
 166          $events = $sink->get_events();
 167          $event = reset($events);
 168  
 169          // Check that the event data is valid.
 170          $this->assertInstanceOf('\mod_data\event\record_created', $event);
 171          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 172          $url = new \moodle_url('/mod/data/view.php', array('d' => $data->id, 'rid' => $recordid));
 173          $this->assertEquals($url, $event->get_url());
 174      }
 175  
 176      /**
 177       * Test the record updated event.
 178       *
 179       * There is no external API for updating a record, so the unit test will simply create
 180       * and trigger the event and ensure the legacy log data is returned as expected.
 181       */
 182      public function test_record_updated() {
 183          // Create a course we are going to add a data module to.
 184          $course = $this->getDataGenerator()->create_course();
 185  
 186          // The generator used to create a data module.
 187          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 188  
 189          // Create a data module.
 190          $data = $generator->create_instance(array('course' => $course->id));
 191  
 192          // Trigger an event for updating this record.
 193          $event = \mod_data\event\record_updated::create(array(
 194              'objectid' => 1,
 195              'context' => \context_module::instance($data->cmid),
 196              'courseid' => $course->id,
 197              'other' => array(
 198                  'dataid' => $data->id
 199              )
 200          ));
 201  
 202          // Trigger and capture the event for updating the data record.
 203          $sink = $this->redirectEvents();
 204          $event->trigger();
 205          $events = $sink->get_events();
 206          $event = reset($events);
 207  
 208          // Check that the event data is valid.
 209          $this->assertInstanceOf('\mod_data\event\record_updated', $event);
 210          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 211          $url = new \moodle_url('/mod/data/view.php', array('d' => $data->id, 'rid' => $event->objectid));
 212          $this->assertEquals($url, $event->get_url());
 213      }
 214  
 215      /**
 216       * Test the record deleted event.
 217       */
 218      public function test_record_deleted() {
 219          global $DB;
 220  
 221          // Create a course we are going to add a data module to.
 222          $course = $this->getDataGenerator()->create_course();
 223  
 224          // The generator used to create a data module.
 225          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 226  
 227          // Create a data module.
 228          $data = $generator->create_instance(array('course' => $course->id));
 229  
 230          // Now we want to create a field.
 231          $field = data_get_field_new('text', $data);
 232          $fielddata = new \stdClass();
 233          $fielddata->name = 'Test';
 234          $fielddata->description = 'Test description';
 235          $field->define_field($fielddata);
 236          $field->insert_field();
 237  
 238          // Create data record.
 239          $datarecords = new \stdClass();
 240          $datarecords->userid = '2';
 241          $datarecords->dataid = $data->id;
 242          $datarecords->id = $DB->insert_record('data_records', $datarecords);
 243  
 244          // Create data content.
 245          $datacontent = new \stdClass();
 246          $datacontent->fieldid = $field->field->id;
 247          $datacontent->recordid = $datarecords->id;
 248          $datacontent->id = $DB->insert_record('data_content', $datacontent);
 249  
 250          // Trigger and capture the event for deleting the data record.
 251          $sink = $this->redirectEvents();
 252          data_delete_record($datarecords->id, $data, $course->id, $data->cmid);
 253          $events = $sink->get_events();
 254          $event = reset($events);
 255  
 256          // Check that the event data is valid.
 257          $this->assertInstanceOf('\mod_data\event\record_deleted', $event);
 258          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 259          $url = new \moodle_url('/mod/data/view.php', array('d' => $data->id));
 260          $this->assertEquals($url, $event->get_url());
 261      }
 262  
 263      /**
 264       * Test the template viewed event.
 265       *
 266       * There is no external API for viewing templates, so the unit test will simply create
 267       * and trigger the event and ensure the legacy log data is returned as expected.
 268       */
 269      public function test_template_viewed() {
 270          // Create a course we are going to add a data module to.
 271          $course = $this->getDataGenerator()->create_course();
 272  
 273          // The generator used to create a data module.
 274          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 275  
 276          // Create a data module.
 277          $data = $generator->create_instance(array('course' => $course->id));
 278  
 279          // Trigger an event for updating this record.
 280          $event = \mod_data\event\template_viewed::create(array(
 281              'context' => \context_module::instance($data->cmid),
 282              'courseid' => $course->id,
 283              'other' => array(
 284                  'dataid' => $data->id
 285              )
 286          ));
 287  
 288          // Trigger and capture the event for updating the data record.
 289          $sink = $this->redirectEvents();
 290          $event->trigger();
 291          $events = $sink->get_events();
 292          $event = reset($events);
 293  
 294          // Check that the event data is valid.
 295          $this->assertInstanceOf('\mod_data\event\template_viewed', $event);
 296          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 297          $url = new \moodle_url('/mod/data/templates.php', array('d' => $data->id));
 298          $this->assertEquals($url, $event->get_url());
 299      }
 300  
 301      /**
 302       * Test the template updated event.
 303       *
 304       * There is no external API for updating a template, so the unit test will simply create
 305       * and trigger the event and ensure the legacy log data is returned as expected.
 306       */
 307      public function test_template_updated() {
 308          // Create a course we are going to add a data module to.
 309          $course = $this->getDataGenerator()->create_course();
 310  
 311          // The generator used to create a data module.
 312          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 313  
 314          // Create a data module.
 315          $data = $generator->create_instance(array('course' => $course->id));
 316  
 317          // Trigger an event for updating this record.
 318          $event = \mod_data\event\template_updated::create(array(
 319              'context' => \context_module::instance($data->cmid),
 320              'courseid' => $course->id,
 321              'other' => array(
 322                  'dataid' => $data->id,
 323              )
 324          ));
 325  
 326          // Trigger and capture the event for updating the data record.
 327          $sink = $this->redirectEvents();
 328          $event->trigger();
 329          $events = $sink->get_events();
 330          $event = reset($events);
 331  
 332          // Check that the event data is valid.
 333          $this->assertInstanceOf('\mod_data\event\template_updated', $event);
 334          $this->assertEquals(\context_module::instance($data->cmid), $event->get_context());
 335          $url = new \moodle_url('/mod/data/templates.php', array('d' => $data->id));
 336          $this->assertEquals($url, $event->get_url());
 337      }
 338  
 339      /**
 340       * Data provider for build providers for test_needs_mapping and test_set_affected_fields.
 341       *
 342       * @return array[]
 343       */
 344      public function preset_importer_provider(): array {
 345          // Image gallery preset is: ['title' => 'text', 'description' => 'textarea', 'image' => 'picture'];
 346  
 347          $titlefield = new \stdClass();
 348          $titlefield->name = 'title';
 349          $titlefield->type = 'text';
 350  
 351          $descfield = new \stdClass();
 352          $descfield->name = 'description';
 353          $descfield->type = 'textarea';
 354  
 355          $imagefield = new \stdClass();
 356          $imagefield->name = 'image';
 357          $imagefield->type = 'picture';
 358  
 359          $difffield = new \stdClass();
 360          $difffield->name = 'title';
 361          $difffield->type = 'textarea';
 362  
 363          $newfield = new \stdClass();
 364          $newfield->name = 'number';
 365          $newfield->type = 'number';
 366  
 367          return [
 368              'Empty database / Importer with fields' => [
 369                  'currentfields' => [],
 370                  'newfields' => [$titlefield, $descfield, $imagefield],
 371                  'expected' => ['field_created' => 3],
 372              ],
 373              'Database with fields / Empty importer' => [
 374                  'currentfields' => [$titlefield, $descfield, $imagefield],
 375                  'newfields' => [],
 376                  'expected' => ['field_deleted' => 3],
 377              ],
 378              'Fields to create' => [
 379                  'currentfields' => [$titlefield, $descfield],
 380                  'newfields' => [$titlefield, $descfield, $imagefield],
 381                  'expected' => ['field_updated' => 2, 'field_created' => 1],
 382              ],
 383              'Fields to remove' => [
 384                  'currentfields' => [$titlefield, $descfield, $imagefield, $difffield],
 385                  'newfields' => [$titlefield, $descfield, $imagefield],
 386                  'expected' => ['field_updated' => 2, 'field_deleted' => 1],
 387              ],
 388              'Fields to update' => [
 389                  'currentfields' => [$difffield, $descfield, $imagefield],
 390                  'newfields' => [$titlefield, $descfield, $imagefield],
 391                  'expected' => ['field_updated' => 1, 'field_created' => 1, 'field_deleted' => 1],
 392              ],
 393              'Fields to create, remove and update' => [
 394                  'currentfields' => [$titlefield, $descfield, $imagefield, $difffield],
 395                  'newfields' => [$titlefield, $descfield, $newfield],
 396                  'expected' => ['field_updated' => 2, 'field_created' => 1, 'field_deleted' => 2],
 397              ],
 398          ];
 399      }
 400      /**
 401       * Test for needs_mapping method.
 402       *
 403       * @dataProvider preset_importer_provider
 404       *
 405       * @param array $currentfields Fields of the current activity.
 406       * @param array $newfields Fields to be imported.
 407       * @param array $expected Expected events.
 408       */
 409      public function test_importing_events(
 410          array $currentfields,
 411          array $newfields,
 412          array $expected
 413      ) {
 414  
 415          global $USER;
 416  
 417          $this->resetAfterTest();
 418          $this->setAdminUser();
 419          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 420  
 421          // Create a course and a database activity.
 422          $course = $this->getDataGenerator()->create_course();
 423          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 424          // Add current fields to the activity.
 425          foreach ($currentfields as $field) {
 426              $plugingenerator->create_field($field, $activity);
 427          }
 428          $manager = manager::create_from_instance($activity);
 429  
 430          $presetactivity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 431          // Add current fields to the activity.
 432          foreach ($newfields as $field) {
 433              $plugingenerator->create_field($field, $presetactivity);
 434          }
 435  
 436          $record = (object) [
 437              'name' => 'Testing preset name',
 438              'description' => 'Testing preset description',
 439          ];
 440          $saved = $plugingenerator->create_preset($presetactivity, $record);
 441          $savedimporter = new preset_existing_importer($manager, $USER->id . '/Testing preset name');
 442  
 443          // Trigger and capture the event for deleting the field.
 444          $sink = $this->redirectEvents();
 445          $savedimporter->import(false);
 446          $events = $sink->get_events();
 447  
 448          foreach ($expected as $triggeredevent => $count) {
 449              for ($i = 0; $i < $count; $i++) {
 450                  $event = array_shift($events);
 451  
 452                  // Check that the event data is valid.
 453                  $this->assertInstanceOf('\mod_data\event\\'.$triggeredevent, $event);
 454                  $this->assertEquals(\context_module::instance($activity->cmid), $event->get_context());
 455                  $this->assertEventContextNotUsed($event);
 456                  $url = new \moodle_url('/mod/data/field.php', ['d' => $activity->id]);
 457                  $this->assertEquals($url, $event->get_url());
 458              }
 459          }
 460      }
 461  }