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    mod_choice
  21   * @copyright  2013 Adrian Greeve <adrian@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace mod_choice\event;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  global $CFG;
  30  require_once($CFG->dirroot . '/mod/choice/lib.php');
  31  
  32  /**
  33   * Events tests class.
  34   *
  35   * @package    mod_choice
  36   * @copyright  2013 Adrian Greeve <adrian@moodle.com>
  37   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   */
  39  class events_test extends \advanced_testcase {
  40      /** @var choice_object */
  41      protected $choice;
  42  
  43      /** @var course_object */
  44      protected $course;
  45  
  46      /** @var cm_object Course module object. */
  47      protected $cm;
  48  
  49      /** @var context_object */
  50      protected $context;
  51  
  52      /**
  53       * Setup often used objects for the following tests.
  54       */
  55      protected function setUp(): void {
  56          global $DB;
  57  
  58          $this->resetAfterTest();
  59  
  60          $this->course = $this->getDataGenerator()->create_course();
  61          $this->choice = $this->getDataGenerator()->create_module('choice', array('course' => $this->course->id));
  62          $this->cm = $DB->get_record('course_modules', array('id' => $this->choice->cmid));
  63          $this->context = \context_module::instance($this->choice->cmid);
  64      }
  65  
  66      /**
  67       * Test to ensure that event data is being stored correctly.
  68       */
  69      public function test_answer_created() {
  70          global $DB;
  71          // Generate user data.
  72          $user = $this->getDataGenerator()->create_user();
  73          $this->setUser($user);
  74  
  75          $optionids = array_keys($DB->get_records('choice_options', array('choiceid' => $this->choice->id)));
  76          // Redirect event.
  77          $sink = $this->redirectEvents();
  78          choice_user_submit_response($optionids[3], $this->choice, $user->id, $this->course, $this->cm);
  79          $events = $sink->get_events();
  80          $answer = $DB->get_record('choice_answers', ['userid' => $user->id, 'choiceid' => $this->choice->id]);
  81  
  82          // Data checking.
  83          $this->assertCount(1, $events);
  84          $this->assertInstanceOf('\mod_choice\event\answer_created', $events[0]);
  85          $this->assertEquals($user->id, $events[0]->userid);
  86          $this->assertEquals($user->id, $events[0]->relateduserid);
  87          $this->assertEquals(\context_module::instance($this->choice->cmid), $events[0]->get_context());
  88          $this->assertEquals($answer->id, $events[0]->objectid);
  89          $this->assertEquals($this->choice->id, $events[0]->other['choiceid']);
  90          $this->assertEquals($optionids[3], $events[0]->other['optionid']);
  91          $this->assertEventContextNotUsed($events[0]);
  92          $sink->close();
  93      }
  94  
  95      /**
  96       * Test to ensure that event data is being stored correctly.
  97       */
  98      public function test_answer_submitted_by_another_user() {
  99          global $DB, $USER;
 100          // Generate user data.
 101          $user = $this->getDataGenerator()->create_user();
 102  
 103          $optionids = array_keys($DB->get_records('choice_options', array('choiceid' => $this->choice->id)));
 104          // Redirect event.
 105          $sink = $this->redirectEvents();
 106          choice_user_submit_response($optionids[3], $this->choice, $user->id, $this->course, $this->cm);
 107          $events = $sink->get_events();
 108          $answer = $DB->get_record('choice_answers', ['userid' => $user->id, 'choiceid' => $this->choice->id]);
 109  
 110          // Data checking.
 111          $this->assertCount(1, $events);
 112          $this->assertInstanceOf('\mod_choice\event\answer_created', $events[0]);
 113          $this->assertEquals($USER->id, $events[0]->userid);
 114          $this->assertEquals($user->id, $events[0]->relateduserid);
 115          $this->assertEquals(\context_module::instance($this->choice->cmid), $events[0]->get_context());
 116          $this->assertEquals($answer->id, $events[0]->objectid);
 117          $this->assertEquals($this->choice->id, $events[0]->other['choiceid']);
 118          $this->assertEquals($optionids[3], $events[0]->other['optionid']);
 119          $this->assertEventContextNotUsed($events[0]);
 120          $sink->close();
 121      }
 122  
 123      /**
 124       * Test to ensure that multiple choice data is being stored correctly.
 125       */
 126      public function test_answer_created_multiple() {
 127          global $DB;
 128  
 129          // Generate user data.
 130          $user = $this->getDataGenerator()->create_user();
 131          $this->setUser($user);
 132  
 133          // Create multiple choice.
 134          $choice = $this->getDataGenerator()->create_module('choice', array('course' => $this->course->id,
 135              'allowmultiple' => 1));
 136          $cm = $DB->get_record('course_modules', array('id' => $choice->cmid));
 137          $context = \context_module::instance($choice->cmid);
 138  
 139          $optionids = array_keys($DB->get_records('choice_options', array('choiceid' => $choice->id)));
 140          $submittedoptionids = array($optionids[1], $optionids[3]);
 141  
 142          // Redirect event.
 143          $sink = $this->redirectEvents();
 144          choice_user_submit_response($submittedoptionids, $choice, $user->id, $this->course, $cm);
 145          $events = $sink->get_events();
 146          $answers = $DB->get_records('choice_answers', ['userid' => $user->id, 'choiceid' => $choice->id], 'id');
 147          $answers = array_values($answers);
 148  
 149          // Data checking.
 150          $this->assertCount(2, $events);
 151          $this->assertInstanceOf('\mod_choice\event\answer_created', $events[0]);
 152          $this->assertEquals($user->id, $events[0]->userid);
 153          $this->assertEquals($user->id, $events[0]->relateduserid);
 154          $this->assertEquals(\context_module::instance($choice->cmid), $events[0]->get_context());
 155          $this->assertEquals($answers[0]->id, $events[0]->objectid);
 156          $this->assertEquals($choice->id, $events[0]->other['choiceid']);
 157          $this->assertEquals($optionids[1], $events[0]->other['optionid']);
 158          $this->assertEventContextNotUsed($events[0]);
 159  
 160          $this->assertInstanceOf('\mod_choice\event\answer_created', $events[1]);
 161          $this->assertEquals($user->id, $events[1]->userid);
 162          $this->assertEquals($user->id, $events[1]->relateduserid);
 163          $this->assertEquals(\context_module::instance($choice->cmid), $events[1]->get_context());
 164          $this->assertEquals($answers[1]->id, $events[1]->objectid);
 165          $this->assertEquals($choice->id, $events[1]->other['choiceid']);
 166          $this->assertEquals($optionids[3], $events[1]->other['optionid']);
 167          $this->assertEventContextNotUsed($events[1]);
 168          $sink->close();
 169      }
 170  
 171      /**
 172       * Test custom validations.
 173       */
 174      public function test_answer_created_other_exception() {
 175          // Generate user data.
 176          $user = $this->getDataGenerator()->create_user();
 177  
 178          $eventdata = array();
 179          $eventdata['context'] = $this->context;
 180          $eventdata['objectid'] = 2;
 181          $eventdata['userid'] = $user->id;
 182          $eventdata['courseid'] = $this->course->id;
 183          $eventdata['other'] = array();
 184  
 185          // Make sure content identifier is always set.
 186          $this->expectException(\coding_exception::class);
 187          $event = \mod_choice\event\answer_created::create($eventdata);
 188          $event->trigger();
 189          $this->assertEventContextNotUsed($event);
 190      }
 191  
 192      /**
 193       * Test to ensure that event data is being stored correctly.
 194       */
 195      public function test_answer_updated() {
 196          global $DB;
 197          // Generate user data.
 198          $user = $this->getDataGenerator()->create_user();
 199          $this->setUser($user);
 200  
 201          $optionids = array_keys($DB->get_records('choice_options', array('choiceid' => $this->choice->id)));
 202  
 203          // Create the first answer.
 204          choice_user_submit_response($optionids[2], $this->choice, $user->id, $this->course, $this->cm);
 205          $oldanswer = $DB->get_record('choice_answers', ['userid' => $user->id, 'choiceid' => $this->choice->id]);
 206  
 207          // Redirect event.
 208          $sink = $this->redirectEvents();
 209          // Now choose a different answer.
 210          choice_user_submit_response($optionids[3], $this->choice, $user->id, $this->course, $this->cm);
 211          $newanswer = $DB->get_record('choice_answers', ['userid' => $user->id, 'choiceid' => $this->choice->id]);
 212  
 213          $events = $sink->get_events();
 214  
 215          // Data checking.
 216          $this->assertCount(2, $events);
 217          $this->assertInstanceOf('\mod_choice\event\answer_deleted', $events[0]);
 218          $this->assertEquals($user->id, $events[0]->userid);
 219          $this->assertEquals(\context_module::instance($this->choice->cmid), $events[0]->get_context());
 220          $this->assertEquals($oldanswer->id, $events[0]->objectid);
 221          $this->assertEquals($this->choice->id, $events[0]->other['choiceid']);
 222          $this->assertEquals($optionids[2], $events[0]->other['optionid']);
 223          $this->assertEventContextNotUsed($events[0]);
 224  
 225          $this->assertInstanceOf('\mod_choice\event\answer_created', $events[1]);
 226          $this->assertEquals($user->id, $events[1]->userid);
 227          $this->assertEquals(\context_module::instance($this->choice->cmid), $events[1]->get_context());
 228          $this->assertEquals($newanswer->id, $events[1]->objectid);
 229          $this->assertEquals($this->choice->id, $events[1]->other['choiceid']);
 230          $this->assertEquals($optionids[3], $events[1]->other['optionid']);
 231          $this->assertEventContextNotUsed($events[1]);
 232  
 233          $sink->close();
 234      }
 235  
 236      /**
 237       * Test to ensure that event data is being stored correctly.
 238       */
 239      public function test_answer_deleted() {
 240          global $DB, $USER;
 241          // Generate user data.
 242          $user = $this->getDataGenerator()->create_user();
 243  
 244          $optionids = array_keys($DB->get_records('choice_options', array('choiceid' => $this->choice->id)));
 245  
 246          // Create the first answer.
 247          choice_user_submit_response($optionids[2], $this->choice, $user->id, $this->course, $this->cm);
 248          // Get the users response.
 249          $answer = $DB->get_record('choice_answers', array('userid' => $user->id, 'choiceid' => $this->choice->id),
 250              '*', $strictness = IGNORE_MULTIPLE);
 251  
 252          // Redirect event.
 253          $sink = $this->redirectEvents();
 254          // Now delete the answer.
 255          choice_delete_responses(array($answer->id), $this->choice, $this->cm, $this->course);
 256  
 257          // Get our event event.
 258          $events = $sink->get_events();
 259          $event = reset($events);
 260  
 261          // Data checking.
 262          $this->assertInstanceOf('\mod_choice\event\answer_deleted', $event);
 263          $this->assertEquals($USER->id, $event->userid);
 264          $this->assertEquals($user->id, $event->relateduserid);
 265          $this->assertEquals(\context_module::instance($this->choice->cmid), $event->get_context());
 266          $this->assertEquals($this->choice->id, $event->other['choiceid']);
 267          $this->assertEquals($answer->optionid, $event->other['optionid']);
 268          $this->assertEventContextNotUsed($event);
 269          $sink->close();
 270      }
 271  
 272      /**
 273       * Test to ensure that event data is being stored correctly.
 274       */
 275      public function test_report_viewed() {
 276          global $USER;
 277  
 278          $this->resetAfterTest();
 279  
 280          // Generate user data.
 281          $this->setAdminUser();
 282  
 283          $eventdata = array();
 284          $eventdata['objectid'] = $this->choice->id;
 285          $eventdata['context'] = $this->context;
 286          $eventdata['courseid'] = $this->course->id;
 287          $eventdata['other']['content'] = 'choicereportcontentviewed';
 288  
 289          // This is fired in a page view so we can't run this through a function.
 290          $event = \mod_choice\event\report_viewed::create($eventdata);
 291  
 292          // Redirect event.
 293          $sink = $this->redirectEvents();
 294          $event->trigger();
 295          $event = $sink->get_events();
 296  
 297          // Data checking.
 298          $this->assertCount(1, $event);
 299          $this->assertInstanceOf('\mod_choice\event\report_viewed', $event[0]);
 300          $this->assertEquals($USER->id, $event[0]->userid);
 301          $this->assertEquals(\context_module::instance($this->choice->cmid), $event[0]->get_context());
 302          $expected = array($this->course->id, "choice", "report", 'report.php?id=' . $this->context->instanceid,
 303              $this->choice->id, $this->context->instanceid);
 304          $this->assertEventLegacyLogData($expected, $event[0]);
 305          $this->assertEventContextNotUsed($event[0]);
 306          $sink->close();
 307      }
 308  
 309      /**
 310       * Test to ensure that event data is being stored correctly.
 311       */
 312      public function test_report_downloaded() {
 313          global $USER;
 314  
 315          $this->resetAfterTest();
 316  
 317          // Generate user data.
 318          $this->setAdminUser();
 319  
 320          $eventdata = array();
 321          $eventdata['context'] = $this->context;
 322          $eventdata['courseid'] = $this->course->id;
 323          $eventdata['other']['content'] = 'choicereportcontentviewed';
 324          $eventdata['other']['format'] = 'csv';
 325          $eventdata['other']['choiceid'] = $this->choice->id;
 326  
 327          // This is fired in a page view so we can't run this through a function.
 328          $event = \mod_choice\event\report_downloaded::create($eventdata);
 329  
 330          // Redirect event.
 331          $sink = $this->redirectEvents();
 332          $event->trigger();
 333          $event = $sink->get_events();
 334  
 335          // Data checking.
 336          $this->assertCount(1, $event);
 337          $this->assertInstanceOf('\mod_choice\event\report_downloaded', $event[0]);
 338          $this->assertEquals($USER->id, $event[0]->userid);
 339          $this->assertEquals(\context_module::instance($this->choice->cmid), $event[0]->get_context());
 340          $this->assertEquals('csv', $event[0]->other['format']);
 341          $this->assertEquals($this->choice->id, $event[0]->other['choiceid']);
 342          $this->assertEventContextNotUsed($event[0]);
 343          $sink->close();
 344      }
 345  
 346      /**
 347       * Test to ensure that event data is being stored correctly.
 348       */
 349      public function test_course_module_viewed() {
 350          global $USER;
 351  
 352          // Generate user data.
 353          $this->setAdminUser();
 354  
 355          $eventdata = array();
 356          $eventdata['objectid'] = $this->choice->id;
 357          $eventdata['context'] = $this->context;
 358          $eventdata['courseid'] = $this->course->id;
 359          $eventdata['other']['content'] = 'pageresourceview';
 360  
 361          // This is fired in a page view so we can't run this through a function.
 362          $event = \mod_choice\event\course_module_viewed::create($eventdata);
 363  
 364          // Redirect event.
 365          $sink = $this->redirectEvents();
 366          $event->trigger();
 367          $event = $sink->get_events();
 368  
 369          // Data checking.
 370          $this->assertCount(1, $event);
 371          $this->assertInstanceOf('\mod_choice\event\course_module_viewed', $event[0]);
 372          $this->assertEquals($USER->id, $event[0]->userid);
 373          $this->assertEquals(\context_module::instance($this->choice->cmid), $event[0]->get_context());
 374          $expected = array($this->course->id, "choice", "view", 'view.php?id=' . $this->context->instanceid,
 375              $this->choice->id, $this->context->instanceid);
 376          $this->assertEventLegacyLogData($expected, $event[0]);
 377          $this->assertEventContextNotUsed($event[0]);
 378          $sink->close();
 379      }
 380  
 381      /**
 382       * Test to ensure that event data is being stored correctly.
 383       */
 384      public function test_course_module_instance_list_viewed_viewed() {
 385          global $USER;
 386  
 387          // Not much can be tested here as the event is only triggered on a page load,
 388          // let's just check that the event contains the expected basic information.
 389          $this->setAdminUser();
 390  
 391          $params = array('context' => \context_course::instance($this->course->id));
 392          $event = \mod_choice\event\course_module_instance_list_viewed::create($params);
 393          $sink = $this->redirectEvents();
 394          $event->trigger();
 395          $events = $sink->get_events();
 396          $event = reset($events);
 397          $this->assertInstanceOf('\mod_choice\event\course_module_instance_list_viewed', $event);
 398          $this->assertEquals($USER->id, $event->userid);
 399          $this->assertEquals(\context_course::instance($this->course->id), $event->get_context());
 400          $expected = array($this->course->id, 'choice', 'view all', 'index.php?id=' . $this->course->id, '');
 401          $this->assertEventLegacyLogData($expected, $event);
 402          $this->assertEventContextNotUsed($event);
 403      }
 404  }