Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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 39 and 310]

   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
  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  defined('MOODLE_INTERNAL') || die();
  27  
  28  require_once (__DIR__.'/fixtures/event_fixtures.php');
  29  
  30  class core_events_testcase extends advanced_testcase {
  31  
  32      /**
  33       * Test set up.
  34       *
  35       * This is executed before running any test in this file.
  36       */
  37      public function setUp() {
  38          $this->resetAfterTest();
  39      }
  40  
  41      /**
  42       * Test the course category created event.
  43       */
  44      public function test_course_category_created() {
  45          // Trigger and capture the event.
  46          $sink = $this->redirectEvents();
  47          $category = $this->getDataGenerator()->create_category();
  48          $events = $sink->get_events();
  49          $event = reset($events);
  50  
  51          // Check that the event data is valid.
  52          $this->assertInstanceOf('\core\event\course_category_created', $event);
  53          $this->assertEquals(context_coursecat::instance($category->id), $event->get_context());
  54          $url = new moodle_url('/course/management.php', array('categoryid' => $event->objectid));
  55          $this->assertEquals($url, $event->get_url());
  56          $expected = array(SITEID, 'category', 'add', 'editcategory.php?id=' . $category->id, $category->id);
  57          $this->assertEventLegacyLogData($expected, $event);
  58          $this->assertEventContextNotUsed($event);
  59      }
  60  
  61      /**
  62       * Test the course category updated event.
  63       */
  64      public function test_course_category_updated() {
  65          // Create a category.
  66          $category = $this->getDataGenerator()->create_category();
  67  
  68          // Create some data we are going to use to update this category.
  69          $data = new stdClass();
  70          $data->name = 'Category name change';
  71  
  72          // Trigger and capture the event for updating a category.
  73          $sink = $this->redirectEvents();
  74          $category->update($data);
  75          $events = $sink->get_events();
  76          $event = reset($events);
  77  
  78          // Check that the event data is valid.
  79          $this->assertInstanceOf('\core\event\course_category_updated', $event);
  80          $this->assertEquals(context_coursecat::instance($category->id), $event->get_context());
  81          $url = new moodle_url('/course/editcategory.php', array('id' => $event->objectid));
  82          $this->assertEquals($url, $event->get_url());
  83          $expected = array(SITEID, 'category', 'update', 'editcategory.php?id=' . $category->id, $category->id);
  84          $this->assertEventLegacyLogData($expected, $event);
  85  
  86          // Create another category and a child category.
  87          $category2 = $this->getDataGenerator()->create_category();
  88          $childcat = $this->getDataGenerator()->create_category(array('parent' => $category2->id));
  89  
  90          // Trigger and capture the event for changing the parent of a category.
  91          $sink = $this->redirectEvents();
  92          $childcat->change_parent($category);
  93          $events = $sink->get_events();
  94          $event = reset($events);
  95  
  96          // Check that the event data is valid.
  97          $this->assertInstanceOf('\core\event\course_category_updated', $event);
  98          $this->assertEquals(context_coursecat::instance($childcat->id), $event->get_context());
  99          $expected = array(SITEID, 'category', 'move', 'editcategory.php?id=' . $childcat->id, $childcat->id);
 100          $this->assertEventLegacyLogData($expected, $event);
 101  
 102          // Trigger and capture the event for changing the sortorder of a category.
 103          $sink = $this->redirectEvents();
 104          $category2->change_sortorder_by_one(true);
 105          $events = $sink->get_events();
 106          $event = reset($events);
 107  
 108          // Check that the event data is valid.
 109          $this->assertInstanceOf('\core\event\course_category_updated', $event);
 110          $this->assertEquals(context_coursecat::instance($category2->id), $event->get_context());
 111          $expected = array(SITEID, 'category', 'move', 'management.php?categoryid=' . $category2->id, $category2->id);
 112          $this->assertEventLegacyLogData($expected, $event);
 113  
 114          // Trigger and capture the event for deleting a category and moving it's children to another.
 115          $sink = $this->redirectEvents();
 116          $category->delete_move($category->id);
 117          $events = $sink->get_events();
 118          $event = reset($events);
 119  
 120          // Check that the event data is valid.
 121          $this->assertInstanceOf('\core\event\course_category_updated', $event);
 122          $this->assertEquals(context_coursecat::instance($childcat->id), $event->get_context());
 123          $expected = array(SITEID, 'category', 'move', 'editcategory.php?id=' . $childcat->id, $childcat->id);
 124          $this->assertEventLegacyLogData($expected, $event);
 125  
 126          // Trigger and capture the event for hiding a category.
 127          $sink = $this->redirectEvents();
 128          $category2->hide();
 129          $events = $sink->get_events();
 130          $event = reset($events);
 131  
 132          // Check that the event data is valid.
 133          $this->assertInstanceOf('\core\event\course_category_updated', $event);
 134          $this->assertEquals(context_coursecat::instance($category2->id), $event->get_context());
 135          $expected = array(SITEID, 'category', 'hide', 'editcategory.php?id=' . $category2->id, $category2->id);
 136          $this->assertEventLegacyLogData($expected, $event);
 137  
 138          // Trigger and capture the event for unhiding a category.
 139          $sink = $this->redirectEvents();
 140          $category2->show();
 141          $events = $sink->get_events();
 142          $event = reset($events);
 143  
 144          // Check that the event data is valid.
 145          $this->assertInstanceOf('\core\event\course_category_updated', $event);
 146          $this->assertEquals(context_coursecat::instance($category2->id), $event->get_context());
 147          $expected = array(SITEID, 'category', 'show', 'editcategory.php?id=' . $category2->id, $category2->id);
 148          $this->assertEventLegacyLogData($expected, $event);
 149          $this->assertEventContextNotUsed($event);
 150      }
 151  
 152      /**
 153       * Test the email failed event.
 154       *
 155       * It's not possible to use the moodle API to simulate the failure of sending
 156       * an email, so here we simply create the event and trigger it.
 157       */
 158      public function test_email_failed() {
 159          // Trigger event for failing to send email.
 160          $event = \core\event\email_failed::create(array(
 161              'context' => context_system::instance(),
 162              'userid' => 1,
 163              'relateduserid' => 2,
 164              'other' => array(
 165                  'subject' => 'This is a subject',
 166                  'message' => 'This is a message',
 167                  'errorinfo' => 'The email failed to send!'
 168              )
 169          ));
 170  
 171          // Trigger and capture the event.
 172          $sink = $this->redirectEvents();
 173          $event->trigger();
 174          $events = $sink->get_events();
 175          $event = reset($events);
 176  
 177          $this->assertInstanceOf('\core\event\email_failed', $event);
 178          $this->assertEquals(context_system::instance(), $event->get_context());
 179          $expected = array(SITEID, 'library', 'mailer', qualified_me(), 'ERROR: The email failed to send!');
 180          $this->assertEventLegacyLogData($expected, $event);
 181          $this->assertEventContextNotUsed($event);
 182      }
 183  
 184      /**
 185       * There is no api involved so the best we can do is test legacy data by triggering event manually.
 186       */
 187      public function test_course_user_report_viewed() {
 188  
 189          $user = $this->getDataGenerator()->create_user();
 190          $course = $this->getDataGenerator()->create_course();
 191          $context = context_course::instance($course->id);
 192  
 193          $eventparams = array();
 194          $eventparams['context'] = $context;
 195          $eventparams['relateduserid'] = $user->id;
 196          $eventparams['other'] = array();
 197          $eventparams['other']['mode'] = 'grade';
 198          $event = \core\event\course_user_report_viewed::create($eventparams);
 199  
 200          // Trigger and capture the event.
 201          $sink = $this->redirectEvents();
 202          $event->trigger();
 203          $events = $sink->get_events();
 204          $event = reset($events);
 205  
 206          $this->assertInstanceOf('\core\event\course_user_report_viewed', $event);
 207          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 208          $expected = array($course->id, 'course', 'user report', 'user.php?id=' . $course->id . '&amp;user='
 209                  . $user->id . '&amp;mode=grade', $user->id);
 210          $this->assertEventLegacyLogData($expected, $event);
 211          $this->assertEventContextNotUsed($event);
 212      }
 213  
 214      /**
 215       * There is no api involved so the best we can do is test legacy data by triggering event manually.
 216       */
 217      public function test_course_viewed() {
 218  
 219          $user = $this->getDataGenerator()->create_user();
 220          $course = $this->getDataGenerator()->create_course();
 221          $context = context_course::instance($course->id);
 222  
 223          // First try with no optional parameters.
 224          $eventparams = array();
 225          $eventparams['context'] = $context;
 226          $event = \core\event\course_viewed::create($eventparams);
 227  
 228          // Trigger and capture the event.
 229          $sink = $this->redirectEvents();
 230          $event->trigger();
 231          $events = $sink->get_events();
 232          $event = reset($events);
 233  
 234          $this->assertInstanceOf('\core\event\course_viewed', $event);
 235          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 236          $expected = array($course->id, 'course', 'view', 'view.php?id=' . $course->id, $course->id);
 237          $this->assertEventLegacyLogData($expected, $event);
 238          $this->assertEventContextNotUsed($event);
 239  
 240          // Now try with optional parameters.
 241          $sectionnumber = 7;
 242          $eventparams = array();
 243          $eventparams['context'] = $context;
 244          $eventparams['other'] = array('coursesectionnumber' => $sectionnumber);
 245          $event = \core\event\course_viewed::create($eventparams);
 246  
 247          // Trigger and capture the event.
 248          $sink = $this->redirectEvents();
 249          $event->trigger();
 250          $loggeddata = $event->get_data();
 251          $events = $sink->get_events();
 252          $event = reset($events);
 253  
 254  
 255          $this->assertInstanceOf('\core\event\course_viewed', $event);
 256          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 257          $expected = array($course->id, 'course', 'view section', 'view.php?id=' . $course->id . '&amp;section='
 258                  . $sectionnumber, $sectionnumber);
 259          $this->assertEventLegacyLogData($expected, $event);
 260          $this->assertEventContextNotUsed($event);
 261  
 262          delete_course($course->id, false);
 263          $restored = \core\event\base::restore($loggeddata, array('origin' => 'web', 'ip' => '127.0.0.1'));
 264          $this->assertInstanceOf('\core\event\course_viewed', $restored);
 265          $this->assertNull($restored->get_url());
 266      }
 267  
 268      public function test_recent_capability_viewed() {
 269          $this->resetAfterTest();
 270  
 271          $this->setAdminUser();
 272          $course = $this->getDataGenerator()->create_course();
 273          $context = context_course::instance($course->id);
 274  
 275          $event = \core\event\recent_activity_viewed::create(array('context' => $context));
 276  
 277          // Trigger and capture the event.
 278          $sink = $this->redirectEvents();
 279          $event->trigger();
 280          $events = $sink->get_events();
 281          $event = reset($events);
 282  
 283          $this->assertInstanceOf('\core\event\recent_activity_viewed', $event);
 284          $this->assertEquals($context, $event->get_context());
 285          $expected = array($course->id, "course", "recent", "recent.php?id=$course->id", $course->id);
 286          $this->assertEventLegacyLogData($expected, $event);
 287          $this->assertEventContextNotUsed($event);
 288          $url = new moodle_url('/course/recent.php', array('id' => $course->id));
 289          $this->assertEquals($url, $event->get_url());
 290          $event->get_name();
 291      }
 292  
 293      public function test_user_profile_viewed() {
 294          $this->resetAfterTest();
 295          $this->setAdminUser();
 296  
 297          $user = $this->getDataGenerator()->create_user();
 298          $course = $this->getDataGenerator()->create_course();
 299          $coursecontext = context_course::instance($course->id);
 300  
 301          // User profile viewed in course context.
 302          $eventparams = array(
 303              'objectid' => $user->id,
 304              'relateduserid' => $user->id,
 305              'courseid' => $course->id,
 306              'context' => $coursecontext,
 307              'other' => array(
 308                  'courseid' => $course->id,
 309                  'courseshortname' => $course->shortname,
 310                  'coursefullname' => $course->fullname
 311              )
 312          );
 313          $event = \core\event\user_profile_viewed::create($eventparams);
 314  
 315          // Trigger and capture the event.
 316          $sink = $this->redirectEvents();
 317          $event->trigger();
 318          $events = $sink->get_events();
 319          $event = reset($events);
 320  
 321          $this->assertInstanceOf('\core\event\user_profile_viewed', $event);
 322          $log = array($course->id, 'user', 'view', 'view.php?id=' . $user->id . '&course=' . $course->id, $user->id);
 323          $this->assertEventLegacyLogData($log, $event);
 324          $this->assertEventContextNotUsed($event);
 325  
 326          // User profile viewed in user context.
 327          $usercontext = context_user::instance($user->id);
 328          $eventparams['context'] = $usercontext;
 329          unset($eventparams['courseid'], $eventparams['other']);
 330          $event = \core\event\user_profile_viewed::create($eventparams);
 331  
 332          // Trigger and capture the event.
 333          $sink = $this->redirectEvents();
 334          $event->trigger();
 335          $events = $sink->get_events();
 336          $event = reset($events);
 337  
 338          $this->assertInstanceOf('\core\event\user_profile_viewed', $event);
 339          $expected = null;
 340          $this->assertEventLegacyLogData($expected, $event);
 341          $this->assertEventContextNotUsed($event);
 342      }
 343  
 344      /**
 345       * There is no API associated with this event, so we will just test standard features.
 346       */
 347      public function test_grade_viewed() {
 348          $this->resetAfterTest();
 349          $this->setAdminUser();
 350  
 351          $user = $this->getDataGenerator()->create_user();
 352          $course = $this->getDataGenerator()->create_course();
 353          $coursecontext = context_course::instance($course->id);
 354  
 355          $event = \core_tests\event\grade_report_viewed::create(
 356              array(
 357                  'context' => $coursecontext,
 358                  'courseid' => $course->id,
 359                  'userid' => $user->id,
 360              )
 361          );
 362  
 363          // Trigger and capture the event.
 364          $sink = $this->redirectEvents();
 365          $event->trigger();
 366          $events = $sink->get_events();
 367          $event = reset($events);
 368  
 369          $this->assertInstanceOf('\core\event\grade_report_viewed', $event);
 370          $this->assertEquals($event->courseid, $course->id);
 371          $this->assertEquals($event->userid, $user->id);
 372          $this->assertEventContextNotUsed($event);
 373      }
 374  
 375      /**
 376       * Test the database text field content replaced event.
 377       */
 378      public function test_database_text_field_content_replaced() {
 379          global $CFG;
 380  
 381          require_once($CFG->dirroot . '/lib/adminlib.php');
 382  
 383          // Trigger and capture the event for finding and replacing strings in the database.
 384          $sink = $this->redirectEvents();
 385          ob_start();
 386          db_replace('searchstring', 'replacestring');
 387          ob_end_clean();
 388          $events = $sink->get_events();
 389          $event = reset($events);
 390  
 391          // Check that the event data is valid.
 392          $this->assertInstanceOf('\core\event\database_text_field_content_replaced', $event);
 393          $this->assertEquals(context_system::instance(), $event->get_context());
 394          $this->assertEquals('searchstring', $event->other['search']);
 395          $this->assertEquals('replacestring', $event->other['replace']);
 396      }
 397  }