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 core_message
  21   * @category test
  22   * @copyright 2014 Mark Nelson <markn@moodle.com>
  23   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace core_message\event;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  global $CFG;
  31  
  32  require_once($CFG->dirroot . '/message/tests/messagelib_test.php');
  33  
  34  /**
  35   * Class containing the tests for message related events.
  36   *
  37   * @package core_message
  38   * @category test
  39   * @copyright 2014 Mark Nelson <markn@moodle.com>
  40   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class events_test extends \core_message\messagelib_test {
  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  
  53      /**
  54       * Test the message contact added event.
  55       */
  56      public function test_message_contact_added() {
  57          global $USER;
  58  
  59          // Set this user as the admin.
  60          $this->setAdminUser();
  61  
  62          // Create a user to add to the admin's contact list.
  63          $user = $this->getDataGenerator()->create_user();
  64  
  65          // Trigger and capture the event when adding a contact.
  66          $sink = $this->redirectEvents();
  67          \core_message\api::add_contact($USER->id, $user->id);
  68          $events = $sink->get_events();
  69          $event = reset($events);
  70  
  71          // Check that the event data is valid.
  72          $this->assertInstanceOf('\core\event\message_contact_added', $event);
  73          $this->assertEquals(\context_user::instance(2), $event->get_context());
  74          $url = new \moodle_url('/message/index.php', array('user1' => $event->userid, 'user2' => $event->relateduserid));
  75          $this->assertEquals($url, $event->get_url());
  76      }
  77  
  78      /**
  79       * Test the message contact removed event.
  80       */
  81      public function test_message_contact_removed() {
  82          global $USER;
  83  
  84          // Set this user as the admin.
  85          $this->setAdminUser();
  86  
  87          // Create a user to add to the admin's contact list.
  88          $user = $this->getDataGenerator()->create_user();
  89  
  90          // Add the user to the admin's contact list.
  91          \core_message\api::add_contact($USER->id, $user->id);
  92  
  93          // Trigger and capture the event when adding a contact.
  94          $sink = $this->redirectEvents();
  95          \core_message\api::remove_contact($USER->id, $user->id);
  96          $events = $sink->get_events();
  97          $event = reset($events);
  98  
  99          // Check that the event data is valid.
 100          $this->assertInstanceOf('\core\event\message_contact_removed', $event);
 101          $this->assertEquals(\context_user::instance(2), $event->get_context());
 102          $url = new \moodle_url('/message/index.php', array('user1' => $event->userid, 'user2' => $event->relateduserid));
 103          $this->assertEquals($url, $event->get_url());
 104      }
 105  
 106      /**
 107       * Test the message user blocked event.
 108       */
 109      public function test_message_user_blocked() {
 110          global $USER;
 111  
 112          // Set this user as the admin.
 113          $this->setAdminUser();
 114  
 115          // Create a user to add to the admin's contact list.
 116          $user = $this->getDataGenerator()->create_user();
 117  
 118          // Add the user to the admin's contact list.
 119          \core_message\api::add_contact($USER->id, $user->id);
 120  
 121          // Trigger and capture the event when blocking a contact.
 122          $sink = $this->redirectEvents();
 123          \core_message\api::block_user($USER->id, $user->id);
 124          $events = $sink->get_events();
 125          $event = reset($events);
 126  
 127          // Check that the event data is valid.
 128          $this->assertInstanceOf('\core\event\message_user_blocked', $event);
 129          $this->assertEquals(\context_user::instance(2), $event->get_context());
 130      }
 131  
 132      /**
 133       * Test the message user unblocked event.
 134       */
 135      public function test_message_user_unblocked() {
 136          global $USER;
 137  
 138          // Set this user as the admin.
 139          $this->setAdminUser();
 140  
 141          // Create a user to add to the admin's contact list.
 142          $user = $this->getDataGenerator()->create_user();
 143  
 144          // Add the user to the admin's contact list.
 145          \core_message\api::add_contact($USER->id, $user->id);
 146  
 147          // Block the user.
 148          \core_message\api::block_user($USER->id, $user->id);
 149          // Make sure that we have 1 blocked user.
 150          $this->assertEquals(1, \core_message\api::count_blocked_users());
 151  
 152          // Trigger and capture the event when unblocking a contact.
 153          $sink = $this->redirectEvents();
 154          \core_message\api::unblock_user($USER->id, $user->id);
 155          $events = $sink->get_events();
 156          $event = reset($events);
 157  
 158          // Check that the event data is valid.
 159          $this->assertInstanceOf('\core\event\message_user_unblocked', $event);
 160          $this->assertEquals(\context_user::instance(2), $event->get_context());
 161  
 162          // Make sure that we have no blocked users.
 163          $this->assertEmpty(\core_message\api::count_blocked_users());
 164      }
 165  
 166      /**
 167       * Test the message sent event.
 168       *
 169       * We can not use the message_send() function in the unit test to check that the event was fired as there is a
 170       * conditional check to ensure a fake message is sent during unit tests when calling that particular function.
 171       */
 172      public function test_message_sent() {
 173          $event = \core\event\message_sent::create(array(
 174              'objectid' => 3,
 175              'userid' => 1,
 176              'context'  => \context_system::instance(),
 177              'relateduserid' => 2,
 178              'other' => array(
 179                  'courseid' => 4
 180              )
 181          ));
 182  
 183          // Trigger and capturing the event.
 184          $sink = $this->redirectEvents();
 185          $event->trigger();
 186          $events = $sink->get_events();
 187          $event = reset($events);
 188  
 189          // Check that the event data is valid.
 190          $this->assertInstanceOf('\core\event\message_sent', $event);
 191          $this->assertEquals(\context_system::instance(), $event->get_context());
 192          $url = new \moodle_url('/message/index.php', array('user1' => $event->userid, 'user2' => $event->relateduserid));
 193          $this->assertEquals($url, $event->get_url());
 194          $this->assertEquals(3, $event->objectid);
 195          $this->assertEquals(4, $event->other['courseid']);
 196      }
 197  
 198      public function test_mesage_sent_without_other_courseid() {
 199  
 200          // Creating a message_sent event without other[courseid] leads to exception.
 201          $this->expectException('coding_exception');
 202          $this->expectExceptionMessage('The \'courseid\' value must be set in other');
 203  
 204          $event = \core\event\message_sent::create(array(
 205              'userid' => 1,
 206              'context'  => \context_system::instance(),
 207              'relateduserid' => 2,
 208              'other' => array(
 209                  'messageid' => 3,
 210              )
 211          ));
 212      }
 213  
 214      public function test_mesage_sent_via_create_from_ids() {
 215          // Containing courseid.
 216          $event = \core\event\message_sent::create_from_ids(1, 2, 3, 4);
 217  
 218          // Trigger and capturing the event.
 219          $sink = $this->redirectEvents();
 220          $event->trigger();
 221          $events = $sink->get_events();
 222          $event = reset($events);
 223  
 224          // Check that the event data is valid.
 225          $this->assertInstanceOf('\core\event\message_sent', $event);
 226          $this->assertEquals(\context_system::instance(), $event->get_context());
 227          $url = new \moodle_url('/message/index.php', array('user1' => $event->userid, 'user2' => $event->relateduserid));
 228          $this->assertEquals($url, $event->get_url());
 229          $this->assertEquals(3, $event->objectid);
 230          $this->assertEquals(4, $event->other['courseid']);
 231      }
 232  
 233      /**
 234       * Test the group message sent event.
 235       *
 236       * We can't test events in any testing of the message_send() function as there is a conditional PHPUNIT check in message_send,
 237       * resulting in fake messages being generated and captured under test. As a result, none of the events code, nor message
 238       * processor code is called during testing.
 239       */
 240      public function test_group_message_sent() {
 241          $event = \core\event\group_message_sent::create([
 242              'objectid' => 3,
 243              'userid' => 1,
 244              'context'  => \context_system::instance(),
 245              'other' => [
 246                  'courseid' => 4,
 247                  'conversationid' => 54
 248              ]
 249          ]);
 250  
 251          // Trigger and capture the event.
 252          $sink = $this->redirectEvents();
 253          $event->trigger();
 254          $events = $sink->get_events();
 255          $event = reset($events);
 256  
 257          // Check that the event data is valid.
 258          $this->assertInstanceOf('\core\event\group_message_sent', $event);
 259          $this->assertEquals(\context_system::instance(), $event->get_context());
 260          $url = new \moodle_url('/message/index.php');
 261          $this->assertEquals($url, $event->get_url());
 262          $this->assertEquals(3, $event->objectid);
 263          $this->assertEquals(4, $event->other['courseid']);
 264          $this->assertEquals(54, $event->other['conversationid']);
 265      }
 266  
 267      /**
 268       * Test the group message sent event when created without a courseid.
 269       */
 270      public function test_group_message_sent_without_other_courseid() {
 271          // Creating a message_sent event without other[courseid] leads to exception.
 272          $this->expectException('coding_exception');
 273          $this->expectExceptionMessage('The \'courseid\' value must be set in other');
 274  
 275          $event = \core\event\group_message_sent::create([
 276              'userid' => 1,
 277              'objectid' => 3,
 278              'context'  => \context_system::instance(),
 279              'relateduserid' => 2,
 280              'other' => [
 281                  'conversationid' => 34
 282              ]
 283          ]);
 284      }
 285  
 286      /**
 287       * Test the group message sent event when created without a conversationid.
 288       */
 289      public function test_group_message_sent_without_other_conversationid() {
 290          // Creating a message_sent event without other[courseid] leads to exception.
 291          $this->expectException('coding_exception');
 292          $this->expectExceptionMessage('The \'conversationid\' value must be set in other');
 293  
 294          $event = \core\event\group_message_sent::create([
 295              'userid' => 1,
 296              'objectid' => 3,
 297              'context'  => \context_system::instance(),
 298              'relateduserid' => 2,
 299              'other' => [
 300                  'courseid' => 44,
 301              ]
 302          ]);
 303      }
 304  
 305      /**
 306       * Test the group message sent event using the create_from_ids() method.
 307       */
 308      public function test_group_message_sent_via_create_from_ids() {
 309          // Fields are: userfromid, conversationid, messageid, courseid.
 310          $event = \core\event\group_message_sent::create_from_ids(1, 2, 3, 4);
 311  
 312          // Trigger and capture the event.
 313          $sink = $this->redirectEvents();
 314          $event->trigger();
 315          $events = $sink->get_events();
 316          $event = reset($events);
 317  
 318          // Check that the event data is valid.
 319          $this->assertInstanceOf('\core\event\group_message_sent', $event);
 320          $this->assertEquals(\context_system::instance(), $event->get_context());
 321          $this->assertEquals(new \moodle_url('/message/index.php'), $event->get_url());
 322          $this->assertEquals(1, $event->userid);
 323          $this->assertEquals(2, $event->other['conversationid']);
 324          $this->assertEquals(3, $event->objectid);
 325          $this->assertEquals(4, $event->other['courseid']);
 326      }
 327  
 328      /**
 329       * Test the message viewed event.
 330       */
 331      public function test_message_viewed() {
 332          global $DB;
 333  
 334          // Create users to send messages between.
 335          $user1 = $this->getDataGenerator()->create_user();
 336          $user2 = $this->getDataGenerator()->create_user();
 337  
 338          $messageid = $this->send_fake_message($user1, $user2);
 339  
 340          // Trigger and capture the event.
 341          $sink = $this->redirectEvents();
 342          $message = $DB->get_record('messages', ['id' => $messageid]);
 343          \core_message\api::mark_message_as_read($user1->id, $message);
 344          $events = $sink->get_events();
 345          $event = reset($events);
 346  
 347          // Get the usage action.
 348          $mua = $DB->get_record('message_user_actions', ['userid' => $user1->id, 'messageid' => $messageid,
 349              'action' => \core_message\api::MESSAGE_ACTION_READ]);
 350  
 351          // Check that the event data is valid.
 352          $this->assertInstanceOf('\core\event\message_viewed', $event);
 353          $this->assertEquals(\context_user::instance($user1->id), $event->get_context());
 354          $this->assertEquals($mua->id, $event->objectid);
 355          $this->assertEquals($messageid, $event->other['messageid']);
 356          $url = new \moodle_url('/message/index.php', array('user1' => $event->userid, 'user2' => $event->relateduserid));
 357          $this->assertEquals($url, $event->get_url());
 358      }
 359  
 360      /**
 361       * Test the message deleted event.
 362       */
 363      public function test_message_deleted() {
 364          global $DB, $USER;
 365  
 366          $this->setAdminUser();
 367  
 368          // Create users to send messages between.
 369          $user1 = $this->getDataGenerator()->create_user();
 370          $user2 = $this->getDataGenerator()->create_user();
 371  
 372          $messageid = $this->send_fake_message($user1, $user2);
 373  
 374          // Trigger and capture the event.
 375          $sink = $this->redirectEvents();
 376          \core_message\api::delete_message($user1->id, $messageid);
 377          $events = $sink->get_events();
 378          $event = reset($events);
 379  
 380          // Get the usage action.
 381          $mua = $DB->get_record('message_user_actions', ['userid' => $user1->id, 'messageid' => $messageid,
 382              'action' => \core_message\api::MESSAGE_ACTION_DELETED]);
 383  
 384          // Check that the event data is valid.
 385          $this->assertInstanceOf('\core\event\message_deleted', $event);
 386          $this->assertEquals($USER->id, $event->userid); // The user who deleted it.
 387          $this->assertEquals($user1->id, $event->relateduserid);
 388          $this->assertEquals($mua->id, $event->objectid);
 389          $this->assertEquals($messageid, $event->other['messageid']);
 390  
 391          $this->setUser($user1);
 392  
 393          // Create a read message.
 394          $messageid = $this->send_fake_message($user1, $user2);
 395          $m = $DB->get_record('messages', ['id' => $messageid]);
 396          \core_message\api::mark_message_as_read($user2->id, $m);
 397  
 398          // Trigger and capture the event.
 399          $sink = $this->redirectEvents();
 400          \core_message\api::delete_message($user2->id, $messageid);
 401          $events = $sink->get_events();
 402          $event = reset($events);
 403  
 404          // Get the usage action.
 405          $mua = $DB->get_record('message_user_actions', ['userid' => $user2->id, 'messageid' => $messageid,
 406              'action' => \core_message\api::MESSAGE_ACTION_DELETED]);
 407  
 408          // Check that the event data is valid.
 409          $this->assertInstanceOf('\core\event\message_deleted', $event);
 410          $this->assertEquals($user1->id, $event->userid);
 411          $this->assertEquals($user2->id, $event->relateduserid);
 412          $this->assertEquals($mua->id, $event->objectid);
 413          $this->assertEquals($messageid, $event->other['messageid']);
 414      }
 415  
 416      /**
 417       * Test the message deleted event is fired when deleting a conversation.
 418       */
 419      public function test_message_deleted_whole_conversation() {
 420          global $DB;
 421  
 422          // Create some users.
 423          $user1 = self::getDataGenerator()->create_user();
 424          $user2 = self::getDataGenerator()->create_user();
 425  
 426          // The person doing the deletion.
 427          $this->setUser($user1);
 428  
 429          // Send some messages back and forth.
 430          $time = 1;
 431          $messages = [];
 432          $messages[] = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
 433          $messages[] = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
 434          $messages[] = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
 435          $messages[] = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
 436          $messages[] = $this->send_fake_message($user1, $user2, 'You doing much?', 0, $time + 5);
 437          $messages[] = $this->send_fake_message($user2, $user1, 'Nah', 0, $time + 6);
 438          $messages[] = $this->send_fake_message($user1, $user2, 'You nubz0r!', 0, $time + 7);
 439          $messages[] = $this->send_fake_message($user2, $user1, 'Ouch.', 0, $time + 8);
 440  
 441          // Mark the last 4 messages as read.
 442          $m5 = $DB->get_record('messages', ['id' => $messages[4]]);
 443          $m6 = $DB->get_record('messages', ['id' => $messages[5]]);
 444          $m7 = $DB->get_record('messages', ['id' => $messages[6]]);
 445          $m8 = $DB->get_record('messages', ['id' => $messages[7]]);
 446          \core_message\api::mark_message_as_read($user2->id, $m5);
 447          \core_message\api::mark_message_as_read($user1->id, $m6);
 448          \core_message\api::mark_message_as_read($user2->id, $m7);
 449          \core_message\api::mark_message_as_read($user1->id, $m8);
 450  
 451          // Trigger and capture the event.
 452          $sink = $this->redirectEvents();
 453          $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
 454          \core_message\api::delete_conversation_by_id($user1->id, $conversationid);
 455          $events = $sink->get_events();
 456  
 457          // Get the user actions for the messages deleted by that user.
 458          $muas = $DB->get_records('message_user_actions', ['userid' => $user1->id,
 459              'action' => \core_message\api::MESSAGE_ACTION_DELETED], 'timecreated ASC');
 460          $this->assertCount(8, $muas);
 461  
 462          // Create a list we can use for testing.
 463          $muatest = [];
 464          foreach ($muas as $mua) {
 465              $muatest[$mua->messageid] = $mua;
 466          }
 467  
 468          // Check that there were the correct number of events triggered.
 469          $this->assertEquals(8, count($events));
 470  
 471          // Check that the event data is valid.
 472          $i = 1;
 473          foreach ($events as $event) {
 474              $messageid = $messages[$i - 1];
 475  
 476              $this->assertInstanceOf('\core\event\message_deleted', $event);
 477  
 478              $this->assertEquals($muatest[$messageid]->id, $event->objectid);
 479              $this->assertEquals($user1->id, $event->userid);
 480              $this->assertEquals($user1->id, $event->relateduserid);
 481              $this->assertEquals($messageid, $event->other['messageid']);
 482  
 483              $i++;
 484          }
 485      }
 486  
 487      /**
 488       * Test the notification sent event.
 489       */
 490      public function test_notification_sent() {
 491          // Create a course.
 492          $course = $this->getDataGenerator()->create_course();
 493  
 494          // Create users to send notification between.
 495          $user1 = $this->getDataGenerator()->create_user();
 496          $user2 = $this->getDataGenerator()->create_user();
 497  
 498          // Send a notification.
 499          $notificationid = $this->send_fake_message($user1, $user2, 'Hello world!', 1);
 500  
 501          // Containing courseid.
 502          $event = \core\event\notification_sent::create_from_ids($user1->id, $user2->id, $notificationid, $course->id);
 503  
 504          // Trigger and capturing the event.
 505          $sink = $this->redirectEvents();
 506          $event->trigger();
 507          $events = $sink->get_events();
 508          $event = reset($events);
 509  
 510          // Check that the event data is valid.
 511          $this->assertInstanceOf('\core\event\notification_sent', $event);
 512          $this->assertEquals($notificationid, $event->objectid);
 513          $this->assertEquals($user1->id, $event->userid);
 514          $this->assertEquals($user2->id, $event->relateduserid);
 515          $this->assertEquals(\context_system::instance(), $event->get_context());
 516          $this->assertEquals($course->id, $event->other['courseid']);
 517          $url = new \moodle_url('/message/output/popup/notifications.php', array('notificationid' => $event->objectid));
 518          $this->assertEquals($url, $event->get_url());
 519      }
 520  
 521      /**
 522       * Test the notification sent event when null passed as course.
 523       */
 524      public function test_notification_sent_with_null_course() {
 525          $event = \core\event\notification_sent::create_from_ids(1, 1, 1, null);
 526  
 527          // Trigger and capture the event.
 528          $sink = $this->redirectEvents();
 529          $event->trigger();
 530          $events = $sink->get_events();
 531          $event = reset($events);
 532  
 533          // Check that the event data is valid.
 534          $this->assertInstanceOf('\core\event\notification_sent', $event);
 535          $this->assertEquals(SITEID, $event->other['courseid']);
 536      }
 537  
 538      /**
 539       * Test the notification viewed event.
 540       */
 541      public function test_notification_viewed() {
 542          global $DB;
 543  
 544          // Create users to send notifications between.
 545          $user1 = $this->getDataGenerator()->create_user();
 546          $user2 = $this->getDataGenerator()->create_user();
 547  
 548          // Send a notification.
 549          $notificationid = $this->send_fake_message($user1, $user2, 'Hello world!', 1);
 550  
 551          // Trigger and capture the event.
 552          $sink = $this->redirectEvents();
 553          $notification = $DB->get_record('notifications', ['id' => $notificationid]);
 554          \core_message\api::mark_notification_as_read($notification);
 555          $events = $sink->get_events();
 556          $event = reset($events);
 557  
 558          // Check that the event data is valid.
 559          $this->assertInstanceOf('\core\event\notification_viewed', $event);
 560          $this->assertEquals($notificationid, $event->objectid);
 561          $this->assertEquals($user2->id, $event->userid);
 562          $this->assertEquals($user1->id, $event->relateduserid);
 563          $this->assertEquals(\context_user::instance($user2->id), $event->get_context());
 564          $url = new \moodle_url('/message/output/popup/notifications.php', array('notificationid' => $event->objectid));
 565          $this->assertEquals($url, $event->get_url());
 566      }
 567  }