Search moodle.org's
Developer Documentation

See Release Notes

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