Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [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  /**
  18   * Events tests.
  19   *
  20   * @package core_tag
  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 core_tag\event;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  global $CFG;
  31  
  32  // Used to create a wiki page to tag.
  33  require_once($CFG->dirroot . '/mod/wiki/locallib.php');
  34  
  35  class events_test extends \advanced_testcase {
  36  
  37      /**
  38       * Test set up.
  39       *
  40       * This is executed before running any test in this file.
  41       */
  42      public function setUp(): void {
  43          $this->resetAfterTest();
  44      }
  45  
  46      /**
  47       * Test the tag updated event.
  48       */
  49      public function test_tag_updated() {
  50          $this->setAdminUser();
  51  
  52          // Save the system context.
  53          $systemcontext = \context_system::instance();
  54  
  55          // Create a tag we are going to update.
  56          $tag = $this->getDataGenerator()->create_tag();
  57  
  58          // Store the name before we change it.
  59          $oldname = $tag->name;
  60  
  61          // Trigger and capture the event when renaming a tag.
  62          $sink = $this->redirectEvents();
  63          \core_tag_tag::get($tag->id, '*')->update(array('rawname' => 'newname'));
  64          // Update the tag's name since we have renamed it.
  65          $tag->name = 'newname';
  66          $events = $sink->get_events();
  67          $event = reset($events);
  68  
  69          // Check that the event data is valid.
  70          $this->assertInstanceOf('\core\event\tag_updated', $event);
  71          $this->assertEquals($systemcontext, $event->get_context());
  72          $expected = array(SITEID, 'tag', 'update', 'index.php?id=' . $tag->id, $oldname . '->'. $tag->name);
  73          $this->assertEventLegacyLogData($expected, $event);
  74  
  75          // Trigger and capture the event when setting the type of a tag.
  76          $sink = $this->redirectEvents();
  77          \core_tag_tag::get($tag->id, '*')->update(array('isstandard' => 1));
  78          $events = $sink->get_events();
  79          $event = reset($events);
  80  
  81          // Check that the event data is valid.
  82          $this->assertInstanceOf('\core\event\tag_updated', $event);
  83          $this->assertEquals($systemcontext, $event->get_context());
  84          $expected = array(0, 'tag', 'update', 'index.php?id=' . $tag->id, $tag->name);
  85          $this->assertEventLegacyLogData($expected, $event);
  86  
  87          // Trigger and capture the event for setting the description of a tag.
  88          $sink = $this->redirectEvents();
  89          \core_tag_tag::get($tag->id, '*')->update(
  90                  array('description' => 'description', 'descriptionformat' => FORMAT_MOODLE));
  91          $events = $sink->get_events();
  92          $event = reset($events);
  93  
  94          // Check that the event data is valid.
  95          $this->assertInstanceOf('\core\event\tag_updated', $event);
  96          $this->assertEquals($systemcontext, $event->get_context());
  97          $expected = array(0, 'tag', 'update', 'index.php?id=' . $tag->id, $tag->name);
  98          $this->assertEventLegacyLogData($expected, $event);
  99      }
 100  
 101      /**
 102       * Test the tag added event.
 103       */
 104      public function test_tag_added() {
 105          global $DB;
 106  
 107          // Create a course to tag.
 108          $course = $this->getDataGenerator()->create_course();
 109  
 110          // Trigger and capture the event for tagging a course.
 111          $sink = $this->redirectEvents();
 112          \core_tag_tag::set_item_tags('core', 'course', $course->id, \context_course::instance($course->id), array('A tag'));
 113          $events = $sink->get_events();
 114          $event = $events[1];
 115  
 116          // Check that the tag was added to the course and that the event data is valid.
 117          $this->assertEquals(1, $DB->count_records('tag_instance', array('component' => 'core')));
 118          $this->assertInstanceOf('\core\event\tag_added', $event);
 119          $this->assertEquals(\context_course::instance($course->id), $event->get_context());
 120          $expected = array($course->id, 'coursetags', 'add', 'tag/search.php?query=A+tag', 'Course tagged');
 121          $this->assertEventLegacyLogData($expected, $event);
 122  
 123          // Create a question to tag.
 124          $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
 125          $cat = $questiongenerator->create_question_category();
 126          $question = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
 127  
 128          // Trigger and capture the event for tagging a question.
 129          $this->assertEquals(1, $DB->count_records('tag_instance'));
 130          $sink = $this->redirectEvents();
 131          \core_tag_tag::set_item_tags('core_question', 'question', $question->id,
 132              \context::instance_by_id($cat->contextid), array('A tag'));
 133          $events = $sink->get_events();
 134          $event = reset($events);
 135  
 136          // Check that the tag was added to the question and the event data is valid.
 137          $this->assertEquals(1, $DB->count_records('tag_instance', array('component' => 'core')));
 138          $this->assertInstanceOf('\core\event\tag_added', $event);
 139          $this->assertEquals(\context_system::instance(), $event->get_context());
 140          $expected = null;
 141          $this->assertEventLegacyLogData($expected, $event);
 142      }
 143  
 144      /**
 145       * Test the tag removed event.
 146       */
 147      public function test_tag_removed() {
 148          global $DB;
 149  
 150          $this->setAdminUser();
 151  
 152          // Create a course to tag.
 153          $course = $this->getDataGenerator()->create_course();
 154  
 155          // Create a wiki page to tag.
 156          $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
 157          $wiki = $wikigenerator->create_instance(array('course' => $course->id));
 158          $subwikiid = wiki_add_subwiki($wiki->id, 0);
 159          $wikipageid = wiki_create_page($subwikiid, 'Title', FORMAT_HTML, '2');
 160  
 161          // Create the tag.
 162          $tag = $this->getDataGenerator()->create_tag();
 163  
 164          // Assign a tag to a course.
 165          \core_tag_tag::add_item_tag('core', 'course', $course->id, \context_course::instance($course->id), $tag->rawname);
 166  
 167          // Trigger and capture the event for untagging a course.
 168          $sink = $this->redirectEvents();
 169          \core_tag_tag::remove_item_tag('core', 'course', $course->id, $tag->rawname);
 170          $events = $sink->get_events();
 171          $event = reset($events);
 172  
 173          // Check that the tag was removed from the course and the event data is valid.
 174          $this->assertEquals(0, $DB->count_records('tag_instance'));
 175          $this->assertInstanceOf('\core\event\tag_removed', $event);
 176          $this->assertEquals(\context_course::instance($course->id), $event->get_context());
 177  
 178          // Create the tag.
 179          $tag = $this->getDataGenerator()->create_tag();
 180  
 181          // Assign a tag to a wiki this time.
 182          \core_tag_tag::add_item_tag('mod_wiki', 'wiki_pages', $wikipageid, \context_module::instance($wiki->cmid), $tag->rawname);
 183  
 184          // Trigger and capture the event for deleting this tag instance.
 185          $sink = $this->redirectEvents();
 186          \core_tag_tag::remove_item_tag('mod_wiki', 'wiki_pages', $wikipageid, $tag->rawname);
 187          $events = $sink->get_events();
 188          $event = reset($events);
 189  
 190          // Check that tag was removed from the wiki page and the event data is valid.
 191          $this->assertEquals(0, $DB->count_records('tag_instance'));
 192          $this->assertInstanceOf('\core\event\tag_removed', $event);
 193          $this->assertEquals(\context_module::instance($wiki->cmid), $event->get_context());
 194  
 195          // Create a tag again - the other would have been deleted since there were no more instances associated with it.
 196          $tag = $this->getDataGenerator()->create_tag();
 197  
 198          // Assign a tag to the wiki again.
 199          \core_tag_tag::add_item_tag('mod_wiki', 'wiki_pages', $wikipageid, \context_module::instance($wiki->cmid), $tag->rawname);
 200  
 201          // Now we want to delete this tag, and because there is only one tag instance
 202          // associated with it, it should get deleted as well.
 203          $sink = $this->redirectEvents();
 204          \core_tag_tag::delete_tags($tag->id);
 205          $events = $sink->get_events();
 206          $event = reset($events);
 207  
 208          // Check that tag was removed from the wiki page and the event data is valid.
 209          $this->assertEquals(0, $DB->count_records('tag_instance'));
 210          $this->assertInstanceOf('\core\event\tag_removed', $event);
 211          $this->assertEquals(\context_module::instance($wiki->cmid), $event->get_context());
 212  
 213          // Create a tag again - the other would have been deleted since there were no more instances associated with it.
 214          $tag = $this->getDataGenerator()->create_tag();
 215  
 216          // Assign a tag to the wiki again.
 217          \core_tag_tag::add_item_tag('mod_wiki', 'wiki_pages', $wikipageid, \context_module::instance($wiki->cmid), $tag->rawname);
 218  
 219          // Delete all tag instances for this wiki instance.
 220          $sink = $this->redirectEvents();
 221          \core_tag_tag::delete_instances('mod_wiki', 'wiki_pages', \context_module::instance($wiki->cmid)->id);
 222          $events = $sink->get_events();
 223          $event = reset($events);
 224  
 225          // Check that tag was removed from the wiki page and the event data is valid.
 226          $this->assertEquals(0, $DB->count_records('tag_instance'));
 227          $this->assertInstanceOf('\core\event\tag_removed', $event);
 228          $this->assertEquals(\context_module::instance($wiki->cmid), $event->get_context());
 229  
 230          // Create another wiki.
 231          $wiki2 = $wikigenerator->create_instance(array('course' => $course->id));
 232          $subwikiid2 = wiki_add_subwiki($wiki2->id, 0);
 233          $wikipageid2 = wiki_create_page($subwikiid2, 'Title', FORMAT_HTML, '2');
 234  
 235          // Assign a tag to both wiki pages.
 236          \core_tag_tag::add_item_tag('mod_wiki', 'wiki_pages', $wikipageid, \context_module::instance($wiki->cmid), $tag->rawname);
 237          \core_tag_tag::add_item_tag('mod_wiki', 'wiki_pages', $wikipageid2, \context_module::instance($wiki2->cmid), $tag->rawname);
 238  
 239          // Now remove all tag_instances associated with all wikis.
 240          $sink = $this->redirectEvents();
 241          \core_tag_tag::delete_instances('mod_wiki');
 242          $events = $sink->get_events();
 243  
 244          // There will be two events - one for each wiki instance removed.
 245          $this->assertCount(2, $events);
 246          $contexts = [\context_module::instance($wiki->cmid), \context_module::instance($wiki2->cmid)];
 247          $this->assertNotEquals($events[0]->contextid, $events[1]->contextid);
 248  
 249          // Check that the tags were removed from the wiki pages.
 250          $this->assertEquals(0, $DB->count_records('tag_instance'));
 251  
 252          // Check the first event data is valid.
 253          $this->assertInstanceOf('\core\event\tag_removed', $events[0]);
 254          $this->assertContains($events[0]->get_context(), $contexts);
 255  
 256          // Check that the second event data is valid.
 257          $this->assertInstanceOf('\core\event\tag_removed', $events[1]);
 258          $this->assertContains($events[1]->get_context(), $contexts);
 259      }
 260  
 261      /**
 262       * Test the tag flagged event.
 263       */
 264      public function test_tag_flagged() {
 265          global $DB;
 266  
 267          $this->setAdminUser();
 268  
 269          // Create tags we are going to flag.
 270          $tag = $this->getDataGenerator()->create_tag();
 271          $tag2 = $this->getDataGenerator()->create_tag();
 272          $tags = array($tag, $tag2);
 273  
 274          // Trigger and capture the event for setting the flag of a tag.
 275          $sink = $this->redirectEvents();
 276          \core_tag_tag::get($tag->id, '*')->flag();
 277          $events = $sink->get_events();
 278          $event = reset($events);
 279  
 280          // Check that the flag was updated.
 281          $tag = $DB->get_record('tag', array('id' => $tag->id));
 282          $this->assertEquals(1, $tag->flag);
 283  
 284          // Check that the event data is valid.
 285          $this->assertInstanceOf('\core\event\tag_flagged', $event);
 286          $this->assertEquals(\context_system::instance(), $event->get_context());
 287          $expected = array(SITEID, 'tag', 'flag', 'index.php?id=' . $tag->id, $tag->id, '', '2');
 288          $this->assertEventLegacyLogData($expected, $event);
 289  
 290          // Unset the flag for both (though by default tag2 should have been created with 0 already).
 291          foreach ($tags as $t) {
 292              \core_tag_tag::get($t->id, '*')->reset_flag();
 293          }
 294  
 295          // Trigger and capture the event for setting the flag for multiple tags.
 296          $sink = $this->redirectEvents();
 297          foreach ($tags as $t) {
 298              \core_tag_tag::get($t->id, '*')->flag();
 299          }
 300          $events = $sink->get_events();
 301  
 302          // Check that the flags were updated.
 303          $tag = $DB->get_record('tag', array('id' => $tag->id));
 304          $this->assertEquals(1, $tag->flag);
 305          $tag2 = $DB->get_record('tag', array('id' => $tag2->id));
 306          $this->assertEquals(1, $tag2->flag);
 307  
 308          // Confirm the events.
 309          $event = $events[0];
 310          $this->assertInstanceOf('\core\event\tag_flagged', $event);
 311          $this->assertEquals(\context_system::instance(), $event->get_context());
 312          $expected = array(SITEID, 'tag', 'flag', 'index.php?id=' . $tag->id, $tag->id, '', '2');
 313          $this->assertEventLegacyLogData($expected, $event);
 314  
 315          $event = $events[1];
 316          $this->assertInstanceOf('\core\event\tag_flagged', $event);
 317          $this->assertEquals(\context_system::instance(), $event->get_context());
 318          $expected = array(SITEID, 'tag', 'flag', 'index.php?id=' . $tag2->id, $tag2->id, '', '2');
 319          $this->assertEventLegacyLogData($expected, $event);
 320      }
 321  
 322      /**
 323       * Test the tag unflagged event.
 324       */
 325      public function test_tag_unflagged() {
 326          global $DB;
 327  
 328          $this->setAdminUser();
 329  
 330          // Create tags we are going to unflag.
 331          $tag = $this->getDataGenerator()->create_tag();
 332          $tag2 = $this->getDataGenerator()->create_tag();
 333          $tags = array($tag, $tag2);
 334  
 335          // Flag it.
 336          \core_tag_tag::get($tag->id, '*')->flag();
 337  
 338          // Trigger and capture the event for unsetting the flag of a tag.
 339          $sink = $this->redirectEvents();
 340          \core_tag_tag::get($tag->id, '*')->reset_flag();
 341          $events = $sink->get_events();
 342          $event = reset($events);
 343  
 344          // Check that the flag was updated.
 345          $tag = $DB->get_record('tag', array('id' => $tag->id));
 346          $this->assertEquals(0, $tag->flag);
 347  
 348          // Check that the event data is valid.
 349          $this->assertInstanceOf('\core\event\tag_unflagged', $event);
 350          $this->assertEquals(\context_system::instance(), $event->get_context());
 351  
 352          // Set the flag back for both.
 353          foreach ($tags as $t) {
 354              \core_tag_tag::get($t->id, '*')->flag();
 355          }
 356  
 357          // Trigger and capture the event for unsetting the flag for multiple tags.
 358          $sink = $this->redirectEvents();
 359          foreach ($tags as $t) {
 360              \core_tag_tag::get($t->id, '*')->reset_flag();
 361          }
 362          $events = $sink->get_events();
 363  
 364          // Check that the flags were updated.
 365          $tag = $DB->get_record('tag', array('id' => $tag->id));
 366          $this->assertEquals(0, $tag->flag);
 367          $tag2 = $DB->get_record('tag', array('id' => $tag2->id));
 368          $this->assertEquals(0, $tag2->flag);
 369  
 370          // Confirm the events.
 371          $event = $events[0];
 372          $this->assertInstanceOf('\core\event\tag_unflagged', $event);
 373          $this->assertEquals(\context_system::instance(), $event->get_context());
 374  
 375          $event = $events[1];
 376          $this->assertInstanceOf('\core\event\tag_unflagged', $event);
 377          $this->assertEquals(\context_system::instance(), $event->get_context());
 378      }
 379  
 380      /**
 381       * Test the tag deleted event
 382       */
 383      public function test_tag_deleted() {
 384          global $DB;
 385  
 386          $this->setAdminUser();
 387  
 388          // Create a course and a user.
 389          $course = $this->getDataGenerator()->create_course();
 390          $user = $this->getDataGenerator()->create_user();
 391  
 392          // Create tag we are going to delete.
 393          $tag = $this->getDataGenerator()->create_tag();
 394  
 395          // Trigger and capture the event for deleting a tag.
 396          $sink = $this->redirectEvents();
 397          \core_tag_tag::delete_tags($tag->id);
 398          $events = $sink->get_events();
 399          $event = reset($events);
 400  
 401          // Check that the tag was deleted and the event data is valid.
 402          $this->assertEquals(0, $DB->count_records('tag'));
 403          $this->assertInstanceOf('\core\event\tag_deleted', $event);
 404          $this->assertEquals(\context_system::instance(), $event->get_context());
 405  
 406          // Create two tags we are going to delete to ensure passing multiple tags work.
 407          $tag = $this->getDataGenerator()->create_tag();
 408          $tag2 = $this->getDataGenerator()->create_tag();
 409  
 410          // Trigger and capture the events for deleting multiple tags.
 411          $sink = $this->redirectEvents();
 412          \core_tag_tag::delete_tags(array($tag->id, $tag2->id));
 413          $events = $sink->get_events();
 414  
 415          // Check that the tags were deleted and the events data is valid.
 416          $this->assertEquals(0, $DB->count_records('tag'));
 417          foreach ($events as $event) {
 418              $this->assertInstanceOf('\core\event\tag_deleted', $event);
 419              $this->assertEquals(\context_system::instance(), $event->get_context());
 420          }
 421  
 422          // Add a tag instance to a course.
 423          \core_tag_tag::add_item_tag('core', 'course', $course->id, \context_course::instance($course->id), 'cat', $user->id);
 424  
 425          // Trigger and capture the event for deleting a personal tag for a user for a course.
 426          $sink = $this->redirectEvents();
 427          \core_tag_tag::remove_item_tag('core', 'course', $course->id, 'cat', $user->id);
 428          $events = $sink->get_events();
 429          $event = $events[1];
 430  
 431          // Check that the tag was deleted and the event data is valid.
 432          $this->assertEquals(0, $DB->count_records('tag'));
 433          $this->assertInstanceOf('\core\event\tag_deleted', $event);
 434          $this->assertEquals(\context_system::instance(), $event->get_context());
 435  
 436          // Add the tag instance to the course again as it was deleted.
 437          \core_tag_tag::add_item_tag('core', 'course', $course->id, \context_course::instance($course->id), 'dog', $user->id);
 438  
 439          // Trigger and capture the event for deleting all tags in a course.
 440          $sink = $this->redirectEvents();
 441          \core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
 442          $events = $sink->get_events();
 443          $event = $events[1];
 444  
 445          // Check that the tag was deleted and the event data is valid.
 446          $this->assertEquals(0, $DB->count_records('tag'));
 447          $this->assertInstanceOf('\core\event\tag_deleted', $event);
 448          $this->assertEquals(\context_system::instance(), $event->get_context());
 449  
 450          // Add multiple tag instances now and check that it still works.
 451          \core_tag_tag::set_item_tags('core', 'course', $course->id, \context_course::instance($course->id),
 452              array('fish', 'hamster'), $user->id);
 453  
 454          // Trigger and capture the event for deleting all tags in a course.
 455          $sink = $this->redirectEvents();
 456          \core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
 457          $events = $sink->get_events();
 458          $events = array($events[1], $events[3]);
 459  
 460          // Check that the tags were deleted and the events data is valid.
 461          $this->assertEquals(0, $DB->count_records('tag'));
 462          foreach ($events as $event) {
 463              $this->assertInstanceOf('\core\event\tag_deleted', $event);
 464              $this->assertEquals(\context_system::instance(), $event->get_context());
 465          }
 466      }
 467  
 468      /**
 469       * Test the tag created event.
 470       */
 471      public function test_tag_created() {
 472          global $DB;
 473  
 474          // Trigger and capture the event for creating a tag.
 475          $sink = $this->redirectEvents();
 476          \core_tag_tag::create_if_missing(\core_tag_area::get_collection('core', 'course'),
 477                  array('A really awesome tag!'));
 478          $events = $sink->get_events();
 479          $event = reset($events);
 480  
 481          // Check that the tag was created and the event data is valid.
 482          $this->assertEquals(1, $DB->count_records('tag'));
 483          $this->assertInstanceOf('\core\event\tag_created', $event);
 484          $this->assertEquals(\context_system::instance(), $event->get_context());
 485      }
 486  }