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 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [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  namespace core_message;
  18  
  19  use core_message\tests\helper as testhelper;
  20  
  21  defined('MOODLE_INTERNAL') || die();
  22  
  23  global $CFG;
  24  require_once($CFG->dirroot . '/message/lib.php');
  25  
  26  /**
  27   * Test api's in message lib.
  28   *
  29   * @package core_message
  30   * @category test
  31   * @copyright 2014 Rajesh Taneja <rajesh@moodle.com>
  32   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class messagelib_test extends \advanced_testcase {
  35  
  36      /** @var phpunit_message_sink keep track of messages. */
  37      protected $messagesink = null;
  38  
  39      /**
  40       * Test set up.
  41       *
  42       * This is executed before running any test in this file.
  43       */
  44      public function setUp(): void {
  45          $this->preventResetByRollback(); // Messaging is not compatible with transactions.
  46          $this->messagesink = $this->redirectMessages();
  47          $this->resetAfterTest();
  48      }
  49  
  50      /**
  51       * Send a fake message.
  52       *
  53       * {@link message_send()} does not support transaction, this function will simulate a message
  54       * sent from a user to another. We should stop using it once {@link message_send()} will support
  55       * transactions. This is not clean at all, this is just used to add rows to the table.
  56       *
  57       * @param \stdClass $userfrom user object of the one sending the message.
  58       * @param \stdClass $userto user object of the one receiving the message.
  59       * @param string $message message to send.
  60       * @param int $notification if the message is a notification.
  61       * @param int $time the time the message was sent
  62       * @return int the id of the message
  63       */
  64      protected function send_fake_message($userfrom, $userto, $message = 'Hello world!', $notification = 0, $time = 0) {
  65          global $DB;
  66  
  67          if (empty($time)) {
  68              $time = time();
  69          }
  70  
  71          if ($notification) {
  72              $record = new \stdClass();
  73              $record->useridfrom = $userfrom->id;
  74              $record->useridto = $userto->id;
  75              $record->subject = 'No subject';
  76              $record->fullmessage = $message;
  77              $record->smallmessage = $message;
  78              $record->timecreated = $time;
  79  
  80              return $DB->insert_record('notifications', $record);
  81          }
  82  
  83          if ($userfrom->id == $userto->id) {
  84              // It's a self conversation.
  85              $conversation = \core_message\api::get_self_conversation($userfrom->id);
  86              if (empty($conversation)) {
  87                  $conversation = \core_message\api::create_conversation(
  88                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
  89                      [$userfrom->id]
  90                  );
  91              }
  92              $conversationid = $conversation->id;
  93          } else if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) {
  94              // It's an individual conversation between two different users.
  95              $conversation = \core_message\api::create_conversation(
  96                  \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
  97                  [
  98                      $userfrom->id,
  99                      $userto->id
 100                  ]
 101              );
 102              $conversationid = $conversation->id;
 103          }
 104  
 105          // Ok, send the message.
 106          $record = new \stdClass();
 107          $record->useridfrom = $userfrom->id;
 108          $record->conversationid = $conversationid;
 109          $record->subject = 'No subject';
 110          $record->fullmessage = $message;
 111          $record->smallmessage = $message;
 112          $record->timecreated = $time;
 113  
 114          return $DB->insert_record('messages', $record);
 115      }
 116  
 117      /**
 118       * Test message_get_blocked_users throws an exception because has been removed.
 119       */
 120      public function test_message_get_blocked_users() {
 121          $this->expectException('coding_exception');
 122          $this->expectExceptionMessage(
 123              'message_get_blocked_users() has been removed, please use \core_message\api::get_blocked_users() instead.'
 124          );
 125          message_get_blocked_users();
 126      }
 127  
 128      /**
 129       * Test message_get_contacts throws an exception because has been removed.
 130       */
 131      public function test_message_get_contacts() {
 132          $this->expectException('coding_exception');
 133          $this->expectExceptionMessage('message_get_contacts() has been removed.');
 134          message_get_contacts();
 135      }
 136  
 137      /**
 138       * Test message_count_unread_messages.
 139       * TODO: MDL-69643
 140       */
 141      public function test_message_count_unread_messages() {
 142          // Create users to send and receive message.
 143          $userfrom1 = $this->getDataGenerator()->create_user();
 144          $userfrom2 = $this->getDataGenerator()->create_user();
 145          $userto = $this->getDataGenerator()->create_user();
 146  
 147          $this->assertEquals(0, message_count_unread_messages($userto));
 148          $this->assertDebuggingCalled();
 149  
 150          // Send fake messages.
 151          $this->send_fake_message($userfrom1, $userto);
 152          $this->send_fake_message($userfrom2, $userto);
 153  
 154          $this->assertEquals(2, message_count_unread_messages($userto));
 155          $this->assertDebuggingCalled();
 156  
 157          $this->assertEquals(1, message_count_unread_messages($userto, $userfrom1));
 158          $this->assertDebuggingCalled();
 159      }
 160  
 161      /**
 162       * Test message_count_unread_messages with read messages.
 163       */
 164      public function test_message_count_unread_messages_with_read_messages() {
 165          global $DB;
 166  
 167          // Create users to send and receive messages.
 168          $userfrom1 = $this->getDataGenerator()->create_user();
 169          $userfrom2 = $this->getDataGenerator()->create_user();
 170          $userto = $this->getDataGenerator()->create_user();
 171  
 172          $this->assertEquals(0, message_count_unread_messages($userto));
 173  
 174          // Send fake messages.
 175          $messageid = $this->send_fake_message($userfrom1, $userto);
 176          $this->send_fake_message($userfrom2, $userto);
 177  
 178          // Mark message as read.
 179          $message = $DB->get_record('messages', ['id' => $messageid]);
 180          \core_message\api::mark_message_as_read($userto->id, $message);
 181  
 182          // Should only count the messages that weren't read by the current user.
 183          $this->assertEquals(1, message_count_unread_messages($userto));
 184          $this->assertDebuggingCalledCount(2);
 185  
 186          $this->assertEquals(0, message_count_unread_messages($userto, $userfrom1));
 187          $this->assertDebuggingCalled();
 188      }
 189  
 190      /**
 191       * Test message_count_unread_messages with deleted messages.
 192       */
 193      public function test_message_count_unread_messages_with_deleted_messages() {
 194          global $DB;
 195  
 196          // Create users to send and receive messages.
 197          $userfrom1 = $this->getDataGenerator()->create_user();
 198          $userfrom2 = $this->getDataGenerator()->create_user();
 199          $userto = $this->getDataGenerator()->create_user();
 200  
 201          $this->assertEquals(0, message_count_unread_messages($userto));
 202          $this->assertDebuggingCalled();
 203  
 204          // Send fake messages.
 205          $messageid = $this->send_fake_message($userfrom1, $userto);
 206          $this->send_fake_message($userfrom2, $userto);
 207  
 208          // Delete a message.
 209          \core_message\api::delete_message($userto->id, $messageid);
 210  
 211          // Should only count the messages that weren't deleted by the current user.
 212          $this->assertEquals(1, message_count_unread_messages($userto));
 213          $this->assertDebuggingCalled();
 214          $this->assertEquals(0, message_count_unread_messages($userto, $userfrom1));
 215          $this->assertDebuggingCalled();
 216      }
 217  
 218      /**
 219       * Test message_count_unread_messages with sent messages.
 220       */
 221      public function test_message_count_unread_messages_with_sent_messages() {
 222          $userfrom = $this->getDataGenerator()->create_user();
 223          $userto = $this->getDataGenerator()->create_user();
 224  
 225          $this->send_fake_message($userfrom, $userto);
 226  
 227          // Ensure an exception is thrown.
 228          $this->assertEquals(0, message_count_unread_messages($userfrom));
 229          $this->assertDebuggingCalled();
 230      }
 231  
 232      /**
 233       * Test message_search_users.
 234       */
 235      public function test_message_search_users() {
 236          global $USER;
 237  
 238          // Set this user as the admin.
 239          $this->setAdminUser();
 240  
 241          // Create a user to add to the admin's contact list.
 242          $user1 = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'user1'));
 243          $user2 = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'user2'));
 244  
 245          // Add users to the admin's contact list.
 246          \core_message\api::add_contact($USER->id, $user1->id);
 247          \core_message\api::add_contact($USER->id, $user2->id);
 248  
 249          $this->assertCount(1, message_search_users(0, 'Test1'));
 250          $this->assertCount(2, message_search_users(0, 'Test'));
 251          $this->assertCount(1, message_search_users(0, 'user1'));
 252          $this->assertCount(2, message_search_users(0, 'user'));
 253      }
 254  
 255      /**
 256       * Test message_get_messages.
 257       */
 258      public function test_message_get_messages() {
 259          global $DB;
 260  
 261          $this->resetAfterTest(true);
 262  
 263          // Set this user as the admin.
 264          $this->setAdminUser();
 265  
 266          $user1 = self::getDataGenerator()->create_user();
 267          $user2 = self::getDataGenerator()->create_user();
 268          $user3 = self::getDataGenerator()->create_user();
 269  
 270          \core_message\api::add_contact($user1->id, $user2->id);
 271          \core_message\api::add_contact($user1->id, $user3->id);
 272  
 273          // Create some individual conversations.
 274          $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 275              [$user1->id, $user2->id]);
 276          $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 277              [$user1->id, $user3->id]);
 278  
 279          // Send some messages to individual conversations.
 280          $im1 = testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1');
 281          $im2 = testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2');
 282          $im3 = testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 3');
 283          $im4 = testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4');
 284  
 285          // Mark a message as read by user2.
 286          $message = $DB->get_record('messages', ['id' => $im1]);
 287          \core_message\api::mark_message_as_read($user2->id, $message);
 288  
 289          // Retrieve unread messages sent from user1 to user2.
 290          $lastmessages = message_get_messages($user2->id, $user1->id, 0, MESSAGE_GET_UNREAD);
 291          $this->assertCount(1, $lastmessages);
 292          $this->assertArrayHasKey($im3, $lastmessages);
 293  
 294          // Get only read messages.
 295          $lastmessages = message_get_messages($user2->id, $user1->id, 0, MESSAGE_GET_READ);
 296          $this->assertCount(1, $lastmessages);
 297          $this->assertArrayHasKey($im1, $lastmessages);
 298  
 299          // Get both read and unread.
 300          $lastmessages = message_get_messages($user2->id, $user1->id, 0, MESSAGE_GET_READ_AND_UNREAD);
 301          $this->assertCount(2, $lastmessages);
 302          $this->assertArrayHasKey($im1, $lastmessages);
 303          $this->assertArrayHasKey($im3, $lastmessages);
 304  
 305          // Repeat retrieve read/unread messages but using a bool to test backwards compatibility.
 306          $lastmessages = message_get_messages($user2->id, $user1->id, 0, false);
 307          $this->assertCount(1, $lastmessages);
 308          $this->assertArrayHasKey($im3, $lastmessages);
 309  
 310          $lastmessages = message_get_messages($user2->id, $user1->id, 0, true);
 311          $this->assertCount(1, $lastmessages);
 312          $this->assertArrayHasKey($im1, $lastmessages);
 313  
 314          // Create some group conversations.
 315          $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 316              [$user1->id, $user2->id, $user3->id], 'Group chat');
 317  
 318          // Send some messages to group conversations.
 319          $gm1 = testhelper::send_fake_message_to_conversation($user1, $gc1->id, 'Group message 1');
 320  
 321          // Retrieve all messages sent from user1 to user2 (the result should be the same as before, because only individual
 322          // conversations should be considered by the message_get_messages function).
 323          $lastmessages = message_get_messages($user2->id, $user1->id, 0, MESSAGE_GET_READ_AND_UNREAD);
 324          $this->assertCount(2, $lastmessages);
 325          $this->assertArrayHasKey($im1, $lastmessages);
 326          $this->assertArrayHasKey($im3, $lastmessages);
 327      }
 328  
 329      /**
 330       * Test message_get_messages with only group conversations between users.
 331       */
 332      public function test_message_get_messages_only_group_conversations() {
 333          $this->resetAfterTest(true);
 334  
 335          // Set this user as the admin.
 336          $this->setAdminUser();
 337  
 338          $user1 = self::getDataGenerator()->create_user();
 339          $user2 = self::getDataGenerator()->create_user();
 340          $user3 = self::getDataGenerator()->create_user();
 341  
 342          // Create some group conversations.
 343          $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 344              [$user1->id, $user2->id, $user3->id], 'Group chat');
 345  
 346          // Send some messages to group conversations.
 347          $gm1 = testhelper::send_fake_message_to_conversation($user1, $gc1->id, 'Group message 1');
 348          $gm2 = testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Group message 2');
 349  
 350          // Retrieve all messages sent from user1 to user2. There shouldn't be messages, because only individual
 351          // conversations should be considered by the message_get_messages function.
 352          $lastmessages = message_get_messages($user2->id, $user1->id, 0, MESSAGE_GET_READ_AND_UNREAD);
 353          $this->assertCount(0, $lastmessages);
 354      }
 355  
 356  }