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 311 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  /**
  18   * Events tests.
  19   *
  20   * @package    mod_lesson
  21   * @category   test
  22   * @copyright  2013 Mark Nelson <markn@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace mod_lesson\event;
  27  
  28  use lesson;
  29  
  30  defined('MOODLE_INTERNAL') || die();
  31  
  32  global $CFG;
  33  
  34  require_once($CFG->dirroot.'/mod/lesson/locallib.php');
  35  
  36  class events_test extends \advanced_testcase {
  37  
  38      /** @var stdClass the course used for testing */
  39      private $course;
  40  
  41      /** @var lesson the lesson used for testing */
  42      private $lesson;
  43  
  44      /**
  45       * Test set up.
  46       *
  47       * This is executed before running any test in this file.
  48       */
  49      public function setUp(): void {
  50          $this->resetAfterTest();
  51  
  52          $this->setAdminUser();
  53          $this->course = $this->getDataGenerator()->create_course();
  54          $lesson = $this->getDataGenerator()->create_module('lesson', array('course' => $this->course->id));
  55  
  56          // Convert to a lesson object.
  57          $this->lesson = new lesson($lesson);
  58      }
  59  
  60      /**
  61       * Test the page created event.
  62       *
  63       */
  64      public function test_page_created() {
  65  
  66          // Set up a generator to create content.
  67          $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
  68          // Trigger and capture the event.
  69          $sink = $this->redirectEvents();
  70          $pagerecord = $generator->create_content($this->lesson);
  71          $page = $this->lesson->load_page($pagerecord->id);
  72  
  73          // Get our event event.
  74          $events = $sink->get_events();
  75          $event = reset($events);
  76  
  77          // Check that the event data is valid.
  78          $this->assertInstanceOf('\mod_lesson\event\page_created', $event);
  79          $this->assertEquals($page->id, $event->objectid);
  80          $this->assertEventContextNotUsed($event);
  81          $this->assertDebuggingNotCalled();
  82      }
  83  
  84      /**
  85       * Test the page created event.
  86       *
  87       */
  88      public function test_page_moved() {
  89  
  90          // Set up a generator to create content.
  91          // paga3 is the first one and page1 the last one.
  92          $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
  93          $pagerecord1 = $generator->create_content($this->lesson);
  94          $page1 = $this->lesson->load_page($pagerecord1->id);
  95          $pagerecord2 = $generator->create_content($this->lesson);
  96          $page2 = $this->lesson->load_page($pagerecord2->id);
  97          $pagerecord3 = $generator->create_content($this->lesson);
  98          $page3 = $this->lesson->load_page($pagerecord3->id);
  99          // Trigger and capture the event.
 100          $sink = $this->redirectEvents();
 101          $this->lesson->resort_pages($page3->id, $pagerecord2->id);
 102          // Get our event event.
 103          $events = $sink->get_events();
 104          $event = reset($events);
 105  
 106          $this->assertCount(1, $events);
 107          // Check that the event data is valid.
 108          $this->assertInstanceOf('\mod_lesson\event\page_moved', $event);
 109          $this->assertEquals($page3->id, $event->objectid);
 110          $this->assertEquals($pagerecord1->id, $event->other['nextpageid']);
 111          $this->assertEquals($pagerecord2->id, $event->other['prevpageid']);
 112          $this->assertEventContextNotUsed($event);
 113          $this->assertDebuggingNotCalled();
 114      }
 115  
 116      /**
 117       * Test the page deleted event.
 118       *
 119       */
 120      public function test_page_deleted() {
 121  
 122          // Set up a generator to create content.
 123          $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
 124          // Create a content page.
 125          $pagerecord = $generator->create_content($this->lesson);
 126          // Get the lesson page information.
 127          $page = $this->lesson->load_page($pagerecord->id);
 128          // Trigger and capture the event.
 129          $sink = $this->redirectEvents();
 130          $page->delete();
 131  
 132          // Get our event event.
 133          $events = $sink->get_events();
 134          $event = reset($events);
 135  
 136          // Check that the event data is valid.
 137          $this->assertInstanceOf('\mod_lesson\event\page_deleted', $event);
 138          $this->assertEquals($page->id, $event->objectid);
 139          $this->assertEventContextNotUsed($event);
 140          $this->assertDebuggingNotCalled();
 141      }
 142  
 143      /**
 144       * Test the page updated event.
 145       *
 146       * There is no external API for updateing a page, so the unit test will simply
 147       * create and trigger the event and ensure data is returned as expected.
 148       */
 149      public function test_page_updated() {
 150  
 151          // Trigger an event: page updated.
 152          $eventparams = array(
 153              'context' => \context_module::instance($this->lesson->properties()->cmid),
 154              'objectid' => 25,
 155              'other' => array(
 156                  'pagetype' => 'True/false'
 157                  )
 158          );
 159  
 160          $event = \mod_lesson\event\page_updated::create($eventparams);
 161  
 162          // Trigger and capture the event.
 163          $sink = $this->redirectEvents();
 164          $event->trigger();
 165          $events = $sink->get_events();
 166          $event = reset($events);
 167  
 168          // Check that the event data is valid.
 169          $this->assertInstanceOf('\mod_lesson\event\page_updated', $event);
 170          $this->assertEquals(25, $event->objectid);
 171          $this->assertEquals('True/false', $event->other['pagetype']);
 172          $this->assertEventContextNotUsed($event);
 173          $this->assertDebuggingNotCalled();
 174      }
 175  
 176      /**
 177       * Test the essay attempt viewed event.
 178       *
 179       * There is no external API for viewing an essay attempt, so the unit test will simply
 180       * create and trigger the event and ensure the legacy log data is returned as expected.
 181       */
 182      public function test_essay_attempt_viewed() {
 183          // Create a essays list viewed event
 184          $event = \mod_lesson\event\essay_attempt_viewed::create(array(
 185              'objectid' => $this->lesson->id,
 186              'relateduserid' => 3,
 187              'context' => \context_module::instance($this->lesson->properties()->cmid),
 188              'courseid' => $this->course->id
 189          ));
 190  
 191          // Trigger and capture the event.
 192          $sink = $this->redirectEvents();
 193          $event->trigger();
 194          $events = $sink->get_events();
 195          $event = reset($events);
 196  
 197          // Check that the event data is valid.
 198          $this->assertInstanceOf('\mod_lesson\event\essay_attempt_viewed', $event);
 199          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 200          $this->assertEventContextNotUsed($event);
 201      }
 202  
 203      /**
 204       * Test the lesson started event.
 205       */
 206      public function test_lesson_started() {
 207          // Trigger and capture the event.
 208          $sink = $this->redirectEvents();
 209          $this->lesson->start_timer();
 210          $events = $sink->get_events();
 211          $event = reset($events);
 212  
 213          // Check that the event data is valid.
 214          $this->assertInstanceOf('\mod_lesson\event\lesson_started', $event);
 215          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 216          $this->assertEventContextNotUsed($event);
 217      }
 218  
 219      /**
 220       * Test the lesson restarted event.
 221       */
 222      public function test_lesson_restarted() {
 223  
 224          // Initialize timer.
 225          $this->lesson->start_timer();
 226          // Trigger and capture the event.
 227          $sink = $this->redirectEvents();
 228          $this->lesson->update_timer(true);
 229          $events = $sink->get_events();
 230          $event = reset($events);
 231  
 232          // Check that the event data is valid.
 233          $this->assertInstanceOf('\mod_lesson\event\lesson_restarted', $event);
 234          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 235          $expected = array($this->course->id, 'lesson', 'start', 'view.php?id=' . $this->lesson->properties()->cmid,
 236              $this->lesson->properties()->id, $this->lesson->properties()->cmid);
 237          $this->assertEventContextNotUsed($event);
 238          $this->assertDebuggingNotCalled();
 239  
 240      }
 241  
 242      /**
 243       * Test the lesson restarted event.
 244       */
 245      public function test_lesson_resumed() {
 246  
 247          // Initialize timer.
 248          $this->lesson->start_timer();
 249          // Trigger and capture the event.
 250          $sink = $this->redirectEvents();
 251          $this->lesson->update_timer(true, true);
 252          $events = $sink->get_events();
 253          $event = reset($events);
 254  
 255          // Check that the event data is valid.
 256          $this->assertInstanceOf('\mod_lesson\event\lesson_resumed', $event);
 257          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 258          $expected = array($this->course->id, 'lesson', 'start', 'view.php?id=' . $this->lesson->properties()->cmid,
 259              $this->lesson->properties()->id, $this->lesson->properties()->cmid);
 260          $this->assertEventContextNotUsed($event);
 261          $this->assertDebuggingNotCalled();
 262  
 263      }
 264      /**
 265       * Test the lesson ended event.
 266       */
 267      public function test_lesson_ended() {
 268          global $DB, $USER;
 269  
 270          // Add a lesson timer so that stop_timer() does not complain.
 271          $lessontimer = new \stdClass();
 272          $lessontimer->lessonid = $this->lesson->properties()->id;
 273          $lessontimer->userid = $USER->id;
 274          $lessontimer->startime = time();
 275          $lessontimer->lessontime = time();
 276          $DB->insert_record('lesson_timer', $lessontimer);
 277  
 278          // Trigger and capture the event.
 279          $sink = $this->redirectEvents();
 280          $this->lesson->stop_timer();
 281          $events = $sink->get_events();
 282          $event = reset($events);
 283  
 284          // Check that the event data is valid.
 285          $this->assertInstanceOf('\mod_lesson\event\lesson_ended', $event);
 286          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 287          $this->assertEventContextNotUsed($event);
 288      }
 289  
 290      /**
 291       * Test the essay assessed event.
 292       *
 293       * There is no external API for assessing an essay, so the unit test will simply
 294       * create and trigger the event and ensure the legacy log data is returned as expected.
 295       */
 296      public function test_essay_assessed() {
 297          // Create an essay assessed event
 298          $gradeid = 5;
 299          $attemptid = 7;
 300          $event = \mod_lesson\event\essay_assessed::create(array(
 301              'objectid' => $gradeid,
 302              'relateduserid' => 3,
 303              'context' => \context_module::instance($this->lesson->properties()->cmid),
 304              'courseid' => $this->course->id,
 305              'other' => array(
 306                  'lessonid' => $this->lesson->id,
 307                  'attemptid' => $attemptid
 308              )
 309          ));
 310  
 311          // Trigger and capture the event.
 312          $sink = $this->redirectEvents();
 313          $event->trigger();
 314          $events = $sink->get_events();
 315          $event = reset($events);
 316  
 317          // Check that the event data is valid.
 318          $this->assertInstanceOf('\mod_lesson\event\essay_assessed', $event);
 319          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 320          $this->assertEventContextNotUsed($event);
 321      }
 322  
 323      /**
 324       * Test the content page viewed event.
 325       *
 326       */
 327      public function test_content_page_viewed() {
 328          global $DB, $PAGE;
 329  
 330          // Set up a generator to create content.
 331          $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
 332          // Create a content page.
 333          $pagerecord = $generator->create_content($this->lesson);
 334          // Get the lesson page information.
 335          $page = $this->lesson->load_page($pagerecord->id);
 336          // Get the coursemodule record to setup the $PAGE->cm.
 337          $coursemodule = $DB->get_record('course_modules', array('id' => $this->lesson->properties()->cmid));
 338          // Set the $PAGE->cm.
 339          $PAGE->set_cm($coursemodule);
 340          // Get the appropriate renderer.
 341          $lessonoutput = $PAGE->get_renderer('mod_lesson');
 342  
 343          // Trigger and capture the event.
 344          $sink = $this->redirectEvents();
 345          // Fire the function that leads to the triggering of our event.
 346          $lessonoutput->display_page($this->lesson, $page, false);
 347          $events = $sink->get_events();
 348          $event = reset($events);
 349  
 350          // Check that the event data is valid.
 351          $this->assertInstanceOf('\mod_lesson\event\content_page_viewed', $event);
 352          $this->assertEquals($page->id, $event->objectid);
 353          $this->assertEventContextNotUsed($event);
 354          $this->assertDebuggingNotCalled();
 355      }
 356  
 357      /**
 358       * Test the question viewed event.
 359       *
 360       */
 361      public function test_question_viewed() {
 362          global $DB, $PAGE;
 363  
 364          // Set up a generator to create content.
 365          $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
 366          // Create a question page.
 367          $pagerecord = $generator->create_question_truefalse($this->lesson);
 368          // Get the lesson page information.
 369          $page = $this->lesson->load_page($pagerecord->id);
 370          // Get the coursemodule record to setup the $PAGE->cm.
 371          $coursemodule = $DB->get_record('course_modules', array('id' => $this->lesson->properties()->cmid));
 372          // Set the $PAGE->cm.
 373          $PAGE->set_cm($coursemodule);
 374          // Get the appropriate renderer.
 375          $lessonoutput = $PAGE->get_renderer('mod_lesson');
 376  
 377          // Trigger and capture the event.
 378          $sink = $this->redirectEvents();
 379          // Fire the function that leads to the triggering of our event.
 380          $lessonoutput->display_page($this->lesson, $page, false);
 381          $events = $sink->get_events();
 382          $event = reset($events);
 383  
 384          // Check that the event data is valid.
 385          $this->assertInstanceOf('\mod_lesson\event\question_viewed', $event);
 386          $this->assertEquals($page->id, $event->objectid);
 387          $this->assertEquals('True/false', $event->other['pagetype']);
 388          $this->assertEventContextNotUsed($event);
 389          $this->assertDebuggingNotCalled();
 390      }
 391  
 392      /**
 393       * Test the question answered event.
 394       *
 395       * There is no external API for answering an truefalse question, so the unit test will simply
 396       * create and trigger the event and ensure data is returned as expected.
 397       */
 398      public function test_question_answered() {
 399  
 400          // Trigger an event: truefalse question answered.
 401          $eventparams = array(
 402              'context' => \context_module::instance($this->lesson->properties()->cmid),
 403              'objectid' => 25,
 404              'other' => array(
 405                  'pagetype' => 'True/false'
 406                  )
 407          );
 408  
 409          $event = \mod_lesson\event\question_answered::create($eventparams);
 410  
 411          // Trigger and capture the event.
 412          $sink = $this->redirectEvents();
 413          $event->trigger();
 414          $events = $sink->get_events();
 415          $event = reset($events);
 416  
 417          // Check that the event data is valid.
 418          $this->assertInstanceOf('\mod_lesson\event\question_answered', $event);
 419          $this->assertEquals(25, $event->objectid);
 420          $this->assertEquals('True/false', $event->other['pagetype']);
 421          $this->assertEventContextNotUsed($event);
 422          $this->assertDebuggingNotCalled();
 423      }
 424  
 425      /**
 426       * Test the user override created event.
 427       *
 428       * There is no external API for creating a user override, so the unit test will simply
 429       * create and trigger the event and ensure the event data is returned as expected.
 430       */
 431      public function test_user_override_created() {
 432  
 433          $params = array(
 434              'objectid' => 1,
 435              'relateduserid' => 2,
 436              'context' => \context_module::instance($this->lesson->properties()->cmid),
 437              'other' => array(
 438                  'lessonid' => $this->lesson->id
 439              )
 440          );
 441          $event = \mod_lesson\event\user_override_created::create($params);
 442  
 443          // Trigger and capture the event.
 444          $sink = $this->redirectEvents();
 445          $event->trigger();
 446          $events = $sink->get_events();
 447          $event = reset($events);
 448  
 449          // Check that the event data is valid.
 450          $this->assertInstanceOf('\mod_lesson\event\user_override_created', $event);
 451          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 452          $this->assertEventContextNotUsed($event);
 453      }
 454  
 455      /**
 456       * Test the group override created event.
 457       *
 458       * There is no external API for creating a group override, so the unit test will simply
 459       * create and trigger the event and ensure the event data is returned as expected.
 460       */
 461      public function test_group_override_created() {
 462  
 463          $params = array(
 464              'objectid' => 1,
 465              'context' => \context_module::instance($this->lesson->properties()->cmid),
 466              'other' => array(
 467                  'lessonid' => $this->lesson->id,
 468                  'groupid' => 2
 469              )
 470          );
 471          $event = \mod_lesson\event\group_override_created::create($params);
 472  
 473          // Trigger and capture the event.
 474          $sink = $this->redirectEvents();
 475          $event->trigger();
 476          $events = $sink->get_events();
 477          $event = reset($events);
 478  
 479          // Check that the event data is valid.
 480          $this->assertInstanceOf('\mod_lesson\event\group_override_created', $event);
 481          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 482          $this->assertEventContextNotUsed($event);
 483      }
 484  
 485      /**
 486       * Test the user override updated event.
 487       *
 488       * There is no external API for updating a user override, so the unit test will simply
 489       * create and trigger the event and ensure the event data is returned as expected.
 490       */
 491      public function test_user_override_updated() {
 492  
 493          $params = array(
 494              'objectid' => 1,
 495              'relateduserid' => 2,
 496              'context' => \context_module::instance($this->lesson->properties()->cmid),
 497              'other' => array(
 498                  'lessonid' => $this->lesson->id
 499              )
 500          );
 501          $event = \mod_lesson\event\user_override_updated::create($params);
 502  
 503          // Trigger and capture the event.
 504          $sink = $this->redirectEvents();
 505          $event->trigger();
 506          $events = $sink->get_events();
 507          $event = reset($events);
 508  
 509          // Check that the event data is valid.
 510          $this->assertInstanceOf('\mod_lesson\event\user_override_updated', $event);
 511          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 512          $this->assertEventContextNotUsed($event);
 513      }
 514  
 515      /**
 516       * Test the group override updated event.
 517       *
 518       * There is no external API for updating a group override, so the unit test will simply
 519       * create and trigger the event and ensure the event data is returned as expected.
 520       */
 521      public function test_group_override_updated() {
 522  
 523          $params = array(
 524              'objectid' => 1,
 525              'context' => \context_module::instance($this->lesson->properties()->cmid),
 526              'other' => array(
 527                  'lessonid' => $this->lesson->id,
 528                  'groupid' => 2
 529              )
 530          );
 531          $event = \mod_lesson\event\group_override_updated::create($params);
 532  
 533          // Trigger and capture the event.
 534          $sink = $this->redirectEvents();
 535          $event->trigger();
 536          $events = $sink->get_events();
 537          $event = reset($events);
 538  
 539          // Check that the event data is valid.
 540          $this->assertInstanceOf('\mod_lesson\event\group_override_updated', $event);
 541          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 542          $this->assertEventContextNotUsed($event);
 543      }
 544  
 545      /**
 546       * Test the user override deleted event.
 547       */
 548      public function test_user_override_deleted() {
 549          global $DB;
 550  
 551          // Create an override.
 552          $override = new \stdClass();
 553          $override->lesson = $this->lesson->id;
 554          $override->userid = 2;
 555          $override->id = $DB->insert_record('lesson_overrides', $override);
 556  
 557          // Trigger and capture the event.
 558          $sink = $this->redirectEvents();
 559          $this->lesson->delete_override($override->id);
 560          $events = $sink->get_events();
 561          $event = reset($events);
 562  
 563          // Check that the event data is valid.
 564          $this->assertInstanceOf('\mod_lesson\event\user_override_deleted', $event);
 565          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 566          $this->assertEventContextNotUsed($event);
 567      }
 568  
 569      /**
 570       * Test the group override deleted event.
 571       */
 572      public function test_group_override_deleted() {
 573          global $DB;
 574  
 575          // Create an override.
 576          $override = new \stdClass();
 577          $override->lesson = $this->lesson->id;
 578          $override->groupid = 2;
 579          $override->id = $DB->insert_record('lesson_overrides', $override);
 580  
 581          // Trigger and capture the event.
 582          $sink = $this->redirectEvents();
 583          $this->lesson->delete_override($override->id);
 584          $events = $sink->get_events();
 585          $event = reset($events);
 586  
 587          // Check that the event data is valid.
 588          $this->assertInstanceOf('\mod_lesson\event\group_override_deleted', $event);
 589          $this->assertEquals(\context_module::instance($this->lesson->properties()->cmid), $event->get_context());
 590          $this->assertEventContextNotUsed($event);
 591      }
 592  }