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