Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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   * Test message API.
  19   *
  20   * @package core_message
  21   * @category test
  22   * @copyright 2016 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 . '/message/tests/messagelib_test.php');
  31  
  32  use \core_message\tests\helper as testhelper;
  33  
  34  /**
  35   * Test message API.
  36   *
  37   * @package core_message
  38   * @category test
  39   * @copyright 2016 Mark Nelson <markn@moodle.com>
  40   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class core_message_api_testcase extends core_message_messagelib_testcase {
  43  
  44      public function test_mark_all_read_for_user_touser() {
  45          $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
  46          $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
  47  
  48          $this->send_fake_message($sender, $recipient, 'Notification', 1);
  49          $this->send_fake_message($sender, $recipient, 'Notification', 1);
  50          $this->send_fake_message($sender, $recipient, 'Notification', 1);
  51          $this->send_fake_message($sender, $recipient);
  52          $this->send_fake_message($sender, $recipient);
  53          $this->send_fake_message($sender, $recipient);
  54  
  55          \core_message\api::mark_all_notifications_as_read($recipient->id);
  56          \core_message\api::mark_all_messages_as_read($recipient->id);
  57          $this->assertEquals(message_count_unread_messages($recipient), 0);
  58      }
  59  
  60      public function test_mark_all_read_for_user_touser_with_fromuser() {
  61          $sender1 = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
  62          $sender2 = $this->getDataGenerator()->create_user(array('firstname' => 'Test3', 'lastname' => 'User3'));
  63          $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
  64  
  65          $this->send_fake_message($sender1, $recipient, 'Notification', 1);
  66          $this->send_fake_message($sender1, $recipient, 'Notification', 1);
  67          $this->send_fake_message($sender1, $recipient, 'Notification', 1);
  68          $this->send_fake_message($sender1, $recipient);
  69          $this->send_fake_message($sender1, $recipient);
  70          $this->send_fake_message($sender1, $recipient);
  71          $this->send_fake_message($sender2, $recipient, 'Notification', 1);
  72          $this->send_fake_message($sender2, $recipient, 'Notification', 1);
  73          $this->send_fake_message($sender2, $recipient, 'Notification', 1);
  74          $this->send_fake_message($sender2, $recipient);
  75          $this->send_fake_message($sender2, $recipient);
  76          $this->send_fake_message($sender2, $recipient);
  77  
  78          \core_message\api::mark_all_notifications_as_read($recipient->id, $sender1->id);
  79          $conversationid = \core_message\api::get_conversation_between_users([$recipient->id, $sender1->id]);
  80          \core_message\api::mark_all_messages_as_read($recipient->id, $conversationid);
  81  
  82          $this->assertEquals(message_count_unread_messages($recipient), 3);
  83      }
  84  
  85      public function test_mark_all_read_for_user_touser_with_type() {
  86          $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
  87          $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
  88  
  89          $this->send_fake_message($sender, $recipient, 'Notification', 1);
  90          $this->send_fake_message($sender, $recipient, 'Notification', 1);
  91          $this->send_fake_message($sender, $recipient, 'Notification', 1);
  92          $this->send_fake_message($sender, $recipient);
  93          $this->send_fake_message($sender, $recipient);
  94          $this->send_fake_message($sender, $recipient);
  95  
  96          \core_message\api::mark_all_notifications_as_read($recipient->id);
  97          $this->assertEquals(message_count_unread_messages($recipient), 3);
  98  
  99          \core_message\api::mark_all_messages_as_read($recipient->id);
 100          $this->assertEquals(message_count_unread_messages($recipient), 0);
 101      }
 102  
 103      /**
 104       * Test count_blocked_users.
 105       */
 106      public function test_count_blocked_users() {
 107          global $USER;
 108  
 109          // Set this user as the admin.
 110          $this->setAdminUser();
 111  
 112          // Create user to add to the admin's block list.
 113          $user1 = $this->getDataGenerator()->create_user();
 114          $user2 = $this->getDataGenerator()->create_user();
 115  
 116          $this->assertEquals(0, \core_message\api::count_blocked_users());
 117  
 118          // Add 1 blocked user to admin's blocked user list.
 119          \core_message\api::block_user($USER->id, $user1->id);
 120  
 121          $this->assertEquals(0, \core_message\api::count_blocked_users($user1));
 122          $this->assertEquals(1, \core_message\api::count_blocked_users());
 123      }
 124  
 125      /**
 126       * Tests searching users in a course.
 127       */
 128      public function test_search_users_in_course() {
 129          // Create some users.
 130          $user1 = new stdClass();
 131          $user1->firstname = 'User';
 132          $user1->lastname = 'One';
 133          $user1 = self::getDataGenerator()->create_user($user1);
 134  
 135          // The person doing the search.
 136          $this->setUser($user1);
 137  
 138          // Second user is going to have their last access set to now, so they are online.
 139          $user2 = new stdClass();
 140          $user2->firstname = 'User';
 141          $user2->lastname = 'Two';
 142          $user2->lastaccess = time();
 143          $user2 = self::getDataGenerator()->create_user($user2);
 144  
 145          // Block the second user.
 146          \core_message\api::block_user($user1->id, $user2->id);
 147  
 148          $user3 = new stdClass();
 149          $user3->firstname = 'User';
 150          $user3->lastname = 'Three';
 151          $user3 = self::getDataGenerator()->create_user($user3);
 152  
 153          // Create a course.
 154          $course1 = new stdClass();
 155          $course1->fullname = 'Course';
 156          $course1->shortname = 'One';
 157          $course1 = $this->getDataGenerator()->create_course($course1);
 158  
 159          // Enrol the searcher and one user in the course.
 160          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
 161          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
 162  
 163          // Perform a search.
 164          $results = \core_message\api::search_users_in_course($user1->id, $course1->id, 'User');
 165  
 166          $this->assertEquals(1, count($results));
 167  
 168          $user = $results[0];
 169          $this->assertEquals($user2->id, $user->userid);
 170          $this->assertEquals(fullname($user2), $user->fullname);
 171          $this->assertFalse($user->ismessaging);
 172          $this->assertNull($user->lastmessage);
 173          $this->assertNull($user->messageid);
 174          $this->assertNull($user->isonline);
 175          $this->assertFalse($user->isread);
 176          $this->assertTrue($user->isblocked);
 177          $this->assertNull($user->unreadcount);
 178      }
 179  
 180      /**
 181       * Tests searching users.
 182       */
 183      public function test_search_users() {
 184          global $DB;
 185  
 186          // Create some users.
 187          $user1 = new stdClass();
 188          $user1->firstname = 'User';
 189          $user1->lastname = 'One';
 190          $user1 = self::getDataGenerator()->create_user($user1);
 191  
 192          // Set as the user performing the search.
 193          $this->setUser($user1);
 194  
 195          $user2 = new stdClass();
 196          $user2->firstname = 'User search';
 197          $user2->lastname = 'Two';
 198          $user2 = self::getDataGenerator()->create_user($user2);
 199  
 200          $user3 = new stdClass();
 201          $user3->firstname = 'User search';
 202          $user3->lastname = 'Three';
 203          $user3 = self::getDataGenerator()->create_user($user3);
 204  
 205          $user4 = new stdClass();
 206          $user4->firstname = 'User';
 207          $user4->lastname = 'Four';
 208          $user4 = self::getDataGenerator()->create_user($user4);
 209  
 210          $user5 = new stdClass();
 211          $user5->firstname = 'User search';
 212          $user5->lastname = 'Five';
 213          $user5 = self::getDataGenerator()->create_user($user5);
 214  
 215          $user6 = new stdClass();
 216          $user6->firstname = 'User';
 217          $user6->lastname = 'Six';
 218          $user6 = self::getDataGenerator()->create_user($user6);
 219  
 220          // Create some courses.
 221          $course1 = new stdClass();
 222          $course1->fullname = 'Course search';
 223          $course1->shortname = 'One';
 224          $course1 = $this->getDataGenerator()->create_course($course1);
 225  
 226          $course2 = new stdClass();
 227          $course2->fullname = 'Course';
 228          $course2->shortname = 'Two';
 229          $course2 = $this->getDataGenerator()->create_course($course2);
 230  
 231          $course3 = new stdClass();
 232          $course3->fullname = 'Course';
 233          $course3->shortname = 'Three search';
 234          $course3 = $this->getDataGenerator()->create_course($course3);
 235  
 236          $course4 = new stdClass();
 237          $course4->fullname = 'Course Four';
 238          $course4->shortname = 'CF100';
 239          $course4 = $this->getDataGenerator()->create_course($course4);
 240  
 241          $course5 = new stdClass();
 242          $course5->fullname = 'Course';
 243          $course5->shortname = 'Five search';
 244          $course5 = $this->getDataGenerator()->create_course($course5);
 245  
 246          $role = $DB->get_record('role', ['shortname' => 'student']);
 247          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $role->id);
 248          $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $role->id);
 249          $this->getDataGenerator()->enrol_user($user1->id, $course3->id, $role->id);
 250          $this->getDataGenerator()->enrol_user($user1->id, $course5->id, $role->id);
 251  
 252          // Add some users as contacts.
 253          \core_message\api::add_contact($user1->id, $user2->id);
 254          \core_message\api::add_contact($user1->id, $user3->id);
 255          \core_message\api::add_contact($user1->id, $user4->id);
 256  
 257          // Remove the viewparticipants capability from one of the courses.
 258          $course5context = context_course::instance($course5->id);
 259          assign_capability('moodle/course:viewparticipants', CAP_PROHIBIT, $role->id, $course5context->id);
 260  
 261          // Perform a search $CFG->messagingallusers setting enabled.
 262          set_config('messagingallusers', 1);
 263          list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
 264  
 265          // Check that we retrieved the correct contacts.
 266          $this->assertEquals(2, count($contacts));
 267          $this->assertEquals($user3->id, $contacts[0]->userid);
 268          $this->assertEquals($user2->id, $contacts[1]->userid);
 269  
 270          // Check that we retrieved the correct courses.
 271          $this->assertEquals(2, count($courses));
 272          $this->assertEquals($course3->id, $courses[0]->id);
 273          $this->assertEquals($course1->id, $courses[1]->id);
 274  
 275          // Check that we retrieved the correct non-contacts.
 276          $this->assertEquals(1, count($noncontacts));
 277          $this->assertEquals($user5->id, $noncontacts[0]->userid);
 278      }
 279  
 280      /**
 281       * Tests searching users with empty result.
 282       */
 283      public function test_search_users_with_empty_result() {
 284  
 285          // Create some users.
 286          $user1 = new stdClass();
 287          $user1->firstname = 'User';
 288          $user1->lastname = 'One';
 289          $user1 = self::getDataGenerator()->create_user($user1);
 290  
 291          // Set as the user performing the search.
 292          $this->setUser($user1);
 293  
 294          $user2 = new stdClass();
 295          $user2->firstname = 'User';
 296          $user2->lastname = 'Two';
 297          $user2 = self::getDataGenerator()->create_user($user2);
 298  
 299          // Perform a search $CFG->messagingallusers setting enabled.
 300          set_config('messagingallusers', 1);
 301          list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
 302  
 303          // Check results are empty.
 304          $this->assertEquals(0, count($contacts));
 305          $this->assertEquals(0, count($courses));
 306          $this->assertEquals(0, count($noncontacts));
 307      }
 308  
 309      /**
 310       * Tests searching for users when site-wide messaging is disabled.
 311       *
 312       * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
 313       * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
 314       * profile.
 315       */
 316      public function test_message_search_users_messagingallusers_disabled() {
 317          global $DB;
 318          $this->resetAfterTest();
 319  
 320          // Create some users.
 321          $users = [];
 322          foreach (range(1, 8) as $i) {
 323              $user = new stdClass();
 324              $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
 325              $user->lastname = $i;
 326              $user = $this->getDataGenerator()->create_user($user);
 327              $users[$i] = $user;
 328          }
 329  
 330          // Enrol a few users in the same course, but leave them as non-contacts.
 331          $course1 = $this->getDataGenerator()->create_course();
 332          $course2 = $this->getDataGenerator()->create_course();
 333  
 334          $this->setAdminUser();
 335          $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
 336          $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
 337          $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
 338  
 339          // Add some other users as contacts.
 340          \core_message\api::add_contact($users[1]->id, $users[2]->id);
 341          \core_message\api::add_contact($users[3]->id, $users[1]->id);
 342          \core_message\api::add_contact($users[1]->id, $users[4]->id);
 343  
 344          // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
 345          $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher');
 346          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 347          set_config('coursecontact', $teacherrole->id);
 348  
 349          // Create individual conversations between some users, one contact and one non-contact.
 350          $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 351              [$users[1]->id, $users[2]->id]);
 352          $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 353              [$users[6]->id, $users[1]->id]);
 354  
 355          // Create a group conversation between 4 users, including a contact and a non-contact.
 356          $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 357              [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
 358  
 359          // Set as the user performing the search.
 360          $this->setUser($users[1]);
 361  
 362          // Perform a search with $CFG->messagingallusers disabled.
 363          set_config('messagingallusers', 0);
 364          $result = \core_message\api::message_search_users($users[1]->id, 'search');
 365  
 366          // Confirm that we returns contacts and non-contacts.
 367          $this->assertArrayHasKey(0, $result);
 368          $this->assertArrayHasKey(1, $result);
 369          $contacts = $result[0];
 370          $noncontacts = $result[1];
 371  
 372          // Check that we retrieved the correct contacts.
 373          $this->assertCount(2, $contacts);
 374          $this->assertEquals($users[2]->id, $contacts[0]->id);
 375          $this->assertEquals($users[3]->id, $contacts[1]->id);
 376  
 377          // Verify the correct conversations were returned for the contacts.
 378          $this->assertCount(2, $contacts[0]->conversations);
 379          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
 380          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
 381  
 382          $this->assertCount(0, $contacts[1]->conversations);
 383  
 384          // Check that we retrieved the correct non-contacts.
 385          // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles
 386          // are visible in that course. This excludes users like course contacts.
 387          $this->assertCount(3, $noncontacts);
 388          // Self-conversation first.
 389          $this->assertEquals($users[1]->id, $noncontacts[0]->id);
 390          $this->assertEquals($users[6]->id, $noncontacts[1]->id);
 391          $this->assertEquals($users[7]->id, $noncontacts[2]->id);
 392  
 393          // Verify the correct conversations were returned for the non-contacts.
 394          $this->assertCount(1, $noncontacts[1]->conversations);
 395          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 396              $noncontacts[1]->conversations[$ic2->id]->type);
 397  
 398          $this->assertCount(1, $noncontacts[2]->conversations);
 399          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
 400      }
 401  
 402      /**
 403       * Tests searching for users when site-wide messaging is enabled.
 404       *
 405       * This test verifies that any contacts are returned, as well as any non-contacts,
 406       * provided the searching user can view their profile.
 407       */
 408      public function test_message_search_users_messagingallusers_enabled() {
 409          global $DB;
 410          $this->resetAfterTest();
 411  
 412          // Create some users.
 413          $users = [];
 414          foreach (range(1, 9) as $i) {
 415              $user = new stdClass();
 416              $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
 417              $user->lastname = $i;
 418              $user = $this->getDataGenerator()->create_user($user);
 419              $users[$i] = $user;
 420          }
 421  
 422          $course1 = $this->getDataGenerator()->create_course();
 423          $coursecontext = \context_course::instance($course1->id);
 424  
 425          // Enrol a few users in the same course, but leave them as non-contacts.
 426          $this->setAdminUser();
 427          $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id, 'student');
 428          $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id, 'student');
 429          $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id, 'student');
 430  
 431          // Add some other users as contacts.
 432          \core_message\api::add_contact($users[1]->id, $users[2]->id);
 433          \core_message\api::add_contact($users[3]->id, $users[1]->id);
 434          \core_message\api::add_contact($users[1]->id, $users[4]->id);
 435  
 436          // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
 437          $this->getDataGenerator()->enrol_user($users[9]->id, $course1->id, 'editingteacher');
 438          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 439          set_config('coursecontact', $teacherrole->id);
 440  
 441          // Get self-conversation.
 442          $selfconversation = \core_message\api::get_self_conversation($users[1]->id);
 443  
 444          // Create individual conversations between some users, one contact and one non-contact.
 445          $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 446              [$users[1]->id, $users[2]->id]);
 447          $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 448              [$users[6]->id, $users[1]->id]);
 449  
 450          // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
 451          $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 452              [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
 453  
 454          // Set as the user performing the search.
 455          $this->setUser($users[1]);
 456  
 457          // Perform a search with $CFG->messagingallusers enabled.
 458          set_config('messagingallusers', 1);
 459          $result = \core_message\api::message_search_users($users[1]->id, 'search');
 460  
 461          // Confirm that we returns contacts and non-contacts.
 462          $this->assertArrayHasKey(0, $result);
 463          $this->assertArrayHasKey(1, $result);
 464          $contacts = $result[0];
 465          $noncontacts = $result[1];
 466  
 467          // Check that we retrieved the correct contacts.
 468          $this->assertCount(2, $contacts);
 469          $this->assertEquals($users[2]->id, $contacts[0]->id);
 470          $this->assertEquals($users[3]->id, $contacts[1]->id);
 471  
 472          // Verify the correct conversations were returned for the contacts.
 473          $this->assertCount(2, $contacts[0]->conversations);
 474          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
 475          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
 476  
 477          $this->assertCount(0, $contacts[1]->conversations);
 478  
 479          // Check that we retrieved the correct non-contacts.
 480          // If site wide messaging is enabled, we expect to only be able to search for users whose profiles we can view.
 481          // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1.
 482          // Consider first conversations is self-conversation.
 483          $this->assertCount(4, $noncontacts);
 484          $this->assertEquals($users[1]->id, $noncontacts[0]->id);
 485          $this->assertEquals($users[6]->id, $noncontacts[1]->id);
 486          $this->assertEquals($users[7]->id, $noncontacts[2]->id);
 487          $this->assertEquals($users[9]->id, $noncontacts[3]->id);
 488  
 489          $this->assertCount(1, $noncontacts[1]->conversations);
 490          $this->assertCount(1, $noncontacts[2]->conversations);
 491          $this->assertCount(0, $noncontacts[3]->conversations);
 492  
 493          // Verify the correct conversations were returned for the non-contacts.
 494          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
 495              $noncontacts[0]->conversations[$selfconversation->id]->type);
 496  
 497          $this->assertCount(1, $noncontacts[1]->conversations);
 498          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 499              $noncontacts[1]->conversations[$ic2->id]->type);
 500  
 501          $this->assertCount(1, $noncontacts[2]->conversations);
 502          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
 503  
 504          $this->assertCount(0, $noncontacts[3]->conversations);
 505      }
 506  
 507      /**
 508       * Verify searching for users find themselves when they have self-conversations.
 509       */
 510      public function test_message_search_users_self_conversations() {
 511          $this->resetAfterTest();
 512  
 513          // Create some users.
 514          $user1 = new stdClass();
 515          $user1->firstname = 'User';
 516          $user1->lastname = 'One';
 517          $user1 = $this->getDataGenerator()->create_user($user1);
 518          $user2 = new stdClass();
 519          $user2->firstname = 'User';
 520          $user2->lastname = 'Two';
 521          $user2 = $this->getDataGenerator()->create_user($user2);
 522  
 523          // Get self-conversation for user1.
 524          $sc1 = \core_message\api::get_self_conversation($user1->id);
 525          testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
 526  
 527          // Perform a search as user1.
 528          $this->setUser($user1);
 529          $result = \core_message\api::message_search_users($user1->id, 'One');
 530  
 531          // Check user1 is found as non-contacts.
 532          $this->assertCount(0, $result[0]);
 533          $this->assertCount(1, $result[1]);
 534      }
 535  
 536      /**
 537       * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
 538       */
 539      public function test_message_search_users_with_empty_result() {
 540          $this->resetAfterTest();
 541  
 542          // Create some users, but make sure neither will match the search term.
 543          $user1 = new stdClass();
 544          $user1->firstname = 'User';
 545          $user1->lastname = 'One';
 546          $user1 = $this->getDataGenerator()->create_user($user1);
 547          $user2 = new stdClass();
 548          $user2->firstname = 'User';
 549          $user2->lastname = 'Two';
 550          $user2 = $this->getDataGenerator()->create_user($user2);
 551  
 552          // Perform a search as user1.
 553          $this->setUser($user1);
 554          $result = \core_message\api::message_search_users($user1->id, 'search');
 555  
 556          // Check results are empty.
 557          $this->assertCount(0, $result[0]);
 558          $this->assertCount(0, $result[1]);
 559      }
 560  
 561      /**
 562       * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
 563       */
 564      public function test_message_search_users_limit_offset() {
 565          $this->resetAfterTest();
 566  
 567          // Create 20 users.
 568          $users = [];
 569          foreach (range(1, 20) as $i) {
 570              $user = new stdClass();
 571              $user->firstname = "User search";
 572              $user->lastname = $i;
 573              $user = $this->getDataGenerator()->create_user($user);
 574              $users[$i] = $user;
 575          }
 576  
 577          // Enrol the first 9 users in the same course, but leave them as non-contacts.
 578          $this->setAdminUser();
 579          $course1 = $this->getDataGenerator()->create_course();
 580          foreach (range(1, 8) as $i) {
 581              $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
 582          }
 583  
 584          // Add 5 users, starting at the 11th user, as contacts for user1.
 585          foreach (range(11, 15) as $i) {
 586              \core_message\api::add_contact($users[1]->id, $users[$i]->id);
 587          }
 588  
 589          // Set as the user performing the search.
 590          $this->setUser($users[1]);
 591  
 592          // Search using a limit of 3.
 593          // This tests the case where we have more results than the limit for both contacts and non-contacts.
 594          $result = \core_message\api::message_search_users($users[1]->id, 'search', 0, 3);
 595          $contacts = $result[0];
 596          $noncontacts = $result[1];
 597  
 598          // Check that we retrieved the correct contacts.
 599          $this->assertCount(3, $contacts);
 600          $this->assertEquals($users[11]->id, $contacts[0]->id);
 601          $this->assertEquals($users[12]->id, $contacts[1]->id);
 602          $this->assertEquals($users[13]->id, $contacts[2]->id);
 603  
 604          // Check that we retrieved the correct non-contacts.
 605          // Consider first conversations is self-conversation.
 606          $this->assertCount(3, $noncontacts);
 607          $this->assertEquals($users[1]->id, $noncontacts[0]->id);
 608          $this->assertEquals($users[2]->id, $noncontacts[1]->id);
 609          $this->assertEquals($users[3]->id, $noncontacts[2]->id);
 610  
 611          // Now, offset to get the next batch of results.
 612          // We expect to see 2 contacts, and 3 non-contacts.
 613          $result = \core_message\api::message_search_users($users[1]->id, 'search', 3, 3);
 614          $contacts = $result[0];
 615          $noncontacts = $result[1];
 616          $this->assertCount(2, $contacts);
 617          $this->assertEquals($users[14]->id, $contacts[0]->id);
 618          $this->assertEquals($users[15]->id, $contacts[1]->id);
 619  
 620          $this->assertCount(3, $noncontacts);
 621          $this->assertEquals($users[4]->id, $noncontacts[0]->id);
 622          $this->assertEquals($users[5]->id, $noncontacts[1]->id);
 623          $this->assertEquals($users[6]->id, $noncontacts[2]->id);
 624  
 625          // Now, offset to get the next batch of results.
 626          // We expect to see 0 contacts, and 2 non-contacts.
 627          $result = \core_message\api::message_search_users($users[1]->id, 'search', 6, 3);
 628          $contacts = $result[0];
 629          $noncontacts = $result[1];
 630          $this->assertCount(0, $contacts);
 631  
 632          $this->assertCount(2, $noncontacts);
 633          $this->assertEquals($users[7]->id, $noncontacts[0]->id);
 634          $this->assertEquals($users[8]->id, $noncontacts[1]->id);
 635      }
 636  
 637      /**
 638       * Tests searching users as a user having the 'moodle/user:viewdetails' capability.
 639       */
 640      public function test_message_search_users_with_cap() {
 641          $this->resetAfterTest();
 642          global $DB;
 643  
 644          // Create some users.
 645          $users = [];
 646          foreach (range(1, 8) as $i) {
 647              $user = new stdClass();
 648              $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
 649              $user->lastname = $i;
 650              $user = $this->getDataGenerator()->create_user($user);
 651              $users[$i] = $user;
 652          }
 653  
 654          // Enrol a few users in the same course, but leave them as non-contacts.
 655          $course1 = $this->getDataGenerator()->create_course();
 656          $this->setAdminUser();
 657          $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
 658          $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
 659          $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
 660  
 661          // Add some other users as contacts.
 662          \core_message\api::add_contact($users[1]->id, $users[2]->id);
 663          \core_message\api::add_contact($users[3]->id, $users[1]->id);
 664          \core_message\api::add_contact($users[1]->id, $users[4]->id);
 665  
 666          // Set as the user performing the search.
 667          $this->setUser($users[1]);
 668  
 669          // Grant the authenticated user role the capability 'user:viewdetails' at site context.
 670          $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
 671          assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
 672  
 673          // Perform a search with $CFG->messagingallusers disabled.
 674          set_config('messagingallusers', 0);
 675          $result = \core_message\api::message_search_users($users[1]->id, 'search');
 676          $contacts = $result[0];
 677          $noncontacts = $result[1];
 678  
 679          // Check that we retrieved the correct contacts.
 680          $this->assertCount(2, $contacts);
 681          $this->assertEquals($users[2]->id, $contacts[0]->id);
 682          $this->assertEquals($users[3]->id, $contacts[1]->id);
 683  
 684          // Check that we retrieved the correct non-contacts.
 685          // Site-wide messaging is disabled, so we expect to be able to search for any users whose profiles we can view.
 686          // Consider first conversations is self-conversation.
 687          $this->assertCount(3, $noncontacts);
 688          $this->assertEquals($users[1]->id, $noncontacts[0]->id);
 689          $this->assertEquals($users[6]->id, $noncontacts[1]->id);
 690          $this->assertEquals($users[7]->id, $noncontacts[2]->id);
 691      }
 692  
 693      /**
 694       * Tests searching users with messaging disabled.
 695       */
 696      public function test_message_search_users_messaging_disabled() {
 697          $this->resetAfterTest();
 698  
 699          // Create a user.
 700          $user = $this->getDataGenerator()->create_user();
 701  
 702          // Disable messaging.
 703          set_config('messaging', 0);
 704  
 705          // Ensure an exception is thrown.
 706          $this->expectException('moodle_exception');
 707          \core_message\api::message_search_users($user->id, 'User');
 708      }
 709  
 710      /**
 711       * Tests getting conversations between 2 users.
 712       */
 713      public function test_get_conversations_between_users() {
 714          // Create some users.
 715          $user1 = new stdClass();
 716          $user1->firstname = 'User';
 717          $user1->lastname = 'One';
 718          $user1 = self::getDataGenerator()->create_user($user1);
 719  
 720          $user2 = new stdClass();
 721          $user2->firstname = 'User';
 722          $user2->lastname = 'Two';
 723          $user2 = self::getDataGenerator()->create_user($user2);
 724  
 725          $user3 = new stdClass();
 726          $user3->firstname = 'User search';
 727          $user3->lastname = 'Three';
 728          $user3 = self::getDataGenerator()->create_user($user3);
 729  
 730          $user4 = new stdClass();
 731          $user4->firstname = 'User';
 732          $user4->lastname = 'Four';
 733          $user4 = self::getDataGenerator()->create_user($user4);
 734  
 735          $user5 = new stdClass();
 736          $user5->firstname = 'User';
 737          $user5->lastname = 'Five';
 738          $user5 = self::getDataGenerator()->create_user($user5);
 739  
 740          $user6 = new stdClass();
 741          $user6->firstname = 'User search';
 742          $user6->lastname = 'Six';
 743          $user6 = self::getDataGenerator()->create_user($user6);
 744  
 745          // Add some users as contacts.
 746          \core_message\api::add_contact($user1->id, $user2->id);
 747          \core_message\api::add_contact($user6->id, $user1->id);
 748  
 749          // Create private conversations with some users.
 750          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 751              array($user1->id, $user2->id));
 752          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 753              array($user3->id, $user1->id));
 754  
 755          // Create a group conversation with users.
 756          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 757              array($user1->id, $user2->id, $user3->id, $user4->id),
 758              'Project chat');
 759  
 760          // Check that we retrieved the correct conversations.
 761          $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user2->id));
 762          $this->assertCount(2, \core_message\api::get_conversations_between_users($user2->id, $user1->id));
 763          $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user3->id));
 764          $this->assertCount(2, \core_message\api::get_conversations_between_users($user3->id, $user1->id));
 765          $this->assertCount(1, \core_message\api::get_conversations_between_users($user1->id, $user4->id));
 766          $this->assertCount(1, \core_message\api::get_conversations_between_users($user4->id, $user1->id));
 767          $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user5->id));
 768          $this->assertCount(0, \core_message\api::get_conversations_between_users($user5->id, $user1->id));
 769          $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user6->id));
 770          $this->assertCount(0, \core_message\api::get_conversations_between_users($user6->id, $user1->id));
 771      }
 772  
 773      /**
 774       * Tests getting self-conversations.
 775       */
 776      public function test_get_self_conversation() {
 777          // Create some users.
 778          $user1 = new stdClass();
 779          $user1->firstname = 'User';
 780          $user1->lastname = 'One';
 781          $user1 = self::getDataGenerator()->create_user($user1);
 782  
 783          $user2 = new stdClass();
 784          $user2->firstname = 'User';
 785          $user2->lastname = 'Two';
 786          $user2 = self::getDataGenerator()->create_user($user2);
 787  
 788          $user3 = new stdClass();
 789          $user3->firstname = 'User search';
 790          $user3->lastname = 'Three';
 791          $user3 = self::getDataGenerator()->create_user($user3);
 792  
 793          // Add some users as contacts.
 794          \core_message\api::add_contact($user1->id, $user2->id);
 795          \core_message\api::add_contact($user3->id, $user1->id);
 796  
 797          // Create private conversations with some users.
 798          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 799              array($user1->id, $user2->id));
 800          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
 801              array($user3->id, $user1->id));
 802  
 803          // Create a group conversation with users.
 804          $gc = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 805              array($user1->id, $user2->id, $user3->id),
 806              'Project chat');
 807  
 808          // Get self-conversations.
 809          $rsc1 = \core_message\api::get_self_conversation($user1->id);
 810          $rsc2 = \core_message\api::get_self_conversation($user2->id);
 811          $rsc3 = \core_message\api::get_self_conversation($user3->id);
 812  
 813          // Send message to self-conversation.
 814          testhelper::send_fake_message_to_conversation($user1, $rsc1->id, 'Message to myself!');
 815  
 816          // Check that we retrieved the correct conversations.
 817          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, $rsc1->type);
 818          $members = \core_message\api::get_conversation_members($user1->id, $rsc1->id);
 819          $this->assertCount(1, $members);
 820          $member = reset($members);
 821          $this->assertEquals($user1->id, $member->id);
 822  
 823          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, $rsc2->type);
 824          $members = \core_message\api::get_conversation_members($user2->id, $rsc2->id);
 825          $this->assertCount(1, $members);
 826          $member = reset($members);
 827          $this->assertEquals($user2->id, $member->id);
 828  
 829          \core_message\api::delete_all_conversation_data($rsc3->id);
 830          $selfconversation = \core_message\api::get_self_conversation($user3->id);
 831          $members = \core_message\api::get_conversation_members($user1->id, $selfconversation->id);
 832          $this->assertCount(1, $members);
 833      }
 834  
 835      /**
 836       * Tests searching messages.
 837       */
 838      public function test_search_messages() {
 839          $this->resetAfterTest();
 840  
 841          // Create some users.
 842          $user1 = self::getDataGenerator()->create_user();
 843          $user2 = self::getDataGenerator()->create_user();
 844          $user3 = self::getDataGenerator()->create_user();
 845  
 846          // The person doing the search.
 847          $this->setUser($user1);
 848  
 849          // Get self-conversation.
 850          $sc = \core_message\api::get_self_conversation($user1->id);
 851  
 852          // Create group conversation.
 853          $gc = \core_message\api::create_conversation(
 854              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
 855              [$user1->id, $user2->id, $user3->id]
 856          );
 857  
 858          // Send some messages back and forth.
 859          $time = 1;
 860          testhelper::send_fake_message_to_conversation($user1, $sc->id, 'Test message to self!', $time);
 861          testhelper::send_fake_message_to_conversation($user1, $gc->id, 'My hero!', $time + 1);
 862          $this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time + 2);
 863          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 3);
 864          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 4);
 865          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 5);
 866          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 6);
 867  
 868          $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
 869          $conv2id = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
 870  
 871          // Block user 3.
 872          \core_message\api::block_user($user1->id, $user3->id);
 873  
 874          // Perform a search.
 875          $messages = \core_message\api::search_messages($user1->id, 'o');
 876  
 877          // Confirm the data is correct.
 878          $this->assertEquals(5, count($messages));
 879          $message1 = $messages[0];
 880          $message2 = $messages[1];
 881          $message3 = $messages[2];
 882          $message4 = $messages[3];
 883          $message5 = $messages[4];
 884  
 885          $this->assertEquals($user2->id, $message1->userid);
 886          $this->assertEquals($user2->id, $message1->useridfrom);
 887          $this->assertEquals(fullname($user2), $message1->fullname);
 888          $this->assertTrue($message1->ismessaging);
 889          $this->assertEquals('Word.', $message1->lastmessage);
 890          $this->assertNotEmpty($message1->messageid);
 891          $this->assertNull($message1->isonline);
 892          $this->assertFalse($message1->isread);
 893          $this->assertFalse($message1->isblocked);
 894          $this->assertNull($message1->unreadcount);
 895          $this->assertEquals($convid, $message1->conversationid);
 896  
 897          $this->assertEquals($user2->id, $message2->userid);
 898          $this->assertEquals($user1->id, $message2->useridfrom);
 899          $this->assertEquals(fullname($user2), $message2->fullname);
 900          $this->assertTrue($message2->ismessaging);
 901          $this->assertEquals('Yo!', $message2->lastmessage);
 902          $this->assertNotEmpty($message2->messageid);
 903          $this->assertNull($message2->isonline);
 904          $this->assertTrue($message2->isread);
 905          $this->assertFalse($message2->isblocked);
 906          $this->assertNull($message2->unreadcount);
 907          $this->assertEquals($convid, $message2->conversationid);
 908  
 909          $this->assertEquals($user3->id, $message3->userid);
 910          $this->assertEquals($user3->id, $message3->useridfrom);
 911          $this->assertEquals(fullname($user3), $message3->fullname);
 912          $this->assertTrue($message3->ismessaging);
 913          $this->assertEquals('Don\'t block me.', $message3->lastmessage);
 914          $this->assertNotEmpty($message3->messageid);
 915          $this->assertNull($message3->isonline);
 916          $this->assertFalse($message3->isread);
 917          $this->assertTrue($message3->isblocked);
 918          $this->assertNull($message3->unreadcount);
 919          $this->assertEquals($conv2id, $message3->conversationid);
 920  
 921          // This is a group conversation. For now, search_messages returns only one of the other users on the conversation. It can't
 922          // be guaranteed who will be returned in the first place, so we need to use the in_array to check all the possibilities.
 923          $this->assertTrue(in_array($message4->userid, [$user2->id, $user3->id]));
 924          $this->assertEquals($user1->id, $message4->useridfrom);
 925          $this->assertTrue($message4->ismessaging);
 926          $this->assertEquals('My hero!', $message4->lastmessage);
 927          $this->assertNotEmpty($message4->messageid);
 928          $this->assertNull($message4->isonline);
 929          $this->assertTrue($message4->isread);
 930          $this->assertNull($message4->unreadcount);
 931          $this->assertEquals($gc->id, $message4->conversationid);
 932  
 933          $this->assertEquals($user1->id, $message5->userid);
 934          $this->assertEquals($user1->id, $message5->useridfrom);
 935          $this->assertEquals(fullname($user1), $message5->fullname);
 936          $this->assertTrue($message5->ismessaging);
 937          $this->assertEquals('Test message to self!', $message5->lastmessage);
 938          $this->assertNotEmpty($message5->messageid);
 939          $this->assertFalse($message5->isonline);
 940          $this->assertTrue($message5->isread);
 941          $this->assertFalse($message5->isblocked);
 942          $this->assertNull($message5->unreadcount);
 943          $this->assertEquals($sc->id, $message5->conversationid);
 944      }
 945  
 946      /**
 947       * Test verifying that favourited conversations can be retrieved.
 948       */
 949      public function test_get_favourite_conversations() {
 950          // Create some users.
 951          $user1 = self::getDataGenerator()->create_user();
 952          $user2 = self::getDataGenerator()->create_user();
 953          $user3 = self::getDataGenerator()->create_user();
 954          $user4 = self::getDataGenerator()->create_user();
 955  
 956          // The person doing the search.
 957          $this->setUser($user1);
 958  
 959          // Only self-conversation created.
 960          $this->assertCount(1, \core_message\api::get_conversations($user1->id));
 961  
 962          // Create some conversations for user1.
 963          $time = 1;
 964          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
 965          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
 966          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
 967          $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
 968  
 969          $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
 970          $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
 971          $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
 972          $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
 973  
 974          $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
 975          $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
 976          $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
 977  
 978          // Favourite the first 2 conversations for user1.
 979          $convoids = [];
 980          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
 981          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
 982          $user1context = context_user::instance($user1->id);
 983          $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
 984          foreach ($convoids as $convoid) {
 985              $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
 986          }
 987  
 988          // We should have 4 conversations.
 989          // Consider first conversations is self-conversation.
 990          $this->assertCount(4, \core_message\api::get_conversations($user1->id));
 991  
 992          // And 3 favourited conversations (self-conversation included).
 993          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
 994          $this->assertCount(3, $conversations);
 995          $conversations = \core_message\api::get_conversations(
 996              $user1->id,
 997              0,
 998              20,
 999              \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
1000              true
1001          );
1002          $this->assertCount(1, $conversations);
1003      }
1004  
1005      /**
1006       * Tests retrieving favourite conversations with a limit and offset to ensure pagination works correctly.
1007       */
1008      public function test_get_favourite_conversations_limit_offset() {
1009          // Create some users.
1010          $user1 = self::getDataGenerator()->create_user();
1011          $user2 = self::getDataGenerator()->create_user();
1012          $user3 = self::getDataGenerator()->create_user();
1013          $user4 = self::getDataGenerator()->create_user();
1014  
1015          // The person doing the search.
1016          $this->setUser($user1);
1017  
1018          // Only self-conversation created.
1019          $this->assertCount(1, \core_message\api::get_conversations($user1->id));
1020  
1021          // Create some conversations for user1.
1022          $time = 1;
1023          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1024          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1025          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1026          $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1027  
1028          $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1029          $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1030          $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1031          $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1032  
1033          $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
1034          $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
1035          $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
1036  
1037          // Favourite the all conversations for user1.
1038          $convoids = [];
1039          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1040          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1041          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user4->id]);
1042          $user1context = context_user::instance($user1->id);
1043          $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
1044          foreach ($convoids as $convoid) {
1045              $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
1046          }
1047  
1048          // Consider first conversations is self-conversation.
1049          // Get all records, using offset 0 and large limit.
1050          $this->assertCount(4, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1051  
1052          // Now, get 10 conversations starting at the second record. We should see 2 conversations.
1053          $this->assertCount(3, \core_message\api::get_conversations($user1->id, 1, 10, null, true));
1054  
1055          // Now, try to get favourited conversations using an invalid offset.
1056          $this->assertCount(0, \core_message\api::get_conversations($user1->id, 5, 10, null, true));
1057      }
1058  
1059      /**
1060       * Tests retrieving favourite conversations when a conversation contains a deleted user.
1061       */
1062      public function test_get_favourite_conversations_with_deleted_user() {
1063          // Create some users.
1064          $user1 = self::getDataGenerator()->create_user();
1065          $user2 = self::getDataGenerator()->create_user();
1066          $user3 = self::getDataGenerator()->create_user();
1067  
1068          // Send some messages back and forth, have some different conversations with different users.
1069          $time = 1;
1070          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1071          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1072          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1073          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1074  
1075          $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1076          $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1077          $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1078          $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1079  
1080          // Favourite the all conversations for user1.
1081          $convoids = [];
1082          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1083          $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1084          $user1context = context_user::instance($user1->id);
1085          $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
1086          foreach ($convoids as $convoid) {
1087              $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
1088          }
1089  
1090          // Delete the second user.
1091          delete_user($user2);
1092  
1093          // Retrieve the conversations.
1094          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1095  
1096          // We should have both conversations, despite the other user being soft-deleted.
1097          // Consider first conversations is self-conversation.
1098          $this->assertCount(3, $conversations);
1099  
1100          // Confirm the conversation is from the non-deleted user.
1101          $conversation = reset($conversations);
1102          $this->assertEquals($convoids[1], $conversation->id);
1103      }
1104  
1105      /**
1106       * Test confirming that conversations can be marked as favourites.
1107       */
1108      public function test_set_favourite_conversation() {
1109          // Create some users.
1110          $user1 = self::getDataGenerator()->create_user();
1111          $user2 = self::getDataGenerator()->create_user();
1112          $user3 = self::getDataGenerator()->create_user();
1113  
1114          // Send some messages back and forth, have some different conversations with different users.
1115          $time = 1;
1116          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1117          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1118          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1119          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1120  
1121          $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1122          $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1123          $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1124          $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1125  
1126          // Favourite the first conversation as user 1.
1127          $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1128          $favourite = \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
1129  
1130          // Verify we have two favourite conversations a user 1.
1131          // Consider first conversations is self-conversation.
1132          $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1133  
1134          // Verify we have only one favourite as user2, despite being a member in that conversation.
1135          // Consider first conversations is self-conversation.
1136          $this->assertCount(1, \core_message\api::get_conversations($user2->id, 0, 20, null, true));
1137  
1138          // Try to favourite the same conversation again should just return the existing favourite.
1139          $repeatresult = \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
1140          $this->assertEquals($favourite->id, $repeatresult->id);
1141      }
1142  
1143      /**
1144       * Test verifying that trying to mark a non-existent conversation as a favourite, results in an exception.
1145       */
1146      public function test_set_favourite_conversation_nonexistent_conversation() {
1147          // Create some users.
1148          $user1 = self::getDataGenerator()->create_user();
1149          // Try to favourite a non-existent conversation.
1150          $this->expectException(\moodle_exception::class);
1151          \core_message\api::set_favourite_conversation(0, $user1->id);
1152      }
1153  
1154      /**
1155       * Test verifying that a conversation cannot be marked as favourite unless the user is a member of that conversation.
1156       */
1157      public function test_set_favourite_conversation_non_member() {
1158          // Create some users.
1159          $user1 = self::getDataGenerator()->create_user();
1160          $user2 = self::getDataGenerator()->create_user();
1161          $user3 = self::getDataGenerator()->create_user();
1162  
1163          // Send some messages back and forth, have some different conversations with different users.
1164          $time = 1;
1165          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1166          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1167          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1168          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1169  
1170          $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1171          $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1172          $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1173          $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1174  
1175          // Try to favourite the first conversation as user 3, who is not a member.
1176          $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1177          $this->expectException(\moodle_exception::class);
1178          \core_message\api::set_favourite_conversation($conversationid1, $user3->id);
1179      }
1180  
1181      /**
1182       * Test confirming that those conversations marked as favourites can be unfavourited.
1183       */
1184      public function test_unset_favourite_conversation() {
1185          // Create some users.
1186          $user1 = self::getDataGenerator()->create_user();
1187          $user2 = self::getDataGenerator()->create_user();
1188          $user3 = self::getDataGenerator()->create_user();
1189  
1190          // Send some messages back and forth, have some different conversations with different users.
1191          $time = 1;
1192          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1193          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1194          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1195          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1196  
1197          $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1198          $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1199          $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1200          $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1201  
1202          // Favourite the first conversation as user 1 and the second as user 3.
1203          $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1204          $conversationid2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1205          \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
1206          \core_message\api::set_favourite_conversation($conversationid2, $user3->id);
1207  
1208          // Verify we have two favourite conversations for both user 1 and user 3, counting self conversations.
1209          $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1210          $this->assertCount(2, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
1211  
1212          // Now unfavourite the conversation as user 1.
1213          \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1214  
1215          // Verify we have two favourite conversations user 3 only, and one for user1, counting self conversations.
1216          $this->assertCount(2, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
1217          $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1218  
1219          // Try to favourite the same conversation again as user 1.
1220          $this->expectException(\moodle_exception::class);
1221          \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1222      }
1223  
1224      /**
1225       * Test verifying that a valid conversation cannot be unset as a favourite if it's not marked as a favourite.
1226       */
1227      public function test_unset_favourite_conversation_not_favourite() {
1228          // Create some users.
1229          $user1 = self::getDataGenerator()->create_user();
1230          $user2 = self::getDataGenerator()->create_user();
1231  
1232          // Send some messages back and forth, have some different conversations with different users.
1233          $time = 1;
1234          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1235          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1236          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1237          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1238  
1239          // Now try to unfavourite the conversation as user 1.
1240          $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1241          $this->expectException(\moodle_exception::class);
1242          \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1243      }
1244  
1245      /**
1246       * Test verifying that a non-existent conversation cannot be unset as a favourite.
1247       */
1248      public function test_unset_favourite_conversation_non_existent_conversation() {
1249          // Create some users.
1250          $user1 = self::getDataGenerator()->create_user();
1251  
1252          // Now try to unfavourite the conversation as user 1.
1253          $this->expectException(\moodle_exception::class);
1254          \core_message\api::unset_favourite_conversation(0, $user1->id);
1255      }
1256  
1257      /**
1258       * Helper to seed the database with initial state.
1259       */
1260      protected function create_conversation_test_data() {
1261          // Create some users.
1262          $user1 = self::getDataGenerator()->create_user();
1263          $user2 = self::getDataGenerator()->create_user();
1264          $user3 = self::getDataGenerator()->create_user();
1265          $user4 = self::getDataGenerator()->create_user();
1266  
1267          $time = 1;
1268  
1269          // Create some conversations. We want:
1270          // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message.
1271          // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message.
1272          // 3) At least one of each type (group, individual) of which user1 IS NOT a member.
1273          // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering).
1274          // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member.
1275  
1276          // Individual conversation, user1 is a member, last message from other user.
1277          $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1278              [$user1->id, $user2->id]);
1279          testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time);
1280          testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1);
1281  
1282          // Individual conversation, user1 is a member, last message from user1.
1283          $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1284              [$user1->id, $user3->id]);
1285          testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2);
1286          testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3);
1287  
1288          // Individual conversation, user1 is not a member.
1289          $ic3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1290              [$user2->id, $user3->id]);
1291          testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4);
1292          testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5);
1293  
1294          // Group conversation, user1 is not a member.
1295          $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1296              [$user2->id, $user3->id, $user4->id], 'Project discussions');
1297          testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6);
1298          testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7);
1299  
1300          // Group conversation, user1 is a member, last message from another user.
1301          $gc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1302              [$user1->id, $user3->id, $user4->id], 'Group chat');
1303          testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8);
1304          testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9);
1305          testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10);
1306  
1307          // Group conversation, user1 is a member, last message from user1.
1308          $gc3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1309              [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!');
1310          testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11);
1311          testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12);
1312          testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13);
1313  
1314          // Empty group conversations (x2), user1 is a member.
1315          $gc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1316              [$user1->id, $user2->id, $user3->id], 'Empty group');
1317          $gc5 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1318              [$user1->id, $user2->id, $user4->id], 'Another empty group');
1319  
1320          // Empty group conversation, user1 is NOT a member.
1321          $gc6 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1322              [$user2->id, $user3->id, $user4->id], 'Empty group 3');
1323  
1324          return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6];
1325      }
1326  
1327      /**
1328       * Test verifying get_conversations when no limits, offsets, type filters or favourite restrictions are used.
1329       */
1330      public function test_get_conversations_no_restrictions() {
1331          global $DB;
1332  
1333          $user1 = self::getDataGenerator()->create_user();
1334          // Self-conversation should exists.
1335          $this->assertCount(1, \core_message\api::get_conversations($user1->id));
1336  
1337          // Get a bunch of conversations, some group, some individual and in different states.
1338          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1339              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1340  
1341          // Get all conversations for user1.
1342          $conversations = core_message\api::get_conversations($user1->id);
1343  
1344          // Verify there are 2 individual conversation, 2 group conversations, 2 empty group conversations,
1345          // and a self-conversation.
1346          // The conversations with the most recent messages should be listed first, followed by the empty
1347          // conversations, with the most recently created first.
1348          $this->assertCount(7, $conversations);
1349          $typecounts  = array_count_values(array_column($conversations, 'type'));
1350          $this->assertEquals(2, $typecounts[1]);
1351          $this->assertEquals(4, $typecounts[2]);
1352          $this->assertEquals(1, $typecounts[3]);
1353  
1354          // Those conversations having messages should be listed after self-conversation, ordered by most recent message time.
1355          $this->assertEquals($gc3->id, $conversations[0]->id);
1356          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[0]->type);
1357          $this->assertFalse($conversations[1]->isfavourite);
1358          $this->assertCount(1, $conversations[0]->members);
1359          $this->assertEquals(4, $conversations[0]->membercount);
1360          $this->assertCount(1, $conversations[0]->messages);
1361          $message = $DB->get_record('messages', ['id' => $conversations[0]->messages[0]->id]);
1362          $expectedmessagetext = message_format_message_text($message);
1363          $this->assertEquals($expectedmessagetext, $conversations[0]->messages[0]->text);
1364          $this->assertEquals($user1->id, $conversations[0]->messages[0]->useridfrom);
1365  
1366          $this->assertEquals($gc2->id, $conversations[1]->id);
1367          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[1]->type);
1368          $this->assertFalse($conversations[1]->isfavourite);
1369          $this->assertCount(1, $conversations[1]->members);
1370          $this->assertEquals(3, $conversations[1]->membercount);
1371          $this->assertCount(1, $conversations[1]->messages);
1372          $message = $DB->get_record('messages', ['id' => $conversations[1]->messages[0]->id]);
1373          $expectedmessagetext = message_format_message_text($message);
1374          $this->assertEquals($expectedmessagetext, $conversations[1]->messages[0]->text);
1375          $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1376  
1377          $this->assertEquals($ic2->id, $conversations[2]->id);
1378          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[2]->type);
1379          $this->assertFalse($conversations[2]->isfavourite);
1380          $this->assertCount(1, $conversations[2]->members);
1381          $this->assertEquals($user3->id, $conversations[2]->members[$user3->id]->id);
1382          $this->assertEquals(2, $conversations[2]->membercount);
1383          $this->assertCount(1, $conversations[2]->messages);
1384          $message = $DB->get_record('messages', ['id' => $conversations[2]->messages[0]->id]);
1385          $expectedmessagetext = message_format_message_text($message);
1386          $this->assertEquals($expectedmessagetext, $conversations[2]->messages[0]->text);
1387          $this->assertEquals($user1->id, $conversations[2]->messages[0]->useridfrom);
1388  
1389          $this->assertEquals($ic1->id, $conversations[3]->id);
1390          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[3]->type);
1391          $this->assertFalse($conversations[3]->isfavourite);
1392          $this->assertCount(1, $conversations[3]->members);
1393          $this->assertEquals(2, $conversations[3]->membercount);
1394          $this->assertCount(1, $conversations[3]->messages);
1395          $message = $DB->get_record('messages', ['id' => $conversations[3]->messages[0]->id]);
1396          $expectedmessagetext = message_format_message_text($message);
1397          $this->assertEquals($expectedmessagetext, $conversations[3]->messages[0]->text);
1398          $this->assertEquals($user2->id, $conversations[3]->messages[0]->useridfrom);
1399  
1400          // Of the groups without messages, we expect to see the most recently created first.
1401          $this->assertEquals($gc5->id, $conversations[4]->id);
1402          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[4]->type);
1403          $this->assertFalse($conversations[4]->isfavourite);
1404          $this->assertCount(0, $conversations[4]->members); // No members returned, because no recent messages exist.
1405          $this->assertEquals(3, $conversations[4]->membercount);
1406          $this->assertEmpty($conversations[4]->messages);
1407  
1408          $this->assertEquals($gc4->id, $conversations[5]->id);
1409          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[5]->type);
1410          $this->assertFalse($conversations[5]->isfavourite);
1411          $this->assertCount(0, $conversations[5]->members);
1412          $this->assertEquals(3, $conversations[5]->membercount);
1413          $this->assertEmpty($conversations[5]->messages);
1414  
1415          // Verify format of the return structure.
1416          foreach ($conversations as $conv) {
1417              $this->assertObjectHasAttribute('id', $conv);
1418              $this->assertObjectHasAttribute('name', $conv);
1419              $this->assertObjectHasAttribute('subname', $conv);
1420              $this->assertObjectHasAttribute('imageurl', $conv);
1421              $this->assertObjectHasAttribute('type', $conv);
1422              $this->assertObjectHasAttribute('isfavourite', $conv);
1423              $this->assertObjectHasAttribute('membercount', $conv);
1424              $this->assertObjectHasAttribute('isread', $conv);
1425              $this->assertObjectHasAttribute('unreadcount', $conv);
1426              $this->assertObjectHasAttribute('members', $conv);
1427              foreach ($conv->members as $member) {
1428                  $this->assertObjectHasAttribute('id', $member);
1429                  $this->assertObjectHasAttribute('fullname', $member);
1430                  $this->assertObjectHasAttribute('profileimageurl', $member);
1431                  $this->assertObjectHasAttribute('profileimageurlsmall', $member);
1432                  $this->assertObjectHasAttribute('isonline', $member);
1433                  $this->assertObjectHasAttribute('showonlinestatus', $member);
1434                  $this->assertObjectHasAttribute('isblocked', $member);
1435                  $this->assertObjectHasAttribute('iscontact', $member);
1436                  $this->assertObjectHasAttribute('isdeleted', $member);
1437                  $this->assertObjectHasAttribute('canmessage', $member);
1438                  $this->assertObjectHasAttribute('requirescontact', $member);
1439                  $this->assertObjectHasAttribute('contactrequests', $member);
1440              }
1441              $this->assertObjectHasAttribute('messages', $conv);
1442              foreach ($conv->messages as $message) {
1443                  $this->assertObjectHasAttribute('id', $message);
1444                  $this->assertObjectHasAttribute('useridfrom', $message);
1445                  $this->assertObjectHasAttribute('text', $message);
1446                  $this->assertObjectHasAttribute('timecreated', $message);
1447              }
1448          }
1449      }
1450  
1451      /**
1452       * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately.
1453       */
1454      public function test_get_conversations_message_format() {
1455          global $DB;
1456          // Create some users.
1457          $user1 = self::getDataGenerator()->create_user();
1458          $user2 = self::getDataGenerator()->create_user();
1459  
1460          // Create conversation.
1461          $conversation = \core_message\api::create_conversation(
1462              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1463              [$user1->id, $user2->id]
1464          );
1465  
1466          // Send some messages back and forth.
1467          $time = 1;
1468          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1);
1469          $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2);
1470  
1471          // Verify the format of the html message.
1472          $message = $DB->get_record('messages', ['id' => $mid]);
1473          $expectedmessagetext = message_format_message_text($message);
1474          $conversations = \core_message\api::get_conversations($user1->id);
1475          $messages = $conversations[0]->messages;
1476          $this->assertEquals($expectedmessagetext, $messages[0]->text);
1477      }
1478  
1479      /**
1480       * Test verifying get_conversations identifies if a conversation is muted or not.
1481       */
1482      public function test_get_conversations_some_muted() {
1483          // Create some users.
1484          $user1 = self::getDataGenerator()->create_user();
1485          $user2 = self::getDataGenerator()->create_user();
1486          $user3 = self::getDataGenerator()->create_user();
1487  
1488          $conversation1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1489              [$user1->id, $user2->id]);
1490          testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'Message 1');
1491          testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'Message 2');
1492          \core_message\api::mute_conversation($user1->id, $conversation1->id);
1493  
1494          $conversation2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1495              [$user1->id, $user3->id]);
1496          testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Message 1');
1497          testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Message 2');
1498  
1499          $conversation3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1500              [$user1->id, $user2->id]);
1501          \core_message\api::mute_conversation($user1->id, $conversation3->id);
1502  
1503          $conversation4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1504              [$user1->id, $user3->id]);
1505  
1506          $conversations = \core_message\api::get_conversations($user1->id);
1507  
1508          usort($conversations, function($first, $second){
1509              return $first->id > $second->id;
1510          });
1511  
1512          // Consider first conversations is self-conversation.
1513          $selfconversation = array_shift($conversations);
1514          $conv1 = array_shift($conversations);
1515          $conv2 = array_shift($conversations);
1516          $conv3 = array_shift($conversations);
1517          $conv4 = array_shift($conversations);
1518  
1519          $this->assertTrue($conv1->ismuted);
1520          $this->assertFalse($conv2->ismuted);
1521          $this->assertTrue($conv3->ismuted);
1522          $this->assertFalse($conv4->ismuted);
1523      }
1524  
1525      /**
1526       * Tests retrieving conversations with a limit and offset to ensure pagination works correctly.
1527       */
1528      public function test_get_conversations_limit_offset() {
1529          // Get a bunch of conversations, some group, some individual and in different states.
1530          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1531              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1532  
1533          // Get all conversations for user1, limited to 1 result.
1534          $conversations = core_message\api::get_conversations($user1->id, 0, 1);
1535  
1536          // Verify the first conversation.
1537          $this->assertCount(1, $conversations);
1538          $conversation = array_shift($conversations);
1539          $this->assertEquals($conversation->id, $gc3->id);
1540  
1541          // Verify the next conversation.
1542          $conversations = \core_message\api::get_conversations($user1->id, 1, 1);
1543          $this->assertCount(1, $conversations);
1544          $this->assertEquals($gc2->id, $conversations[0]->id);
1545  
1546          // Verify the next conversation.
1547          $conversations = \core_message\api::get_conversations($user1->id, 2, 1);
1548          $this->assertCount(1, $conversations);
1549          $this->assertEquals($ic2->id, $conversations[0]->id);
1550  
1551          // Skip one and get both empty conversations.
1552          $conversations = \core_message\api::get_conversations($user1->id, 4, 2);
1553          $this->assertCount(2, $conversations);
1554          $this->assertEquals($gc5->id, $conversations[0]->id);
1555          $this->assertEmpty($conversations[0]->messages);
1556          $this->assertEquals($gc4->id, $conversations[1]->id);
1557          $this->assertEmpty($conversations[1]->messages);
1558  
1559          // Ask for an offset that doesn't exist and verify no conversations are returned.
1560          $conversations = \core_message\api::get_conversations($user1->id, 10, 1);
1561          $this->assertCount(0, $conversations);
1562      }
1563  
1564      /**
1565       * Test verifying the type filtering behaviour of the
1566       */
1567      public function test_get_conversations_type_filter() {
1568          // Get a bunch of conversations, some group, some individual and in different states.
1569          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1570              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1571  
1572          // Verify we can ask for only individual conversations.
1573          $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1574              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1575          $this->assertCount(2, $conversations);
1576  
1577          // Verify we can ask for only group conversations.
1578          $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1579              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP);
1580          $this->assertCount(4, $conversations);
1581  
1582          // Verify an exception is thrown if an unrecognized type is specified.
1583          $this->expectException(\moodle_exception::class);
1584          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 0);
1585      }
1586  
1587      /**
1588       * Tests retrieving conversations when a 'self' conversation exists.
1589       */
1590      public function test_get_conversations_self_conversations() {
1591          global $DB;
1592  
1593          // Create a conversation between one user and themself.
1594          $user1 = self::getDataGenerator()->create_user();
1595          $user2 = self::getDataGenerator()->create_user();
1596          $user3 = self::getDataGenerator()->create_user();
1597          $user4 = self::getDataGenerator()->create_user();
1598  
1599          // Create some individual conversations.
1600          $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1601              [$user1->id, $user2->id]);
1602          $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1603              [$user1->id, $user3->id]);
1604          testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message from user1 to user2');
1605  
1606          // Get some self-conversations.
1607          $sc1 = \core_message\api::get_self_conversation($user1->id);
1608          $sc4 = \core_message\api::get_self_conversation($user4->id);
1609          testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Test message to self 1!');
1610  
1611          // Verify we are in a 'self' conversation state.
1612          $members = $DB->get_records('message_conversation_members', ['conversationid' => $sc1->id]);
1613          $this->assertCount(1, $members);
1614          $member = array_pop($members);
1615          $this->assertEquals($user1->id, $member->userid);
1616  
1617          // Verify the self-conversations are returned by the method.
1618          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF);
1619          $this->assertCount(1, $conversations);
1620          $conversation = array_pop($conversations);
1621          $this->assertEquals($conversation->id, $sc1->id);
1622  
1623          $conversations = \core_message\api::get_conversations($user4->id);
1624          // The self-conversation.
1625          $this->assertCount(1, $conversations);
1626  
1627          // Get only private conversations for user1 (empty conversations, like $ic2, are not returned).
1628          $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1629              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1630          $this->assertCount(1, $conversations);
1631  
1632          // Merge self with private conversations for user1.
1633          $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1634              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
1635          $this->assertCount(2, $conversations);
1636  
1637          // Get only private conversations for user2.
1638          $conversations = \core_message\api::get_conversations($user2->id, 0, 20,
1639              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1640          $this->assertCount(1, $conversations);
1641  
1642          // Merge self with private conversations for user2.
1643          $conversations = \core_message\api::get_conversations($user2->id, 0, 20,
1644              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
1645          $this->assertCount(2, $conversations);
1646      }
1647  
1648      /**
1649       * Tests retrieving conversations when a conversation contains a deleted user.
1650       */
1651      public function test_get_conversations_with_deleted_user() {
1652          // Get a bunch of conversations, some group, some individual and in different states.
1653          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1654              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1655  
1656          // Delete the second user and retrieve the conversations.
1657          // We should have 6 still, as conversations with soft-deleted users are still returned.
1658          // Group conversations are also present, albeit with less members.
1659          delete_user($user2);
1660          // This is to confirm an exception is not thrown when a user AND the user context is deleted.
1661          // We no longer delete the user context, but historically we did.
1662          context_helper::delete_instance(CONTEXT_USER, $user2->id);
1663          $conversations = \core_message\api::get_conversations($user1->id);
1664          // Consider there's a self-conversation (the last one).
1665          $this->assertCount(7, $conversations);
1666          $this->assertEquals($gc3->id, $conversations[0]->id);
1667          $this->assertcount(1, $conversations[0]->members);
1668          $this->assertEquals($gc2->id, $conversations[1]->id);
1669          $this->assertcount(1, $conversations[1]->members);
1670          $this->assertEquals($ic2->id, $conversations[2]->id);
1671          $this->assertEquals($ic1->id, $conversations[3]->id);
1672          $this->assertEquals($gc5->id, $conversations[4]->id);
1673          $this->assertEquals($gc4->id, $conversations[5]->id);
1674  
1675          // Delete a user from a group conversation where that user had sent the most recent message.
1676          // This user will still be present in the members array, as will the message in the messages array.
1677          delete_user($user4);
1678          $conversations = \core_message\api::get_conversations($user1->id);
1679  
1680          // Consider there's a self-conversation (the last one).
1681          $this->assertCount(7, $conversations);
1682          $this->assertEquals($gc2->id, $conversations[1]->id);
1683          $this->assertcount(1, $conversations[1]->members);
1684          $this->assertEquals($user4->id, $conversations[1]->members[$user4->id]->id);
1685          $this->assertcount(1, $conversations[1]->messages);
1686          $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1687  
1688          // Delete the third user and retrieve the conversations.
1689          // We should have 6 still, as conversations with soft-deleted users are still returned.
1690          // Group conversations are also present, albeit with less members.
1691          delete_user($user3);
1692          $conversations = \core_message\api::get_conversations($user1->id);
1693          // Consider there's a self-conversation (the last one).
1694          $this->assertCount(7, $conversations);
1695          $this->assertEquals($gc3->id, $conversations[0]->id);
1696          $this->assertcount(1, $conversations[0]->members);
1697          $this->assertEquals($gc2->id, $conversations[1]->id);
1698          $this->assertcount(1, $conversations[1]->members);
1699          $this->assertEquals($ic2->id, $conversations[2]->id);
1700          $this->assertEquals($ic1->id, $conversations[3]->id);
1701          $this->assertEquals($gc5->id, $conversations[4]->id);
1702          $this->assertEquals($gc4->id, $conversations[5]->id);
1703      }
1704  
1705      /**
1706       * Test confirming the behaviour of get_conversations() when users delete all messages.
1707       */
1708      public function test_get_conversations_deleted_messages() {
1709          // Get a bunch of conversations, some group, some individual and in different states.
1710          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1711              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1712  
1713          $conversations = \core_message\api::get_conversations($user1->id);
1714          // Consider first conversations is self-conversation.
1715          $this->assertCount(7, $conversations);
1716  
1717          // Delete all messages from a group conversation the user is in - it should be returned.
1718          $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $gc2->id));
1719          $convmessages = \core_message\api::get_conversation_messages($user1->id, $gc2->id);
1720          $messages = $convmessages['messages'];
1721          foreach ($messages as $message) {
1722              \core_message\api::delete_message($user1->id, $message->id);
1723          }
1724          $conversations = \core_message\api::get_conversations($user1->id);
1725          // Consider first conversations is self-conversation.
1726          $this->assertCount(7, $conversations);
1727          $this->assertContains($gc2->id, array_column($conversations, 'id'));
1728  
1729          // Delete all messages from an individual conversation the user is in - it should not be returned.
1730          $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $ic1->id));
1731          $convmessages = \core_message\api::get_conversation_messages($user1->id, $ic1->id);
1732          $messages = $convmessages['messages'];
1733          foreach ($messages as $message) {
1734              \core_message\api::delete_message($user1->id, $message->id);
1735          }
1736          $conversations = \core_message\api::get_conversations($user1->id);
1737          // Consider first conversations is self-conversation.
1738          $this->assertCount(6, $conversations);
1739          $this->assertNotContains($ic1->id, array_column($conversations, 'id'));
1740      }
1741  
1742      /**
1743       * Test verifying the behaviour of get_conversations() when fetching favourite conversations with only a single
1744       * favourite.
1745       */
1746      public function test_get_conversations_favourite_conversations_single() {
1747          // Get a bunch of conversations, some group, some individual and in different states.
1748          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1749              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1750  
1751          // Mark a single conversation as favourites.
1752          \core_message\api::set_favourite_conversation($ic2->id, $user1->id);
1753  
1754          // Get the conversation, first with no restrictions, confirming the favourite status of the conversations.
1755          $conversations = \core_message\api::get_conversations($user1->id);
1756          // Consider there is a self-conversation.
1757          $selfconversation = \core_message\api::get_self_conversation($user1->id);
1758          $this->assertCount(7, $conversations);
1759          foreach ($conversations as $conv) {
1760              if (in_array($conv->id, [$ic2->id, $selfconversation->id])) {
1761                  $this->assertTrue($conv->isfavourite);
1762              } else {
1763                  $this->assertFalse($conv->isfavourite);
1764              }
1765          }
1766  
1767          // Now, get ONLY favourite conversations (including self-conversation).
1768          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1769          $this->assertCount(2, $conversations);
1770          foreach ($conversations as $conv) {
1771              if ($conv->type != \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) {
1772                  $this->assertTrue($conv->isfavourite);
1773                  $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conv->type);
1774                  $this->assertEquals($ic2->id, $conv->id);
1775              }
1776          }
1777  
1778          // Now, try ONLY favourites of type 'group'.
1779          $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1780              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1781          $this->assertEmpty($conversations);
1782  
1783          // And NO favourite conversations.
1784          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1785          $this->assertCount(5, $conversations);
1786          foreach ($conversations as $conv) {
1787              $this->assertFalse($conv->isfavourite);
1788              $this->assertNotEquals($ic2, $conv->id);
1789          }
1790      }
1791  
1792      /**
1793       * Test verifying the behaviour of get_conversations() when fetching favourite conversations.
1794       */
1795      public function test_get_conversations_favourite_conversations() {
1796          // Get a bunch of conversations, some group, some individual and in different states.
1797          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1798              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1799  
1800          // Try to get ONLY favourite conversations, when only self-conversation exist.
1801          $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1802  
1803          // Unstar self-conversation.
1804          $selfconversation = \core_message\api::get_self_conversation($user1->id);
1805          \core_message\api::unset_favourite_conversation($selfconversation->id, $user1->id);
1806  
1807          // Try to get ONLY favourite conversations, when no favourites exist.
1808          $this->assertEquals([], \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1809  
1810          // Try to get NO favourite conversations, when no favourites exist.
1811          $this->assertCount(7, \core_message\api::get_conversations($user1->id, 0, 20, null, false));
1812  
1813          // Mark a few conversations as favourites.
1814          \core_message\api::set_favourite_conversation($ic1->id, $user1->id);
1815          \core_message\api::set_favourite_conversation($gc2->id, $user1->id);
1816          \core_message\api::set_favourite_conversation($gc5->id, $user1->id);
1817          $favouriteids = [$ic1->id, $gc2->id, $gc5->id];
1818  
1819          // Get the conversations, first with no restrictions, confirming the favourite status of the conversations.
1820          $conversations = \core_message\api::get_conversations($user1->id);
1821          $this->assertCount(7, $conversations);
1822          foreach ($conversations as $conv) {
1823              if (in_array($conv->id, $favouriteids)) {
1824                  $this->assertTrue($conv->isfavourite);
1825              } else {
1826                  $this->assertFalse($conv->isfavourite);
1827              }
1828          }
1829  
1830          // Now, get ONLY favourite conversations.
1831          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1832          $this->assertCount(3, $conversations);
1833          foreach ($conversations as $conv) {
1834              $this->assertTrue($conv->isfavourite);
1835              $this->assertNotFalse(array_search($conv->id, $favouriteids));
1836          }
1837  
1838          // Now, try ONLY favourites of type 'group'.
1839          $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1840              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1841          $this->assertCount(2, $conversations);
1842          foreach ($conversations as $conv) {
1843              $this->assertTrue($conv->isfavourite);
1844              $this->assertNotFalse(array_search($conv->id, [$gc2->id, $gc5->id]));
1845          }
1846  
1847          // And NO favourite conversations.
1848          $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1849          $this->assertCount(4, $conversations);
1850          foreach ($conversations as $conv) {
1851              $this->assertFalse($conv->isfavourite);
1852              $this->assertFalse(array_search($conv->id, $favouriteids));
1853          }
1854      }
1855  
1856      /**
1857       * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this
1858       * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want
1859       * to confirm this happens.
1860       */
1861      public function test_get_conversations_user_in_group_and_individual_chat() {
1862          $this->resetAfterTest();
1863  
1864          $user1 = self::getDataGenerator()->create_user();
1865          $user2 = self::getDataGenerator()->create_user();
1866          $user3 = self::getDataGenerator()->create_user();
1867  
1868          $conversation = \core_message\api::create_conversation(
1869              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1870              [
1871                  $user1->id,
1872                  $user2->id
1873              ],
1874              'Individual conversation'
1875          );
1876  
1877          testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1878  
1879          $conversation = \core_message\api::create_conversation(
1880              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1881              [
1882                  $user1->id,
1883                  $user2->id,
1884              ],
1885              'Group conversation'
1886          );
1887  
1888          testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1889  
1890          \core_message\api::create_contact_request($user1->id, $user2->id);
1891          \core_message\api::create_contact_request($user1->id, $user3->id);
1892  
1893          $conversations = \core_message\api::get_conversations($user2->id);
1894  
1895          $groupconversation = array_shift($conversations);
1896          $individualconversation = array_shift($conversations);
1897  
1898          $this->assertEquals('Group conversation', $groupconversation->name);
1899          $this->assertEquals('Individual conversation', $individualconversation->name);
1900  
1901          $this->assertCount(1, $groupconversation->members);
1902          $this->assertCount(1, $individualconversation->members);
1903  
1904          $groupmember = reset($groupconversation->members);
1905          $this->assertNull($groupmember->requirescontact);
1906          $this->assertNull($groupmember->canmessage);
1907          $this->assertEmpty($groupmember->contactrequests);
1908  
1909          $individualmember = reset($individualconversation->members);
1910          $this->assertNotNull($individualmember->requirescontact);
1911          $this->assertNotNull($individualmember->canmessage);
1912          $this->assertNotEmpty($individualmember->contactrequests);
1913      }
1914  
1915      /**
1916       * Test verifying that group linked conversations are returned and contain a subname matching the course name.
1917       */
1918      public function test_get_conversations_group_linked() {
1919          global $CFG, $DB;
1920  
1921          // Create some users.
1922          $user1 = self::getDataGenerator()->create_user();
1923          $user2 = self::getDataGenerator()->create_user();
1924          $user3 = self::getDataGenerator()->create_user();
1925  
1926          $course1 = $this->getDataGenerator()->create_course();
1927  
1928          // Create a group with a linked conversation and a valid image.
1929          $this->setAdminUser();
1930          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1931          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1932          $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
1933          $group1 = $this->getDataGenerator()->create_group([
1934              'courseid' => $course1->id,
1935              'enablemessaging' => 1,
1936              'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
1937          ]);
1938  
1939          // Add users to group1.
1940          $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1941          $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
1942  
1943          // Verify the group with the image works as expected.
1944          $conversations = \core_message\api::get_conversations($user1->id);
1945          $this->assertEquals(2, $conversations[0]->membercount);
1946          $this->assertEquals($course1->shortname, $conversations[0]->subname);
1947          $groupimageurl = get_group_picture_url($group1, $group1->courseid, true);
1948          $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1949  
1950          // Create a group with a linked conversation and without any image.
1951          $group2 = $this->getDataGenerator()->create_group([
1952              'courseid' => $course1->id,
1953              'enablemessaging' => 1,
1954          ]);
1955  
1956          // Add users to group2.
1957          $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1958          $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id));
1959  
1960          // Verify the group without any image works as expected too.
1961          $conversations = \core_message\api::get_conversations($user3->id);
1962          // Consider first conversations is self-conversation.
1963          $this->assertEquals(2, $conversations[0]->membercount);
1964          $this->assertEquals($course1->shortname, $conversations[0]->subname);
1965          $this->assertEquals('https://www.example.com/moodle/theme/image.php/_s/boost/core/1/g/g1', $conversations[0]->imageurl);
1966  
1967          // Now, disable the conversation linked to the group and verify it's no longer returned.
1968          $DB->set_field('message_conversations', 'enabled', 0, ['id' => $conversations[0]->id]);
1969          $conversations = \core_message\api::get_conversations($user3->id);
1970          $this->assertCount(1, $conversations);
1971      }
1972  
1973     /**
1974      * The data provider for get_conversations_mixed.
1975      *
1976      * This provides sets of data to for testing.
1977      * @return array
1978      */
1979     public function get_conversations_mixed_provider() {
1980         return array(
1981              'Test that conversations with messages contacts is correctly ordered.' => array(
1982                  'users' => array(
1983                      'user1',
1984                      'user2',
1985                      'user3',
1986                  ),
1987                  'contacts' => array(
1988                  ),
1989                  'messages' => array(
1990                      array(
1991                          'from'          => 'user1',
1992                          'to'            => 'user2',
1993                          'state'         => 'unread',
1994                          'subject'       => 'S1',
1995                      ),
1996                      array(
1997                          'from'          => 'user2',
1998                          'to'            => 'user1',
1999                          'state'         => 'unread',
2000                          'subject'       => 'S2',
2001                      ),
2002                      array(
2003                          'from'          => 'user1',
2004                          'to'            => 'user2',
2005                          'state'         => 'unread',
2006                          'timecreated'   => 0,
2007                          'subject'       => 'S3',
2008                      ),
2009                      array(
2010                          'from'          => 'user1',
2011                          'to'            => 'user3',
2012                          'state'         => 'read',
2013                          'timemodifier'  => 1,
2014                          'subject'       => 'S4',
2015                      ),
2016                      array(
2017                          'from'          => 'user3',
2018                          'to'            => 'user1',
2019                          'state'         => 'read',
2020                          'timemodifier'  => 1,
2021                          'subject'       => 'S5',
2022                      ),
2023                      array(
2024                          'from'          => 'user1',
2025                          'to'            => 'user3',
2026                          'state'         => 'read',
2027                          'timecreated'   => 0,
2028                          'subject'       => 'S6',
2029                      ),
2030                  ),
2031                  'expectations' => array(
2032                      'user1' => array(
2033                          // User1 has conversed most recently with user3. The most recent message is M5.
2034                          array(
2035                              'messageposition'   => 0,
2036                              'with'              => 'user3',
2037                              'subject'           => '<p>S5</p>',
2038                              'unreadcount'       => 0,
2039                          ),
2040                          // User1 has also conversed with user2. The most recent message is S2.
2041                          array(
2042                              'messageposition'   => 1,
2043                              'with'              => 'user2',
2044                              'subject'           => '<p>S2</p>',
2045                              'unreadcount'       => 1,
2046                          ),
2047                      ),
2048                      'user2' => array(
2049                          // User2 has only conversed with user1. Their most recent shared message was S2.
2050                          array(
2051                              'messageposition'   => 0,
2052                              'with'              => 'user1',
2053                              'subject'           => '<p>S2</p>',
2054                              'unreadcount'       => 2,
2055                          ),
2056                      ),
2057                      'user3' => array(
2058                          // User3 has only conversed with user1. Their most recent shared message was S5.
2059                          array(
2060                              'messageposition'   => 0,
2061                              'with'              => 'user1',
2062                              'subject'           => '<p>S5</p>',
2063                              'unreadcount'       => 0,
2064                          ),
2065                      ),
2066                  ),
2067              ),
2068              'Test conversations with a single user, where some messages are read and some are not.' => array(
2069                  'users' => array(
2070                      'user1',
2071                      'user2',
2072                  ),
2073                  'contacts' => array(
2074                  ),
2075                  'messages' => array(
2076                      array(
2077                          'from'          => 'user1',
2078                          'to'            => 'user2',
2079                          'state'         => 'read',
2080                          'subject'       => 'S1',
2081                      ),
2082                      array(
2083                          'from'          => 'user2',
2084                          'to'            => 'user1',
2085                          'state'         => 'read',
2086                          'subject'       => 'S2',
2087                      ),
2088                      array(
2089                          'from'          => 'user1',
2090                          'to'            => 'user2',
2091                          'state'         => 'unread',
2092                          'timemodifier'  => 1,
2093                          'subject'       => 'S3',
2094                      ),
2095                      array(
2096                          'from'          => 'user1',
2097                          'to'            => 'user2',
2098                          'state'         => 'unread',
2099                          'timemodifier'  => 1,
2100                          'subject'       => 'S4',
2101                      ),
2102                  ),
2103                  'expectations' => array(
2104                      // The most recent message between user1 and user2 was S4.
2105                      'user1' => array(
2106                          array(
2107                              'messageposition'   => 0,
2108                              'with'              => 'user2',
2109                              'subject'           => '<p>S4</p>',
2110                              'unreadcount'       => 0,
2111                          ),
2112                      ),
2113                      'user2' => array(
2114                          // The most recent message between user1 and user2 was S4.
2115                          array(
2116                              'messageposition'   => 0,
2117                              'with'              => 'user1',
2118                              'subject'           => '<p>S4</p>',
2119                              'unreadcount'       => 2,
2120                          ),
2121                      ),
2122                  ),
2123              ),
2124              'Test conversations with a single user, where some messages are read and some are not, and messages ' .
2125              'are out of order' => array(
2126              // This can happen through a combination of factors including multi-master DB replication with messages
2127              // read somehow (e.g. API).
2128                  'users' => array(
2129                      'user1',
2130                      'user2',
2131                  ),
2132                  'contacts' => array(
2133                  ),
2134                  'messages' => array(
2135                      array(
2136                          'from'          => 'user1',
2137                          'to'            => 'user2',
2138                          'state'         => 'read',
2139                          'subject'       => 'S1',
2140                          'timemodifier'  => 1,
2141                      ),
2142                      array(
2143                          'from'          => 'user2',
2144                          'to'            => 'user1',
2145                          'state'         => 'read',
2146                          'subject'       => 'S2',
2147                          'timemodifier'  => 2,
2148                      ),
2149                      array(
2150                          'from'          => 'user1',
2151                          'to'            => 'user2',
2152                          'state'         => 'unread',
2153                          'subject'       => 'S3',
2154                      ),
2155                      array(
2156                          'from'          => 'user1',
2157                          'to'            => 'user2',
2158                          'state'         => 'unread',
2159                          'subject'       => 'S4',
2160                      ),
2161                  ),
2162                  'expectations' => array(
2163                      // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
2164                      'user1' => array(
2165                          array(
2166                              'messageposition'   => 0,
2167                              'with'              => 'user2',
2168                              'subject'           => '<p>S2</p>',
2169                              'unreadcount'       => 0,
2170                          ),
2171                      ),
2172                      'user2' => array(
2173                          array(
2174                              'messageposition'   => 0,
2175                              'with'              => 'user1',
2176                              'subject'           => '<p>S2</p>',
2177                              'unreadcount'       => 2
2178                          ),
2179                      ),
2180                  ),
2181              ),
2182              'Test unread message count is correct for both users' => array(
2183                  'users' => array(
2184                      'user1',
2185                      'user2',
2186                  ),
2187                  'contacts' => array(
2188                  ),
2189                  'messages' => array(
2190                      array(
2191                          'from'          => 'user1',
2192                          'to'            => 'user2',
2193                          'state'         => 'read',
2194                          'subject'       => 'S1',
2195                          'timemodifier'  => 1,
2196                      ),
2197                      array(
2198                          'from'          => 'user2',
2199                          'to'            => 'user1',
2200                          'state'         => 'read',
2201                          'subject'       => 'S2',
2202                          'timemodifier'  => 2,
2203                      ),
2204                      array(
2205                          'from'          => 'user1',
2206                          'to'            => 'user2',
2207                          'state'         => 'read',
2208                          'subject'       => 'S3',
2209                          'timemodifier'  => 3,
2210                      ),
2211                      array(
2212                          'from'          => 'user1',
2213                          'to'            => 'user2',
2214                          'state'         => 'read',
2215                          'subject'       => 'S4',
2216                          'timemodifier'  => 4,
2217                      ),
2218                      array(
2219                          'from'          => 'user1',
2220                          'to'            => 'user2',
2221                          'state'         => 'unread',
2222                          'subject'       => 'S5',
2223                          'timemodifier'  => 5,
2224                      ),
2225                      array(
2226                          'from'          => 'user2',
2227                          'to'            => 'user1',
2228                          'state'         => 'unread',
2229                          'subject'       => 'S6',
2230                          'timemodifier'  => 6,
2231                      ),
2232                      array(
2233                          'from'          => 'user1',
2234                          'to'            => 'user2',
2235                          'state'         => 'unread',
2236                          'subject'       => 'S7',
2237                          'timemodifier'  => 7,
2238                      ),
2239                      array(
2240                          'from'          => 'user1',
2241                          'to'            => 'user2',
2242                          'state'         => 'unread',
2243                          'subject'       => 'S8',
2244                          'timemodifier'  => 8,
2245                      ),
2246                  ),
2247                  'expectations' => array(
2248                      // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
2249                      'user1' => array(
2250                          array(
2251                              'messageposition'   => 0,
2252                              'with'              => 'user2',
2253                              'subject'           => '<p>S8</p>',
2254                              'unreadcount'       => 1,
2255                          ),
2256                      ),
2257                      'user2' => array(
2258                          array(
2259                              'messageposition'   => 0,
2260                              'with'              => 'user1',
2261                              'subject'           => '<p>S8</p>',
2262                              'unreadcount'       => 3,
2263                          ),
2264                      ),
2265                  ),
2266              ),
2267          );
2268      }
2269  
2270      /**
2271       * Test that creation can't create the same conversation twice for 1:1 conversations.
2272       */
2273      public function test_create_conversation_duplicate_conversations() {
2274          global $DB;
2275          $user1 = $this::getDataGenerator()->create_user();
2276  
2277          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2278          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2279  
2280          $convhash = \core_message\helper::get_conversation_hash([$user1->id]);
2281          $countconversations = $DB->count_records('message_conversations', ['convhash' => $convhash]);
2282          $this->assertEquals(1, $countconversations);
2283          $this->assertNotEmpty($conversation = \core_message\api::get_self_conversation($user1->id));
2284      }
2285  
2286      /**
2287       * Test get_conversations with a mixture of messages.
2288       *
2289       * @dataProvider get_conversations_mixed_provider
2290       * @param array $usersdata The list of users to create for this test.
2291       * @param array $messagesdata The list of messages to create.
2292       * @param array $expectations The list of expected outcomes.
2293       */
2294      public function test_get_conversations_mixed($usersdata, $contacts, $messagesdata, $expectations) {
2295          global $DB;
2296  
2297          // Create all of the users.
2298          $users = array();
2299          foreach ($usersdata as $username) {
2300              $users[$username] = $this->getDataGenerator()->create_user(array('username' => $username));
2301          }
2302  
2303          foreach ($contacts as $username => $contact) {
2304              foreach ($contact as $contactname => $blocked) {
2305                  $record = new stdClass();
2306                  $record->userid     = $users[$username]->id;
2307                  $record->contactid  = $users[$contactname]->id;
2308                  $record->blocked    = $blocked;
2309                  $record->id = $DB->insert_record('message_contacts', $record);
2310              }
2311          }
2312  
2313          $defaulttimecreated = time();
2314          foreach ($messagesdata as $messagedata) {
2315              $from       = $users[$messagedata['from']];
2316              $to         = $users[$messagedata['to']];
2317              $subject    = $messagedata['subject'];
2318  
2319              if (isset($messagedata['state']) && $messagedata['state'] == 'unread') {
2320                  $messageid = $this->send_fake_message($from, $to, $subject);
2321              } else {
2322                  // If there is no state, or the state is not 'unread', assume the message is read.
2323                  $messageid = message_post_message($from, $to, $subject, FORMAT_PLAIN);
2324              }
2325  
2326              $updatemessage = new stdClass();
2327              $updatemessage->id = $messageid;
2328              if (isset($messagedata['timecreated'])) {
2329                  $updatemessage->timecreated = $messagedata['timecreated'];
2330              } else if (isset($messagedata['timemodifier'])) {
2331                  $updatemessage->timecreated = $defaulttimecreated + $messagedata['timemodifier'];
2332              } else {
2333                  $updatemessage->timecreated = $defaulttimecreated;
2334              }
2335  
2336              $DB->update_record('messages', $updatemessage);
2337          }
2338  
2339          foreach ($expectations as $username => $data) {
2340              // Get the recent conversations for the specified user.
2341              $user = $users[$username];
2342              $conversations = array_values(\core_message\api::get_conversations($user->id));
2343              foreach ($data as $expectation) {
2344                  $otheruser = $users[$expectation['with']];
2345                  $conversation = $conversations[$expectation['messageposition']];
2346                  $this->assertEquals($otheruser->id, $conversation->members[$otheruser->id]->id);
2347                  $this->assertEquals($expectation['subject'], $conversation->messages[0]->text);
2348                  $this->assertEquals($expectation['unreadcount'], $conversation->unreadcount);
2349              }
2350          }
2351      }
2352  
2353      /**
2354       * Tests retrieving contacts.
2355       */
2356      public function test_get_contacts() {
2357          // Create some users.
2358          $user1 = self::getDataGenerator()->create_user();
2359  
2360          // Set as the user.
2361          $this->setUser($user1);
2362  
2363          $user2 = new stdClass();
2364          $user2->firstname = 'User';
2365          $user2->lastname = 'A';
2366          $user2 = self::getDataGenerator()->create_user($user2);
2367  
2368          $user3 = new stdClass();
2369          $user3->firstname = 'User';
2370          $user3->lastname = 'B';
2371          $user3 = self::getDataGenerator()->create_user($user3);
2372  
2373          $user4 = new stdClass();
2374          $user4->firstname = 'User';
2375          $user4->lastname = 'C';
2376          $user4 = self::getDataGenerator()->create_user($user4);
2377  
2378          $user5 = new stdClass();
2379          $user5->firstname = 'User';
2380          $user5->lastname = 'D';
2381          $user5 = self::getDataGenerator()->create_user($user5);
2382  
2383          // Add some users as contacts.
2384          \core_message\api::add_contact($user1->id, $user2->id);
2385          \core_message\api::add_contact($user1->id, $user3->id);
2386          \core_message\api::add_contact($user1->id, $user4->id);
2387  
2388          // Retrieve the contacts.
2389          $contacts = \core_message\api::get_contacts($user1->id);
2390  
2391          // Confirm the data is correct.
2392          $this->assertEquals(3, count($contacts));
2393          usort($contacts, ['static', 'sort_contacts']);
2394  
2395          $contact1 = $contacts[0];
2396          $contact2 = $contacts[1];
2397          $contact3 = $contacts[2];
2398  
2399          $this->assertEquals($user2->id, $contact1->userid);
2400          $this->assertEmpty($contact1->useridfrom);
2401          $this->assertFalse($contact1->ismessaging);
2402          $this->assertNull($contact1->lastmessage);
2403          $this->assertNull($contact1->messageid);
2404          $this->assertNull($contact1->isonline);
2405          $this->assertFalse($contact1->isread);
2406          $this->assertFalse($contact1->isblocked);
2407          $this->assertNull($contact1->unreadcount);
2408  
2409          $this->assertEquals($user3->id, $contact2->userid);
2410          $this->assertEmpty($contact2->useridfrom);
2411          $this->assertFalse($contact2->ismessaging);
2412          $this->assertNull($contact2->lastmessage);
2413          $this->assertNull($contact2->messageid);
2414          $this->assertNull($contact2->isonline);
2415          $this->assertFalse($contact2->isread);
2416          $this->assertFalse($contact2->isblocked);
2417          $this->assertNull($contact2->unreadcount);
2418  
2419          $this->assertEquals($user4->id, $contact3->userid);
2420          $this->assertEmpty($contact3->useridfrom);
2421          $this->assertFalse($contact3->ismessaging);
2422          $this->assertNull($contact3->lastmessage);
2423          $this->assertNull($contact3->messageid);
2424          $this->assertNull($contact3->isonline);
2425          $this->assertFalse($contact3->isread);
2426          $this->assertFalse($contact3->isblocked);
2427          $this->assertNull($contact3->unreadcount);
2428      }
2429  
2430      /**
2431       * Tests retrieving user contacts.
2432       */
2433      public function test_get_user_contacts() {
2434          // Create some users.
2435          $user1 = self::getDataGenerator()->create_user();
2436  
2437          // Set as the user.
2438          $this->setUser($user1);
2439  
2440          $user2 = new stdClass();
2441          $user2->firstname = 'User';
2442          $user2->lastname = 'A';
2443          $user2 = self::getDataGenerator()->create_user($user2);
2444  
2445          $user3 = new stdClass();
2446          $user3->firstname = 'User';
2447          $user3->lastname = 'B';
2448          $user3 = self::getDataGenerator()->create_user($user3);
2449  
2450          $user4 = new stdClass();
2451          $user4->firstname = 'User';
2452          $user4->lastname = 'C';
2453          $user4 = self::getDataGenerator()->create_user($user4);
2454  
2455          $user5 = new stdClass();
2456          $user5->firstname = 'User';
2457          $user5->lastname = 'D';
2458          $user5 = self::getDataGenerator()->create_user($user5);
2459  
2460          // Add some users as contacts.
2461          \core_message\api::add_contact($user1->id, $user2->id);
2462          \core_message\api::add_contact($user1->id, $user3->id);
2463          \core_message\api::add_contact($user1->id, $user4->id);
2464  
2465          // Retrieve the contacts.
2466          $contacts = \core_message\api::get_user_contacts($user1->id);
2467  
2468          // Confirm the data is correct.
2469          $this->assertEquals(3, count($contacts));
2470  
2471          ksort($contacts);
2472  
2473          $contact1 = array_shift($contacts);
2474          $contact2 = array_shift($contacts);
2475          $contact3 = array_shift($contacts);
2476  
2477          $this->assertEquals($user2->id, $contact1->id);
2478          $this->assertEquals(fullname($user2), $contact1->fullname);
2479          $this->assertTrue($contact1->iscontact);
2480  
2481          $this->assertEquals($user3->id, $contact2->id);
2482          $this->assertEquals(fullname($user3), $contact2->fullname);
2483          $this->assertTrue($contact2->iscontact);
2484  
2485          $this->assertEquals($user4->id, $contact3->id);
2486          $this->assertEquals(fullname($user4), $contact3->fullname);
2487          $this->assertTrue($contact3->iscontact);
2488      }
2489  
2490      /**
2491       * Tests retrieving messages.
2492       */
2493      public function test_get_messages() {
2494          // Create some users.
2495          $user1 = self::getDataGenerator()->create_user();
2496          $user2 = self::getDataGenerator()->create_user();
2497  
2498          // The person doing the search.
2499          $this->setUser($user1);
2500  
2501          // Send some messages back and forth.
2502          $time = 1;
2503          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2504          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2505          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2506          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2507  
2508          // Retrieve the messages.
2509          $messages = \core_message\api::get_messages($user1->id, $user2->id);
2510  
2511          // Confirm the message data is correct.
2512          $this->assertEquals(4, count($messages));
2513  
2514          $message1 = $messages[0];
2515          $message2 = $messages[1];
2516          $message3 = $messages[2];
2517          $message4 = $messages[3];
2518  
2519          $this->assertEquals($user1->id, $message1->useridfrom);
2520          $this->assertEquals($user2->id, $message1->useridto);
2521          $this->assertTrue($message1->displayblocktime);
2522          $this->assertContains('Yo!', $message1->text);
2523  
2524          $this->assertEquals($user2->id, $message2->useridfrom);
2525          $this->assertEquals($user1->id, $message2->useridto);
2526          $this->assertFalse($message2->displayblocktime);
2527          $this->assertContains('Sup mang?', $message2->text);
2528  
2529          $this->assertEquals($user1->id, $message3->useridfrom);
2530          $this->assertEquals($user2->id, $message3->useridto);
2531          $this->assertFalse($message3->displayblocktime);
2532          $this->assertContains('Writing PHPUnit tests!', $message3->text);
2533  
2534          $this->assertEquals($user2->id, $message4->useridfrom);
2535          $this->assertEquals($user1->id, $message4->useridto);
2536          $this->assertFalse($message4->displayblocktime);
2537          $this->assertContains('Word.', $message4->text);
2538      }
2539  
2540      /**
2541       * Tests retrieving conversation messages.
2542       */
2543      public function test_get_conversation_messages() {
2544          // Create some users.
2545          $user1 = self::getDataGenerator()->create_user();
2546          $user2 = self::getDataGenerator()->create_user();
2547  
2548          // Create conversation.
2549          $conversation = \core_message\api::create_conversation(
2550              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2551              [$user1->id, $user2->id]
2552          );
2553  
2554          // The person doing the search.
2555          $this->setUser($user1);
2556  
2557          // Send some messages back and forth.
2558          $time = 1;
2559          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2560          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2561          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2562          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2563  
2564          // Retrieve the messages.
2565          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2566  
2567          // Confirm the conversation id is correct.
2568          $this->assertEquals($conversation->id, $convmessages['id']);
2569  
2570          // Confirm the message data is correct.
2571          $messages = $convmessages['messages'];
2572          $this->assertEquals(4, count($messages));
2573          $message1 = $messages[0];
2574          $message2 = $messages[1];
2575          $message3 = $messages[2];
2576          $message4 = $messages[3];
2577  
2578          $this->assertEquals($user1->id, $message1->useridfrom);
2579          $this->assertContains('Yo!', $message1->text);
2580  
2581          $this->assertEquals($user2->id, $message2->useridfrom);
2582          $this->assertContains('Sup mang?', $message2->text);
2583  
2584          $this->assertEquals($user1->id, $message3->useridfrom);
2585          $this->assertContains('Writing PHPUnit tests!', $message3->text);
2586  
2587          $this->assertEquals($user1->id, $message4->useridfrom);
2588          $this->assertContains('Word.', $message4->text);
2589  
2590          // Confirm the members data is correct.
2591          $members = $convmessages['members'];
2592          $this->assertEquals(2, count($members));
2593      }
2594  
2595      /**
2596       * Tests retrieving group conversation messages.
2597       */
2598      public function test_get_group_conversation_messages() {
2599          // Create some users.
2600          $user1 = self::getDataGenerator()->create_user();
2601          $user2 = self::getDataGenerator()->create_user();
2602          $user3 = self::getDataGenerator()->create_user();
2603          $user4 = self::getDataGenerator()->create_user();
2604  
2605          // Create group conversation.
2606          $conversation = \core_message\api::create_conversation(
2607              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2608              [$user1->id, $user2->id, $user3->id, $user4->id]
2609          );
2610  
2611          // The person doing the search.
2612          $this->setUser($user1);
2613  
2614          // Send some messages back and forth.
2615          $time = 1;
2616          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2617          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2618          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2619          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2620          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Yeah!', $time + 5);
2621  
2622          // Retrieve the messages.
2623          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2624  
2625          // Confirm the conversation id is correct.
2626          $this->assertEquals($conversation->id, $convmessages['id']);
2627  
2628          // Confirm the message data is correct.
2629          $messages = $convmessages['messages'];
2630          $this->assertEquals(5, count($messages));
2631  
2632          $message1 = $messages[0];
2633          $message2 = $messages[1];
2634          $message3 = $messages[2];
2635          $message4 = $messages[3];
2636          $message5 = $messages[4];
2637  
2638          $this->assertEquals($user1->id, $message1->useridfrom);
2639          $this->assertContains('Yo!', $message1->text);
2640  
2641          $this->assertEquals($user2->id, $message2->useridfrom);
2642          $this->assertContains('Sup mang?', $message2->text);
2643  
2644          $this->assertEquals($user3->id, $message3->useridfrom);
2645          $this->assertContains('Writing PHPUnit tests!', $message3->text);
2646  
2647          $this->assertEquals($user1->id, $message4->useridfrom);
2648          $this->assertContains('Word.', $message4->text);
2649  
2650          $this->assertEquals($user2->id, $message5->useridfrom);
2651          $this->assertContains('Yeah!', $message5->text);
2652  
2653          // Confirm the members data is correct.
2654          $members = $convmessages['members'];
2655          $this->assertEquals(3, count($members));
2656      }
2657  
2658      /**
2659       * Test verifying the sorting param for get_conversation_messages is respected().
2660       */
2661      public function test_get_conversation_messages_sorting() {
2662          // Create some users.
2663          $user1 = self::getDataGenerator()->create_user();
2664          $user2 = self::getDataGenerator()->create_user();
2665          $user3 = self::getDataGenerator()->create_user();
2666  
2667          // Create conversations - 1 group and 1 individual.
2668          $conversation = \core_message\api::create_conversation(
2669              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2670              [$user1->id, $user2->id]
2671          );
2672          $conversation2 = \core_message\api::create_conversation(
2673              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2674              [$user1->id, $user2->id, $user3->id]
2675          );
2676  
2677          // Send some messages back and forth.
2678          $time = 1;
2679          $m1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2680          $m2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2681          $m3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2682          $m4id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2683  
2684          $gm1id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Yo!', $time + 1);
2685          $gm2id = testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Sup mang?', $time + 2);
2686          $gm3id = testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'Writing PHPUnit tests!', $time + 3);
2687          $gm4id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Word.', $time + 4);
2688  
2689          // The person doing the search.
2690          $this->setUser($user1);
2691  
2692          // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2693          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2694          $messages = $convmessages['messages'];
2695          $this->assertEquals($m1id, $messages[0]->id);
2696          $this->assertEquals($m2id, $messages[1]->id);
2697          $this->assertEquals($m3id, $messages[2]->id);
2698          $this->assertEquals($m4id, $messages[3]->id);
2699  
2700          // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2701          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated DESC');
2702          $messages = $convmessages['messages'];
2703          $this->assertEquals($m1id, $messages[3]->id);
2704          $this->assertEquals($m2id, $messages[2]->id);
2705          $this->assertEquals($m3id, $messages[1]->id);
2706          $this->assertEquals($m4id, $messages[0]->id);
2707  
2708          // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2709          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id);
2710          $messages = $convmessages['messages'];
2711          $this->assertEquals($gm1id, $messages[0]->id);
2712          $this->assertEquals($gm2id, $messages[1]->id);
2713          $this->assertEquals($gm3id, $messages[2]->id);
2714          $this->assertEquals($gm4id, $messages[3]->id);
2715  
2716          // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2717          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id, 0, 0, 'timecreated DESC');
2718          $messages = $convmessages['messages'];
2719          $this->assertEquals($gm1id, $messages[3]->id);
2720          $this->assertEquals($gm2id, $messages[2]->id);
2721          $this->assertEquals($gm3id, $messages[1]->id);
2722          $this->assertEquals($gm4id, $messages[0]->id);
2723      }
2724  
2725      /**
2726       * Test retrieving conversation messages by providing a minimum timecreated value.
2727       */
2728      public function test_get_conversation_messages_time_from_only() {
2729          // Create some users.
2730          $user1 = self::getDataGenerator()->create_user();
2731          $user2 = self::getDataGenerator()->create_user();
2732          $user3 = self::getDataGenerator()->create_user();
2733          $user4 = self::getDataGenerator()->create_user();
2734  
2735          // Create group conversation.
2736          $conversation = \core_message\api::create_conversation(
2737              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2738              [$user1->id, $user2->id, $user3->id, $user4->id]
2739          );
2740  
2741          // The person doing the search.
2742          $this->setUser($user1);
2743  
2744          // Send some messages back and forth.
2745          $time = 1;
2746          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2747          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2748          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2749          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2750  
2751          // Retrieve the messages from $time, which should be all of them.
2752          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC', $time);
2753  
2754          // Confirm the conversation id is correct.
2755          $this->assertEquals($conversation->id, $convmessages['id']);
2756  
2757          // Confirm the message data is correct.
2758          $messages = $convmessages['messages'];
2759          $this->assertEquals(4, count($messages));
2760  
2761          $message1 = $messages[0];
2762          $message2 = $messages[1];
2763          $message3 = $messages[2];
2764          $message4 = $messages[3];
2765  
2766          $this->assertContains('Message 1', $message1->text);
2767          $this->assertContains('Message 2', $message2->text);
2768          $this->assertContains('Message 3', $message3->text);
2769          $this->assertContains('Message 4', $message4->text);
2770  
2771          // Confirm the members data is correct.
2772          $members = $convmessages['members'];
2773          $this->assertEquals(3, count($members));
2774  
2775          // Retrieve the messages from $time + 3, which should only be the 2 last messages.
2776          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2777              'timecreated ASC', $time + 3);
2778  
2779          // Confirm the conversation id is correct.
2780          $this->assertEquals($conversation->id, $convmessages['id']);
2781  
2782          // Confirm the message data is correct.
2783          $messages = $convmessages['messages'];
2784          $this->assertEquals(2, count($messages));
2785  
2786          $message1 = $messages[0];
2787          $message2 = $messages[1];
2788  
2789          $this->assertContains('Message 3', $message1->text);
2790          $this->assertContains('Message 4', $message2->text);
2791  
2792          // Confirm the members data is correct.
2793          $members = $convmessages['members'];
2794          $this->assertEquals(2, count($members));
2795      }
2796  
2797      /**
2798       * Test retrieving conversation messages by providing a maximum timecreated value.
2799       */
2800      public function test_get_conversation_messages_time_to_only() {
2801          // Create some users.
2802          $user1 = self::getDataGenerator()->create_user();
2803          $user2 = self::getDataGenerator()->create_user();
2804          $user3 = self::getDataGenerator()->create_user();
2805          $user4 = self::getDataGenerator()->create_user();
2806  
2807          // Create group conversation.
2808          $conversation = \core_message\api::create_conversation(
2809              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2810              [$user1->id, $user2->id, $user3->id, $user4->id]
2811          );
2812  
2813          // The person doing the search.
2814          $this->setUser($user1);
2815  
2816          // Send some messages back and forth.
2817          $time = 1;
2818          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2819          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2820          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2821          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2822  
2823          // Retrieve the messages up until $time + 4, which should be all of them.
2824          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2825              0, $time + 4);
2826  
2827          // Confirm the conversation id is correct.
2828          $this->assertEquals($conversation->id, $convmessages['id']);
2829  
2830          // Confirm the message data is correct.
2831          $messages = $convmessages['messages'];
2832          $this->assertEquals(4, count($messages));
2833  
2834          $message1 = $messages[0];
2835          $message2 = $messages[1];
2836          $message3 = $messages[2];
2837          $message4 = $messages[3];
2838  
2839          $this->assertContains('Message 1', $message1->text);
2840          $this->assertContains('Message 2', $message2->text);
2841          $this->assertContains('Message 3', $message3->text);
2842          $this->assertContains('Message 4', $message4->text);
2843  
2844          // Confirm the members data is correct.
2845          $members = $convmessages['members'];
2846          $this->assertEquals(3, count($members));
2847  
2848          // Retrieve the messages up until $time + 2, which should be the first two.
2849          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2850              0, $time + 2);
2851  
2852          // Confirm the conversation id is correct.
2853          $this->assertEquals($conversation->id, $convmessages['id']);
2854  
2855          // Confirm the message data is correct.
2856          $messages = $convmessages['messages'];
2857          $this->assertEquals(2, count($messages));
2858  
2859          $message1 = $messages[0];
2860          $message2 = $messages[1];
2861  
2862          $this->assertContains('Message 1', $message1->text);
2863          $this->assertContains('Message 2', $message2->text);
2864  
2865          // Confirm the members data is correct.
2866          $members = $convmessages['members'];
2867          $this->assertEquals(2, count($members));
2868      }
2869  
2870      /**
2871       * Test retrieving conversation messages by providing a minimum and maximum timecreated value.
2872       */
2873      public function test_get_conversation_messages_time_from_and_to() {
2874          // Create some users.
2875          $user1 = self::getDataGenerator()->create_user();
2876          $user2 = self::getDataGenerator()->create_user();
2877          $user3 = self::getDataGenerator()->create_user();
2878          $user4 = self::getDataGenerator()->create_user();
2879  
2880          // Create group conversation.
2881          $conversation = \core_message\api::create_conversation(
2882              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2883              [$user1->id, $user2->id, $user3->id, $user4->id]
2884          );
2885  
2886          // The person doing the search.
2887          $this->setUser($user1);
2888  
2889          // Send some messages back and forth.
2890          $time = 1;
2891          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2892          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2893          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2894          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2895  
2896          // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
2897          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2898              'timecreated ASC', $time + 2, $time + 3);
2899  
2900          // Confirm the conversation id is correct.
2901          $this->assertEquals($conversation->id, $convmessages['id']);
2902  
2903          // Confirm the message data is correct.
2904          $messages = $convmessages['messages'];
2905          $this->assertEquals(2, count($messages));
2906  
2907          $message1 = $messages[0];
2908          $message2 = $messages[1];
2909  
2910          $this->assertContains('Message 2', $message1->text);
2911          $this->assertContains('Message 3', $message2->text);
2912  
2913          // Confirm the members data is correct.
2914          $members = $convmessages['members'];
2915          $this->assertEquals(2, count($members));
2916      }
2917  
2918  
2919      /**
2920       * Test retrieving conversation messages by providing a limitfrom value.
2921       */
2922      public function test_get_conversation_messages_limitfrom_only() {
2923          // Create some users.
2924          $user1 = self::getDataGenerator()->create_user();
2925          $user2 = self::getDataGenerator()->create_user();
2926          $user3 = self::getDataGenerator()->create_user();
2927          $user4 = self::getDataGenerator()->create_user();
2928  
2929          // Create group conversation.
2930          $conversation = \core_message\api::create_conversation(
2931              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2932              [$user1->id, $user2->id, $user3->id, $user4->id]
2933          );
2934  
2935          // The person doing the search.
2936          $this->setUser($user1);
2937  
2938          // Send some messages back and forth.
2939          $time = 1;
2940          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2941          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2942          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2943          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2944  
2945          // Retrieve the messages from $time, which should be all of them.
2946          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2);
2947  
2948          // Confirm the conversation id is correct.
2949          $messages = $convmessages['messages'];
2950          $this->assertEquals($conversation->id, $convmessages['id']);
2951  
2952          // Confirm the message data is correct.
2953          $this->assertEquals(2, count($messages));
2954  
2955          $message1 = $messages[0];
2956          $message2 = $messages[1];
2957  
2958          $this->assertContains('Message 3', $message1->text);
2959          $this->assertContains('Message 4', $message2->text);
2960  
2961          // Confirm the members data is correct.
2962          $members = $convmessages['members'];
2963          $this->assertEquals(2, count($members));
2964      }
2965  
2966      /**
2967       * Test retrieving conversation messages by providing a limitnum value.
2968       */
2969      public function test_get_conversation_messages_limitnum() {
2970          // Create some users.
2971          $user1 = self::getDataGenerator()->create_user();
2972          $user2 = self::getDataGenerator()->create_user();
2973          $user3 = self::getDataGenerator()->create_user();
2974          $user4 = self::getDataGenerator()->create_user();
2975  
2976          // Create group conversation.
2977          $conversation = \core_message\api::create_conversation(
2978              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2979              [$user1->id, $user2->id, $user3->id, $user4->id]
2980          );
2981  
2982          // The person doing the search.
2983          $this->setUser($user1);
2984  
2985          // Send some messages back and forth.
2986          $time = 1;
2987          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2988          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2989          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2990          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2991  
2992          // Retrieve the messages from $time, which should be all of them.
2993          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2, 1);
2994  
2995          // Confirm the conversation id is correct.
2996          $messages = $convmessages['messages'];
2997          $this->assertEquals($conversation->id, $convmessages['id']);
2998  
2999          // Confirm the message data is correct.
3000          $messages = $convmessages['messages'];
3001          $this->assertEquals(1, count($messages));
3002  
3003          $message1 = $messages[0];
3004  
3005          $this->assertContains('Message 3', $message1->text);
3006  
3007          // Confirm the members data is correct.
3008          $members = $convmessages['members'];
3009          $this->assertEquals(1, count($members));
3010      }
3011  
3012      /**
3013       * Tests retrieving most recent message.
3014       */
3015      public function test_get_most_recent_message() {
3016          // Create some users.
3017          $user1 = self::getDataGenerator()->create_user();
3018          $user2 = self::getDataGenerator()->create_user();
3019  
3020          // The person doing the search.
3021          $this->setUser($user1);
3022  
3023          // Send some messages back and forth.
3024          $time = 1;
3025          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3026          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3027          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3028          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3029  
3030          // Retrieve the most recent messages.
3031          $message = \core_message\api::get_most_recent_message($user1->id, $user2->id);
3032  
3033          // Check the results are correct.
3034          $this->assertEquals($user2->id, $message->useridfrom);
3035          $this->assertEquals($user1->id, $message->useridto);
3036          $this->assertContains('Word.', $message->text);
3037      }
3038  
3039      /**
3040       * Tests retrieving most recent conversation message.
3041       */
3042      public function test_get_most_recent_conversation_message() {
3043          // Create some users.
3044          $user1 = self::getDataGenerator()->create_user();
3045          $user2 = self::getDataGenerator()->create_user();
3046          $user3 = self::getDataGenerator()->create_user();
3047  
3048          // Create group conversation.
3049          $conversation = \core_message\api::create_conversation(
3050              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3051              [$user1->id, $user2->id, $user3->id]
3052          );
3053  
3054          // The person getting the most recent conversation message.
3055          $this->setUser($user1);
3056  
3057          // Send some messages back and forth.
3058          $time = 1;
3059          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
3060          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
3061          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
3062          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Word.', $time + 4);
3063  
3064          // Retrieve the most recent messages.
3065          $message = \core_message\api::get_most_recent_conversation_message($conversation->id, $user1->id);
3066  
3067          // Check the results are correct.
3068          $this->assertEquals($user2->id, $message->useridfrom);
3069          $this->assertContains('Word.', $message->text);
3070      }
3071  
3072      /**
3073       * Tests retrieving a user's profile.
3074       */
3075      public function test_get_profile() {
3076          // Create some users.
3077          $user1 = self::getDataGenerator()->create_user();
3078  
3079          $user2 = new stdClass();
3080          $user2->country = 'AU';
3081          $user2->city = 'Perth';
3082          $user2 = self::getDataGenerator()->create_user($user2);
3083  
3084          // The person doing the search.
3085          $this->setUser($user1);
3086  
3087          // Get the profile.
3088          $profile = \core_message\api::get_profile($user1->id, $user2->id);
3089  
3090          $this->assertEquals($user2->id, $profile->userid);
3091          $this->assertEmpty($profile->email);
3092          $this->assertEmpty($profile->country);
3093          $this->assertEmpty($profile->city);
3094          $this->assertEquals(fullname($user2), $profile->fullname);
3095          $this->assertNull($profile->isonline);
3096          $this->assertFalse($profile->isblocked);
3097          $this->assertFalse($profile->iscontact);
3098      }
3099  
3100      /**
3101       * Tests retrieving a user's profile.
3102       */
3103      public function test_get_profile_as_admin() {
3104          // The person doing the search.
3105          $this->setAdminUser();
3106  
3107          // Create some users.
3108          $user1 = self::getDataGenerator()->create_user();
3109  
3110          $user2 = new stdClass();
3111          $user2->country = 'AU';
3112          $user2->city = 'Perth';
3113          $user2 = self::getDataGenerator()->create_user($user2);
3114  
3115          // Get the profile.
3116          $profile = \core_message\api::get_profile($user1->id, $user2->id);
3117  
3118          $this->assertEquals($user2->id, $profile->userid);
3119          $this->assertEquals($user2->email, $profile->email);
3120          $this->assertEquals($user2->country, $profile->country);
3121          $this->assertEquals($user2->city, $profile->city);
3122          $this->assertEquals(fullname($user2), $profile->fullname);
3123          $this->assertFalse($profile->isonline);
3124          $this->assertFalse($profile->isblocked);
3125          $this->assertFalse($profile->iscontact);
3126      }
3127  
3128      /**
3129       * Tests checking if a user can mark all messages as read.
3130       */
3131      public function test_can_mark_all_messages_as_read() {
3132          // Set as the admin.
3133          $this->setAdminUser();
3134  
3135          // Create some users.
3136          $user1 = self::getDataGenerator()->create_user();
3137          $user2 = self::getDataGenerator()->create_user();
3138          $user3 = self::getDataGenerator()->create_user();
3139  
3140          // Send some messages back and forth.
3141          $time = 1;
3142          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3143          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3144          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3145          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3146  
3147          $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3148  
3149          // The admin can do anything.
3150          $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
3151  
3152          // Set as the user 1.
3153          $this->setUser($user1);
3154  
3155          // The user can mark the messages as he is in the conversation.
3156          $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
3157  
3158          // User 1 can not mark the messages read for user 2.
3159          $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user2->id, $conversationid));
3160  
3161          // This user is not a part of the conversation.
3162          $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user3->id, $conversationid));
3163      }
3164  
3165      /**
3166       * Tests checking if a user can delete a conversation.
3167       */
3168      public function test_can_delete_conversation() {
3169          // Set as the admin.
3170          $this->setAdminUser();
3171  
3172          // Create some users.
3173          $user1 = self::getDataGenerator()->create_user();
3174          $user2 = self::getDataGenerator()->create_user();
3175  
3176          // Send some messages back and forth.
3177          $time = 1;
3178          $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3179          $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3180          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3181          $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3182  
3183          $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3184  
3185          // The admin can do anything.
3186          $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
3187  
3188          // Set as the user 1.
3189          $this->setUser($user1);
3190  
3191          // They can delete their own messages.
3192          $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
3193  
3194          // They can't delete someone elses.
3195          $this->assertFalse(\core_message\api::can_delete_conversation($user2->id, $conversationid));
3196      }
3197  
3198      /**
3199       * Tests deleting a conversation.
3200       */
3201      public function test_delete_conversation() {
3202          global $DB;
3203  
3204          // Create some users.
3205          $user1 = self::getDataGenerator()->create_user();
3206          $user2 = self::getDataGenerator()->create_user();
3207  
3208          // The person doing the search.
3209          $this->setUser($user1);
3210  
3211          // Send some messages back and forth.
3212          $time = 1;
3213          $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3214          $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3215          $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3216          $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3217  
3218          // Delete the conversation as user 1.
3219          \core_message\api::delete_conversation($user1->id, $user2->id);
3220          $this->assertDebuggingCalled();
3221  
3222          $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3223          $this->assertCount(4, $muas);
3224          // Sort by id.
3225          ksort($muas);
3226  
3227          $mua1 = array_shift($muas);
3228          $mua2 = array_shift($muas);
3229          $mua3 = array_shift($muas);
3230          $mua4 = array_shift($muas);
3231  
3232          $this->assertEquals($user1->id, $mua1->userid);
3233          $this->assertEquals($m1id, $mua1->messageid);
3234          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3235  
3236          $this->assertEquals($user1->id, $mua2->userid);
3237          $this->assertEquals($m2id, $mua2->messageid);
3238          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
3239  
3240          $this->assertEquals($user1->id, $mua3->userid);
3241          $this->assertEquals($m3id, $mua3->messageid);
3242          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
3243  
3244          $this->assertEquals($user1->id, $mua4->userid);
3245          $this->assertEquals($m4id, $mua4->messageid);
3246          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
3247      }
3248  
3249      /**
3250       * Tests deleting a conversation by conversation id.
3251       */
3252      public function test_delete_conversation_by_id() {
3253          global $DB;
3254  
3255          // Create some users.
3256          $user1 = self::getDataGenerator()->create_user();
3257          $user2 = self::getDataGenerator()->create_user();
3258  
3259          // The person doing the search.
3260          $this->setUser($user1);
3261  
3262          // Get self-conversation.
3263          $sc1 = \core_message\api::get_self_conversation($user1->id);
3264          $sc2 = \core_message\api::get_self_conversation($user2->id);
3265  
3266          // Send some messages back and forth.
3267          $time = 1;
3268          $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3269          $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3270          $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3271          $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3272          $m5id = testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi to myself!', $time + 5);
3273          $m6id = testhelper::send_fake_message_to_conversation($user2, $sc2->id, 'I am talking with myself', $time + 6);
3274  
3275          $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3276  
3277          // Delete the individual conversation between user1 and user2 (only for user1).
3278          \core_message\api::delete_conversation_by_id($user1->id, $conversationid);
3279  
3280          $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3281          $this->assertCount(4, $muas);
3282          // Sort by id.
3283          ksort($muas);
3284  
3285          $mua1 = array_shift($muas);
3286          $mua2 = array_shift($muas);
3287          $mua3 = array_shift($muas);
3288          $mua4 = array_shift($muas);
3289  
3290          $this->assertEquals($user1->id, $mua1->userid);
3291          $this->assertEquals($m1id, $mua1->messageid);
3292          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3293  
3294          $this->assertEquals($user1->id, $mua2->userid);
3295          $this->assertEquals($m2id, $mua2->messageid);
3296          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
3297  
3298          $this->assertEquals($user1->id, $mua3->userid);
3299          $this->assertEquals($m3id, $mua3->messageid);
3300          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
3301  
3302          $this->assertEquals($user1->id, $mua4->userid);
3303          $this->assertEquals($m4id, $mua4->messageid);
3304          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
3305  
3306          // Delete the self-conversation as user 1.
3307          \core_message\api::delete_conversation_by_id($user1->id, $sc1->id);
3308  
3309          $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3310          $this->assertCount(5, $muas);
3311  
3312          // Sort by id.
3313          ksort($muas);
3314  
3315          $mua1 = array_shift($muas);
3316          $mua2 = array_shift($muas);
3317          $mua3 = array_shift($muas);
3318          $mua4 = array_shift($muas);
3319          $mua5 = array_shift($muas);
3320  
3321          // Check only messages in self-conversion for user1 are deleted (self-conversation for user2 shouldn't be removed).
3322          $this->assertEquals($user1->id, $mua5->userid);
3323          $this->assertEquals($m5id, $mua5->messageid);
3324          $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua5->action);
3325      }
3326  
3327      /**
3328       * Tests counting unread conversations.
3329       */
3330      public function test_count_unread_conversations() {
3331          $this->resetAfterTest(true);
3332  
3333          // Create some users.
3334          $user1 = self::getDataGenerator()->create_user();
3335          $user2 = self::getDataGenerator()->create_user();
3336          $user3 = self::getDataGenerator()->create_user();
3337          $user4 = self::getDataGenerator()->create_user();
3338  
3339          // The person wanting the conversation count.
3340          $this->setUser($user1);
3341  
3342          // Send some messages back and forth, have some different conversations with different users.
3343          $this->send_fake_message($user1, $user2, 'Yo!');
3344          $this->send_fake_message($user2, $user1, 'Sup mang?');
3345          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
3346          $this->send_fake_message($user2, $user1, 'Word.');
3347  
3348          $this->send_fake_message($user1, $user3, 'Booyah');
3349          $this->send_fake_message($user3, $user1, 'Whaaat?');
3350          $this->send_fake_message($user1, $user3, 'Nothing.');
3351          $this->send_fake_message($user3, $user1, 'Cool.');
3352  
3353          $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3354          $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3355          $this->send_fake_message($user1, $user4, 'Dope.');
3356  
3357          // Check the amount for the current user.
3358          $this->assertEquals(3, core_message\api::count_unread_conversations());
3359  
3360          // Check the amount for the second user.
3361          $this->assertEquals(1, core_message\api::count_unread_conversations($user2));
3362      }
3363  
3364      /**
3365       * Tests counting unread conversations where one conversation is disabled.
3366       */
3367      public function test_count_unread_conversations_disabled() {
3368          $this->resetAfterTest(true);
3369  
3370          // Create some users.
3371          $user1 = self::getDataGenerator()->create_user();
3372          $user2 = self::getDataGenerator()->create_user();
3373          $user3 = self::getDataGenerator()->create_user();
3374          $user4 = self::getDataGenerator()->create_user();
3375  
3376          // The person wanting the conversation count.
3377          $this->setUser($user1);
3378  
3379          // Send some messages back and forth, have some different conversations with different users.
3380          $this->send_fake_message($user1, $user2, 'Yo!');
3381          $this->send_fake_message($user2, $user1, 'Sup mang?');
3382          $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
3383          $this->send_fake_message($user2, $user1, 'Word.');
3384  
3385          $this->send_fake_message($user1, $user3, 'Booyah');
3386          $this->send_fake_message($user3, $user1, 'Whaaat?');
3387          $this->send_fake_message($user1, $user3, 'Nothing.');
3388          $this->send_fake_message($user3, $user1, 'Cool.');
3389  
3390          $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3391          $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3392          $this->send_fake_message($user1, $user4, 'Dope.');
3393  
3394          // Let's disable the last conversation.
3395          $conversationid = core_message\api::get_conversation_between_users([$user1->id, $user4->id]);
3396          core_message\api::disable_conversation($conversationid);
3397  
3398          // Check that the disabled conversation was not included.
3399          $this->assertEquals(2, core_message\api::count_unread_conversations());
3400      }
3401  
3402      /**
3403       * Tests deleting a conversation.
3404       */
3405      public function test_get_all_message_preferences() {
3406          $user = self::getDataGenerator()->create_user();
3407          $this->setUser($user);
3408  
3409          // Set a couple of preferences to test.
3410          set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
3411          set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
3412  
3413          $processors = get_message_processors();
3414          $providers = message_get_providers_for_user($user->id);
3415          $prefs = \core_message\api::get_all_message_preferences($processors, $providers, $user);
3416  
3417          $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedin['popup']);
3418          $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedoff['email']);
3419      }
3420  
3421      /**
3422       * Tests the user can send a message.
3423       */
3424      public function test_can_send_message() {
3425          // Create some users.
3426          $user1 = self::getDataGenerator()->create_user();
3427          $user2 = self::getDataGenerator()->create_user();
3428  
3429          // Set as the first user.
3430          $this->setUser($user1);
3431  
3432          // With the default privacy setting, users can't message them.
3433          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3434  
3435          // Enrol users to the same course.
3436          $course = $this->getDataGenerator()->create_course();
3437          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3438          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3439          // After enrolling users to the course, they should be able to message them with the default privacy setting.
3440          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
3441      }
3442  
3443      /**
3444       * Tests the user can't send a message without proper capability.
3445       */
3446      public function test_can_send_message_without_sendmessage_cap() {
3447          global $DB;
3448  
3449          // Create some users.
3450          $user1 = self::getDataGenerator()->create_user();
3451          $user2 = self::getDataGenerator()->create_user();
3452  
3453          // Set as the user 1.
3454          $this->setUser($user1);
3455  
3456          // Remove the capability to send a message.
3457          $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3458          unassign_capability('moodle/site:sendmessage', $roleids['user'],
3459              context_system::instance());
3460  
3461          // Check that we can not post a message without the capability.
3462          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3463      }
3464  
3465      /**
3466       * Tests the user can send a message when they are contact.
3467       */
3468      public function test_can_send_message_when_contact() {
3469          // Create some users.
3470          $user1 = self::getDataGenerator()->create_user();
3471          $user2 = self::getDataGenerator()->create_user();
3472  
3473          // Set as the first user.
3474          $this->setUser($user1);
3475  
3476          // Check that we can not send user2 a message.
3477          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3478  
3479          // Add users as contacts.
3480          \core_message\api::add_contact($user1->id, $user2->id);
3481  
3482          // Check that the return result is now true.
3483          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
3484      }
3485  
3486      /**
3487       * Tests the user can't send a message if they are not a contact and the user
3488       * has requested messages only from contacts.
3489       */
3490      public function test_can_send_message_when_not_contact() {
3491          // Create some users.
3492          $user1 = self::getDataGenerator()->create_user();
3493          $user2 = self::getDataGenerator()->create_user();
3494  
3495          // Set as the first user.
3496          $this->setUser($user1);
3497  
3498          // Set the second user's preference to not receive messages from non-contacts.
3499          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3500  
3501          // Check that we can not send user 2 a message.
3502          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3503      }
3504  
3505      /**
3506       * Tests the user can't send a message if they are blocked.
3507       */
3508      public function test_can_send_message_when_blocked() {
3509          // Create some users.
3510          $user1 = self::getDataGenerator()->create_user();
3511          $user2 = self::getDataGenerator()->create_user();
3512  
3513          // Set the user.
3514          $this->setUser($user1);
3515  
3516          // Block the second user.
3517          \core_message\api::block_user($user1->id, $user2->id);
3518  
3519          // Check that the second user can no longer send the first user a message.
3520          $this->assertFalse(\core_message\api::can_send_message($user1->id, $user2->id));
3521      }
3522  
3523      /**
3524       * Tests the user can send a message when site-wide messaging setting is enabled,
3525       * even if they are not a contact and are not members of the same course.
3526       */
3527      public function test_can_send_message_site_messaging_setting() {
3528          // Create some users.
3529          $user1 = self::getDataGenerator()->create_user();
3530          $user2 = self::getDataGenerator()->create_user();
3531  
3532          // Set as the first user.
3533          $this->setUser($user1);
3534  
3535          // By default, user only can be messaged by contacts and members of any of his/her courses.
3536          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3537  
3538          // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
3539          set_config('messagingallusers', true);
3540  
3541          // Set the second user's preference to receive messages from everybody.
3542          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
3543  
3544          // Check that we can send user2 a message.
3545          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
3546  
3547          // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
3548          // and members sharing a course with her.
3549          set_config('messagingallusers', false);
3550  
3551          // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
3552          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3553  
3554          // Enrol users to the same course.
3555          $course = $this->getDataGenerator()->create_course();
3556          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3557          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3558          // Check that we can send user2 a message because they are sharing a course.
3559          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
3560  
3561          // Set the second user's preference to receive messages only from contacts.
3562          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3563          // Check that now the user2 can't be contacted because user1 is not their contact.
3564          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
3565  
3566          // Make contacts user1 and user2.
3567          \core_message\api::add_contact($user2->id, $user1->id);
3568          // Check that we can send user2 a message because they are contacts.
3569          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
3570      }
3571  
3572      /**
3573       * Tests the user with the messageanyuser capability can send a message.
3574       */
3575      public function test_can_send_message_with_messageanyuser_cap() {
3576          global $DB;
3577  
3578          // Create some users.
3579          $teacher1 = self::getDataGenerator()->create_user();
3580          $student1 = self::getDataGenerator()->create_user();
3581          $student2 = self::getDataGenerator()->create_user();
3582  
3583          // Create users not enrolled in any course.
3584          $user1 = self::getDataGenerator()->create_user();
3585  
3586          // Create a course.
3587          $course1 = $this->getDataGenerator()->create_course();
3588  
3589          // Enrol the users in the course.
3590          $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher');
3591          $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student');
3592          $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student');
3593  
3594          // Set some student preferences to not receive messages from non-contacts.
3595          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $student1->id);
3596  
3597          // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
3598          $this->assertTrue(\core_message\api::can_send_message($student1->id, $teacher1->id));
3599  
3600          // Check that the teacher can't contact user1 because it's not his teacher.
3601          $this->assertFalse(\core_message\api::can_send_message($user1->id, $teacher1->id));
3602  
3603          // Remove the messageanyuser capability from the course1 for teachers.
3604          $coursecontext = context_course::instance($course1->id);
3605          $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
3606          assign_capability('moodle/site:messageanyuser', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
3607          $coursecontext->mark_dirty();
3608  
3609          // Check that we can't send user1 a message because they are not contacts.
3610          $this->assertFalse(\core_message\api::can_send_message($student1->id, $teacher1->id));
3611  
3612          // However, teacher can message student2 because they are sharing a course.
3613          $this->assertTrue(\core_message\api::can_send_message($student2->id, $teacher1->id));
3614      }
3615  
3616      /**
3617       * Tests the user when blocked will not be able to send messages if they are blocked.
3618       */
3619      public function test_can_send_message_even_if_blocked() {
3620          $this->resetAfterTest();
3621  
3622          $user1 = self::getDataGenerator()->create_user();
3623          $user2 = self::getDataGenerator()->create_user();
3624  
3625          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id, true));
3626      }
3627  
3628      /**
3629       * Tests the user will be able to send a message even if they are blocked as the user
3630       * has the capability 'moodle/site:messageanyuser'.
3631       */
3632      public function test_can_send_message_even_if_blocked_with_message_any_user_cap() {
3633          global $DB;
3634  
3635          $this->resetAfterTest();
3636  
3637          $user1 = self::getDataGenerator()->create_user();
3638          $user2 = self::getDataGenerator()->create_user();
3639  
3640          $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
3641          assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduserrole->id, context_system::instance(), true);
3642  
3643          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id, true));
3644      }
3645  
3646      /**
3647       * Tests the user will be able to send a message even if they are blocked as the user
3648       * has the capability 'moodle/site:readallmessages'.
3649       */
3650      public function test_can_send_message_even_if_blocked_with_read_all_message_cap() {
3651          global $DB;
3652  
3653          $this->resetAfterTest();
3654  
3655          $user1 = self::getDataGenerator()->create_user();
3656          $user2 = self::getDataGenerator()->create_user();
3657  
3658          $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
3659          assign_capability('moodle/site:readallmessages', CAP_ALLOW, $authenticateduserrole->id, context_system::instance(), true);
3660  
3661          $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id, true));
3662      }
3663  
3664      /**
3665       * Tests the user can not always send a message if they are blocked just because they share a course.
3666       */
3667      public function test_can_send_message_even_if_blocked_shared_course() {
3668          $this->resetAfterTest();
3669  
3670          // Create some users.
3671          $user1 = self::getDataGenerator()->create_user();
3672          $user2 = self::getDataGenerator()->create_user();
3673  
3674          $course = self::getDataGenerator()->create_course();
3675  
3676          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3677          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3678  
3679          $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id, true));
3680      }
3681  
3682      /**
3683       * Tests the user can always send a message even if they are blocked because they share a course and
3684       * have the capability 'moodle/site:messageanyuser' at the course context.
3685       */
3686      public function test_can_send_message_even_if_blocked_shared_course_with_message_any_user_cap() {
3687          global $DB;
3688  
3689          $this->resetAfterTest();
3690  
3691          $editingteacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
3692  
3693          $teacher = self::getDataGenerator()->create_user();
3694          $student = self::getDataGenerator()->create_user();
3695  
3696          $course = self::getDataGenerator()->create_course();
3697  
3698          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $editingteacherrole->id);
3699          $this->getDataGenerator()->enrol_user($student->id, $course->id);
3700  
3701          assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $editingteacherrole->id,
3702              context_course::instance($course->id), true);
3703  
3704          // Check that the second user can no longer send the first user a message.
3705          $this->assertTrue(\core_message\api::can_send_message($student->id, $teacher->id, true));
3706      }
3707  
3708      /**
3709       * Test that calling to can_post_message() now shows debugging. MDL-65093.
3710       *
3711       * @deprecated since 3.8
3712       * @todo Final deprecation in MDL-66266
3713       */
3714      public function test_can_post_emits_debugging() {
3715          // Create some users.
3716          $user1 = self::getDataGenerator()->create_user();
3717          $user2 = self::getDataGenerator()->create_user();
3718  
3719          // Set as the first user.
3720          $this->setUser($user1);
3721  
3722          // With the default privacy setting, users can't message them.
3723          $this->assertFalse(\core_message\api::can_post_message($user2));
3724          $this->assertDebuggingCalled('\core_message\api::can_post_message is deprecated, please use ' .
3725              '\core_message\api::can_send_message instead.', DEBUG_DEVELOPER);
3726      }
3727  
3728      /**
3729       * Verify the expected behaviour of the can_send_message_to_conversation() method for authenticated users with default settings.
3730       */
3731      public function test_can_send_message_to_conversation_basic() {
3732          // Create some users.
3733          $user1 = self::getDataGenerator()->create_user();
3734          $user2 = self::getDataGenerator()->create_user();
3735          $user3 = self::getDataGenerator()->create_user();
3736  
3737          // Create an individual conversation between user1 and user2.
3738          $ic1 = \core_message\api::create_conversation(
3739              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3740              [
3741                  $user1->id,
3742                  $user2->id
3743              ]
3744          );
3745  
3746          // Create a group conversation between and users 1, 2 and 3.
3747          $gc1 = \core_message\api::create_conversation(
3748              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3749              [
3750                  $user1->id,
3751                  $user2->id,
3752                  $user3->id
3753              ]
3754          );
3755  
3756          // Get a self-conversation for user1.
3757          $sc1 = \core_message\api::get_self_conversation($user1->id);
3758  
3759          // For group conversations, there are no user privacy checks, so only membership in the conversation is needed.
3760          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3761  
3762          // For self conversations, there are no user privacy checks, so only membership in the conversation is needed.
3763          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $sc1->id));
3764  
3765          // For individual conversations, the default privacy setting of 'only contacts and course members' applies.
3766          // Users are not in the same course, nor are they contacts, so messages cannot be sent.
3767          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3768  
3769          // Enrol the users into the same course.
3770          $course = $this->getDataGenerator()->create_course();
3771          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3772          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3773  
3774          // After enrolling users to the course, they should be able to message them with the default privacy setting.
3775          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3776      }
3777  
3778      /**
3779       * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the sendmessage capability.
3780       */
3781      public function test_can_send_message_to_conversation_sendmessage_cap() {
3782          global $DB;
3783  
3784          $user1 = self::getDataGenerator()->create_user();
3785          $user2 = self::getDataGenerator()->create_user();
3786          $user3 = self::getDataGenerator()->create_user();
3787  
3788          // Enrol the users into the same course.
3789          $course = $this->getDataGenerator()->create_course();
3790          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3791          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3792          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3793  
3794          // Create an individual conversation between user1 and user2.
3795          $ic1 = \core_message\api::create_conversation(
3796              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3797              [
3798                  $user1->id,
3799                  $user2->id
3800              ]
3801          );
3802  
3803          // Group conversation between and users 1, 2 and 3.
3804          $gc1 = \core_message\api::create_conversation(
3805              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3806              [
3807                  $user1->id,
3808                  $user2->id,
3809                  $user3->id
3810              ]
3811          );
3812  
3813          // Default settings - user1 can send a message to both conversations.
3814          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3815          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3816  
3817          // Remove the capability to send a message.
3818          $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3819          unassign_capability('moodle/site:sendmessage', $roleids['user'], context_system::instance());
3820  
3821          // Verify that a user cannot send a message to either an individual or a group conversation.
3822          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3823          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3824      }
3825  
3826      /**
3827       * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the messageanyuser capability.
3828       */
3829      public function test_can_send_message_to_conversation_messageanyuser_cap() {
3830          global $DB;
3831  
3832          $user1 = self::getDataGenerator()->create_user();
3833          $user2 = self::getDataGenerator()->create_user();
3834          $user3 = self::getDataGenerator()->create_user();
3835  
3836          // Enrol the users into the same course.
3837          $course = $this->getDataGenerator()->create_course();
3838          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3839          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3840          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3841  
3842          // Create an individual conversation between user1 and user2.
3843          $ic1 = \core_message\api::create_conversation(
3844              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3845              [
3846                  $user1->id,
3847                  $user2->id
3848              ]
3849          );
3850  
3851          // Group conversation between and users 1, 2 and 3.
3852          $gc1 = \core_message\api::create_conversation(
3853              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3854              [
3855                  $user1->id,
3856                  $user2->id,
3857                  $user3->id
3858              ]
3859          );
3860  
3861          // Update the message preference for user2, so they can only be messaged by contacts.
3862          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3863  
3864          // Verify that the user cannot be contacted in the individual conversation and that groups are unaffected.
3865          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3866          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3867  
3868          // Assign the 'messageanyuser' capability to user1 at system context.
3869          $systemcontext = context_system::instance();
3870          $authenticateduser = $DB->get_record('role', ['shortname' => 'user']);
3871          assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, $systemcontext->id);
3872  
3873          // Check that user1 can now message user2 due to the capability, and that group conversations is again unaffected.
3874          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3875          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3876      }
3877  
3878      /**
3879       * Test verifying that users cannot send messages to conversations they are not a part of.
3880       */
3881      public function test_can_send_message_to_conversation_non_member() {
3882          // Create some users.
3883          $user1 = self::getDataGenerator()->create_user();
3884          $user2 = self::getDataGenerator()->create_user();
3885          $user3 = self::getDataGenerator()->create_user();
3886          $user4 = self::getDataGenerator()->create_user();
3887  
3888          // Enrol the users into the same course.
3889          $course = $this->getDataGenerator()->create_course();
3890          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3891          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3892          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3893          $this->getDataGenerator()->enrol_user($user4->id, $course->id);
3894  
3895          // Create an individual conversation between user1 and user2.
3896          $ic1 = \core_message\api::create_conversation(
3897              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3898              [
3899                  $user1->id,
3900                  $user2->id
3901              ]
3902          );
3903  
3904          // Create a group conversation between and users 1, 2 and 3.
3905          $gc1 = \core_message\api::create_conversation(
3906              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3907              [
3908                  $user1->id,
3909                  $user2->id,
3910                  $user3->id
3911              ]
3912          );
3913  
3914          // Get a self-conversation for user1.
3915          $sc1 = \core_message\api::get_self_conversation($user1->id);
3916  
3917          // Verify, non members cannot send a message.
3918          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $gc1->id));
3919          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $ic1->id));
3920          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $sc1->id));
3921      }
3922  
3923      /**
3924       * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts only.
3925       */
3926      public function test_can_send_message_to_conversation_privacy_contacts_only() {
3927          // Create some users.
3928          $user1 = self::getDataGenerator()->create_user();
3929          $user2 = self::getDataGenerator()->create_user();
3930          $user3 = self::getDataGenerator()->create_user();
3931  
3932          // Create an individual conversation between user1 and user2.
3933          $ic1 = \core_message\api::create_conversation(
3934              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3935              [
3936                  $user1->id,
3937                  $user2->id
3938              ]
3939          );
3940  
3941          // Create a group conversation between and users 1, 2 and 3.
3942          $gc1 = \core_message\api::create_conversation(
3943              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3944              [
3945                  $user1->id,
3946                  $user2->id,
3947                  $user3->id
3948              ]
3949          );
3950  
3951          // Set the message privacy preference to 'contacts only' for user 2.
3952          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3953  
3954          // Verify that user1 cannot send a message to the individual conversation, but that the group conversation is unaffected.
3955          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3956          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3957  
3958          // Now, simulate a contact request (and approval) between user1 and user2.
3959          \core_message\api::create_contact_request($user1->id, $user2->id);
3960          \core_message\api::confirm_contact_request($user1->id, $user2->id);
3961  
3962          // Verify user1 can now message user2 again via their individual conversation.
3963          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3964      }
3965  
3966      /**
3967       * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts / course members.
3968       */
3969      public function test_can_send_message_to_conversation_privacy_contacts_course() {
3970          // Create some users.
3971          $user1 = self::getDataGenerator()->create_user();
3972          $user2 = self::getDataGenerator()->create_user();
3973          $user3 = self::getDataGenerator()->create_user();
3974  
3975          // Set the message privacy preference to 'contacts + course members' for user 2.
3976          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
3977  
3978          // Create an individual conversation between user1 and user2.
3979          $ic1 = \core_message\api::create_conversation(
3980              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3981              [
3982                  $user1->id,
3983                  $user2->id
3984              ]
3985          );
3986  
3987          // Create a group conversation between and users 1, 2 and 3.
3988          $gc1 = \core_message\api::create_conversation(
3989              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3990              [
3991                  $user1->id,
3992                  $user2->id,
3993                  $user3->id
3994              ]
3995          );
3996  
3997          // Verify that users in a group conversation can message one another (i.e. privacy controls ignored).
3998          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3999  
4000          // Verify that user1 can not message user2 unless they are either contacts, or share a course.
4001          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
4002  
4003          // Enrol the users into the same course.
4004          $course = $this->getDataGenerator()->create_course();
4005          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
4006          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
4007          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
4008  
4009          // Verify that user1 can send a message to user2, based on the shared course, without being a contact.
4010          $this->assertFalse(\core_message\api::is_contact($user1->id, $user2->id));
4011          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
4012      }
4013  
4014      /**
4015       * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to any user.
4016       */
4017      public function test_can_send_message_to_conversation_privacy_sitewide() {
4018          // Create some users.
4019          $user1 = self::getDataGenerator()->create_user();
4020          $user2 = self::getDataGenerator()->create_user();
4021          $user3 = self::getDataGenerator()->create_user();
4022  
4023          // Create an individual conversation between user1 and user2.
4024          $ic1 = \core_message\api::create_conversation(
4025              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4026              [
4027                  $user1->id,
4028                  $user2->id
4029              ]
4030          );
4031  
4032          // Create a group conversation between and users 1, 2 and 3.
4033          $gc1 = \core_message\api::create_conversation(
4034              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4035              [
4036                  $user1->id,
4037                  $user2->id,
4038                  $user3->id
4039              ]
4040          );
4041  
4042          // By default, the messaging privacy dictates that users can only be contacted by contacts, and members of their courses.
4043          // Verify also, that groups are not restricted in this way.
4044          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
4045          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
4046  
4047          // Enable site-wide messagging privacy setting.
4048          // This enables a privacy option for users, allowing them to choose to be contactable by anybody on the site.
4049          set_config('messagingallusers', true);
4050  
4051          // Set the second user's preference to receive messages from everybody.
4052          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
4053  
4054          // Check that user1 can send user2 a message, and that the group conversation is unaffected.
4055          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
4056          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
4057  
4058          // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
4059          // and members sharing a course with her.
4060          set_config('messagingallusers', false);
4061  
4062          // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
4063          // Verify also that the group conversation is unaffected.
4064          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
4065          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
4066      }
4067  
4068      /**
4069       * Test verifying the behaviour of the can_send_message_to_conversation method when a user is blocked.
4070       */
4071      public function test_can_send_message_to_conversation_when_blocked() {
4072          $user1 = self::getDataGenerator()->create_user();
4073          $user2 = self::getDataGenerator()->create_user();
4074          $user3 = self::getDataGenerator()->create_user();
4075  
4076          // Create an individual conversation between user1 and user2.
4077          $ic1 = \core_message\api::create_conversation(
4078              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4079              [
4080                  $user1->id,
4081                  $user2->id
4082              ]
4083          );
4084  
4085          // Create a group conversation between and users 1, 2 and 3.
4086          $gc1 = \core_message\api::create_conversation(
4087              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4088              [
4089                  $user1->id,
4090                  $user2->id,
4091                  $user3->id
4092              ]
4093          );
4094  
4095          // Enrol the users into the same course.
4096          $course = $this->getDataGenerator()->create_course();
4097          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
4098          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
4099          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
4100  
4101          // Block the second user.
4102          \core_message\api::block_user($user1->id, $user2->id);
4103  
4104          // Check that user2 can not send user1 a message in their individual conversation.
4105          $this->assertFalse(\core_message\api::can_send_message_to_conversation($user2->id, $ic1->id));
4106  
4107          // Verify that group conversations are unaffected.
4108          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
4109          $this->assertTrue(\core_message\api::can_send_message_to_conversation($user2->id, $gc1->id));
4110      }
4111  
4112      /**
4113       * Tests get_user_privacy_messaging_preference method.
4114       */
4115      public function test_get_user_privacy_messaging_preference() {
4116          // Create some users.
4117          $user1 = self::getDataGenerator()->create_user();
4118          $user2 = self::getDataGenerator()->create_user();
4119          $user3 = self::getDataGenerator()->create_user();
4120  
4121          // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
4122          set_config('messagingallusers', true);
4123  
4124          // Set some user preferences.
4125          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user1->id);
4126          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
4127  
4128          // Check the returned value for each user.
4129          $this->assertEquals(
4130              \core_message\api::MESSAGE_PRIVACY_SITE,
4131              \core_message\api::get_user_privacy_messaging_preference($user1->id)
4132          );
4133          $this->assertEquals(
4134              \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS,
4135              \core_message\api::get_user_privacy_messaging_preference($user2->id)
4136          );
4137          $this->assertEquals(
4138              \core_message\api::MESSAGE_PRIVACY_SITE,
4139              \core_message\api::get_user_privacy_messaging_preference($user3->id)
4140          );
4141  
4142          // Disable site-wide messagging privacy setting. The user will be able to receive messages from members of their course.
4143          set_config('messagingallusers', false);
4144  
4145          // Check the returned value for each user.
4146          $this->assertEquals(
4147              \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER,
4148              \core_message\api::get_user_privacy_messaging_preference($user1->id)
4149          );
4150          $this->assertEquals(
4151              \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS,
4152              \core_message\api::get_user_privacy_messaging_preference($user2->id)
4153          );
4154          $this->assertEquals(
4155              \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER,
4156              \core_message\api::get_user_privacy_messaging_preference($user3->id)
4157          );
4158      }
4159  
4160      /**
4161       * Tests that when blocking messages from non-contacts is enabled that
4162       * non-contacts trying to send a message return false.
4163       */
4164      public function test_is_user_non_contact_blocked() {
4165          // Create some users.
4166          $user1 = self::getDataGenerator()->create_user();
4167          $user2 = self::getDataGenerator()->create_user();
4168  
4169          // Set as the first user.
4170          $this->setUser($user1);
4171  
4172          // By default, user only can be messaged by contacts and members of any of his/her courses.
4173          $this->assertTrue(\core_message\api::is_user_non_contact_blocked($user2));
4174          $this->assertDebuggingCalled();
4175  
4176          // Enable all users privacy messaging and check now the default user's preference has been set to allow receiving
4177          // messages from everybody.
4178          set_config('messagingallusers', true);
4179          // Check that the return result is now false because any site user can contact him/her.
4180          $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
4181          $this->assertDebuggingCalled();
4182  
4183          // Set the second user's preference to not receive messages from non-contacts.
4184          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
4185          // Check that the return result is still true (because is even more restricted).
4186          $this->assertTrue(\core_message\api::is_user_non_contact_blocked($user2));
4187          $this->assertDebuggingCalled();
4188  
4189          // Add the first user as a contact for the second user.
4190          \core_message\api::add_contact($user2->id, $user1->id);
4191  
4192          // Check that the return result is now false.
4193          $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
4194          $this->assertDebuggingCalled();
4195  
4196          // Set the second user's preference to receive messages from course members.
4197          set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
4198          // Check that the return result is still false (because $user1 is still his/her contact).
4199          $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
4200          $this->assertDebuggingCalled();
4201      }
4202  
4203      /**
4204       * Tests that we return true when a user is blocked, or false
4205       * if they are not blocked.
4206       */
4207      public function test_is_user_blocked() {
4208          // Create some users.
4209          $user1 = self::getDataGenerator()->create_user();
4210          $user2 = self::getDataGenerator()->create_user();
4211  
4212          // Set the user.
4213          $this->setUser($user1);
4214  
4215          // User shouldn't be blocked.
4216          $this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
4217          $this->assertDebuggingCalled();
4218  
4219          // Block the user.
4220          \core_message\api::block_user($user1->id, $user2->id);
4221  
4222          // User should be blocked.
4223          $this->assertTrue(\core_message\api::is_user_blocked($user1->id, $user2->id));
4224          $this->assertDebuggingCalled();
4225  
4226          // Unblock the user.
4227          \core_message\api::unblock_user($user1->id, $user2->id);
4228          $this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
4229          $this->assertDebuggingCalled();
4230      }
4231  
4232      /**
4233       * Tests that the admin is not blocked even if someone has chosen to block them.
4234       */
4235      public function test_is_user_blocked_as_admin() {
4236          // Create a user.
4237          $user1 = self::getDataGenerator()->create_user();
4238  
4239          // Set the user.
4240          $this->setUser($user1);
4241  
4242          // Block the admin user.
4243          \core_message\api::block_user($user1->id, 2);
4244  
4245          // Now change to the admin user.
4246          $this->setAdminUser();
4247  
4248          // As the admin you should still be able to send messages to the user.
4249          $this->assertFalse(\core_message\api::is_user_blocked($user1->id));
4250          $this->assertDebuggingCalled();
4251      }
4252  
4253      /*
4254       * Tes get_message_processor api.
4255       */
4256      public function test_get_message_processor() {
4257          $processors = get_message_processors(true);
4258          if (empty($processors)) {
4259              $this->markTestSkipped("No message processors found");
4260          }
4261  
4262          $name = key($processors);
4263          $processor = current($processors);
4264          $testprocessor = \core_message\api::get_message_processor($name);
4265          $this->assertEquals($processor->name, $testprocessor->name);
4266          $this->assertEquals($processor->enabled, $testprocessor->enabled);
4267          $this->assertEquals($processor->available, $testprocessor->available);
4268          $this->assertEquals($processor->configured, $testprocessor->configured);
4269  
4270          // Disable processor and test.
4271          \core_message\api::update_processor_status($testprocessor, 0);
4272          $testprocessor = \core_message\api::get_message_processor($name, true);
4273          $this->assertEmpty($testprocessor);
4274          $testprocessor = \core_message\api::get_message_processor($name);
4275          $this->assertEquals($processor->name, $testprocessor->name);
4276          $this->assertEquals(0, $testprocessor->enabled);
4277  
4278          // Enable again and test.
4279          \core_message\api::update_processor_status($testprocessor, 1);
4280          $testprocessor = \core_message\api::get_message_processor($name, true);
4281          $this->assertEquals($processor->name, $testprocessor->name);
4282          $this->assertEquals(1, $testprocessor->enabled);
4283          $testprocessor = \core_message\api::get_message_processor($name);
4284          $this->assertEquals($processor->name, $testprocessor->name);
4285          $this->assertEquals(1, $testprocessor->enabled);
4286      }
4287  
4288      /**
4289       * Test method update_processor_status.
4290       */
4291      public function test_update_processor_status() {
4292          $processors = get_message_processors();
4293          if (empty($processors)) {
4294              $this->markTestSkipped("No message processors found");
4295          }
4296          $name = key($processors);
4297          $testprocessor = current($processors);
4298  
4299          // Enable.
4300          \core_message\api::update_processor_status($testprocessor, 1);
4301          $testprocessor = \core_message\api::get_message_processor($name);
4302          $this->assertEquals(1, $testprocessor->enabled);
4303  
4304          // Disable.
4305          \core_message\api::update_processor_status($testprocessor, 0);
4306          $testprocessor = \core_message\api::get_message_processor($name);
4307          $this->assertEquals(0, $testprocessor->enabled);
4308  
4309          // Enable again.
4310          \core_message\api::update_processor_status($testprocessor, 1);
4311          $testprocessor = \core_message\api::get_message_processor($name);
4312          $this->assertEquals(1, $testprocessor->enabled);
4313      }
4314  
4315      /**
4316       * Test method is_user_enabled.
4317       */
4318      public function is_user_enabled() {
4319          $processors = get_message_processors();
4320          if (empty($processors)) {
4321              $this->markTestSkipped("No message processors found");
4322          }
4323          $name = key($processors);
4324          $testprocessor = current($processors);
4325  
4326          // Enable.
4327          \core_message\api::update_processor_status($testprocessor, 1);
4328          $status = \core_message\api::is_processor_enabled($name);
4329          $this->assertEquals(1, $status);
4330  
4331          // Disable.
4332          \core_message\api::update_processor_status($testprocessor, 0);
4333          $status = \core_message\api::is_processor_enabled($name);
4334          $this->assertEquals(0, $status);
4335  
4336          // Enable again.
4337          \core_message\api::update_processor_status($testprocessor, 1);
4338          $status = \core_message\api::is_processor_enabled($name);
4339          $this->assertEquals(1, $status);
4340      }
4341  
4342      /**
4343       * Test retrieving messages by providing a minimum timecreated value.
4344       */
4345      public function test_get_messages_time_from_only() {
4346          // Create some users.
4347          $user1 = self::getDataGenerator()->create_user();
4348          $user2 = self::getDataGenerator()->create_user();
4349  
4350          // The person doing the search.
4351          $this->setUser($user1);
4352  
4353          // Send some messages back and forth.
4354          $time = 1;
4355          $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
4356          $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
4357          $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
4358          $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
4359  
4360          // Retrieve the messages from $time, which should be all of them.
4361          $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time);
4362  
4363          // Confirm the message data is correct.
4364          $this->assertEquals(4, count($messages));
4365  
4366          $message1 = $messages[0];
4367          $message2 = $messages[1];
4368          $message3 = $messages[2];
4369          $message4 = $messages[3];
4370  
4371          $this->assertContains('Message 1', $message1->text);
4372          $this->assertContains('Message 2', $message2->text);
4373          $this->assertContains('Message 3', $message3->text);
4374          $this->assertContains('Message 4', $message4->text);
4375  
4376          // Retrieve the messages from $time + 3, which should only be the 2 last messages.
4377          $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 3);
4378  
4379          // Confirm the message data is correct.
4380          $this->assertEquals(2, count($messages));
4381  
4382          $message1 = $messages[0];
4383          $message2 = $messages[1];
4384  
4385          $this->assertContains('Message 3', $message1->text);
4386          $this->assertContains('Message 4', $message2->text);
4387      }
4388  
4389      /**
4390       * Test retrieving messages by providing a maximum timecreated value.
4391       */
4392      public function test_get_messages_time_to_only() {
4393          // Create some users.
4394          $user1 = self::getDataGenerator()->create_user();
4395          $user2 = self::getDataGenerator()->create_user();
4396  
4397          // The person doing the search.
4398          $this->setUser($user1);
4399  
4400          // Send some messages back and forth.
4401          $time = 1;
4402          $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
4403          $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
4404          $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
4405          $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
4406  
4407          // Retrieve the messages up until $time + 4, which should be all of them.
4408          $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 4);
4409  
4410          // Confirm the message data is correct.
4411          $this->assertEquals(4, count($messages));
4412  
4413          $message1 = $messages[0];
4414          $message2 = $messages[1];
4415          $message3 = $messages[2];
4416          $message4 = $messages[3];
4417  
4418          $this->assertContains('Message 1', $message1->text);
4419          $this->assertContains('Message 2', $message2->text);
4420          $this->assertContains('Message 3', $message3->text);
4421          $this->assertContains('Message 4', $message4->text);
4422  
4423          // Retrieve the messages up until $time + 2, which should be the first two.
4424          $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 2);
4425  
4426          // Confirm the message data is correct.
4427          $this->assertEquals(2, count($messages));
4428  
4429          $message1 = $messages[0];
4430          $message2 = $messages[1];
4431  
4432          $this->assertContains('Message 1', $message1->text);
4433          $this->assertContains('Message 2', $message2->text);
4434      }
4435  
4436      /**
4437       * Test retrieving messages by providing a minimum and maximum timecreated value.
4438       */
4439      public function test_get_messages_time_from_and_to() {
4440          // Create some users.
4441          $user1 = self::getDataGenerator()->create_user();
4442          $user2 = self::getDataGenerator()->create_user();
4443  
4444          // The person doing the search.
4445          $this->setUser($user1);
4446  
4447          // Send some messages back and forth.
4448          $time = 1;
4449          $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
4450          $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
4451          $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
4452          $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
4453  
4454          // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
4455          $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 2, $time + 3);
4456  
4457          // Confirm the message data is correct.
4458          $this->assertEquals(2, count($messages));
4459  
4460          $message1 = $messages[0];
4461          $message2 = $messages[1];
4462  
4463          $this->assertContains('Message 2', $message1->text);
4464          $this->assertContains('Message 3', $message2->text);
4465      }
4466  
4467      /**
4468       * Test returning blocked users.
4469       */
4470      public function test_get_blocked_users() {
4471          global $USER;
4472  
4473          // Set this user as the admin.
4474          $this->setAdminUser();
4475  
4476          // Create a user to add to the admin's contact list.
4477          $user1 = $this->getDataGenerator()->create_user();
4478          $user2 = $this->getDataGenerator()->create_user();
4479  
4480          // Add users to the admin's contact list.
4481          \core_message\api::block_user($USER->id, $user2->id);
4482  
4483          $this->assertCount(1, \core_message\api::get_blocked_users($USER->id));
4484  
4485          // Block other user.
4486          \core_message\api::block_user($USER->id, $user1->id);
4487          $this->assertCount(2, \core_message\api::get_blocked_users($USER->id));
4488  
4489          // Test deleting users.
4490          delete_user($user1);
4491          $this->assertCount(1, \core_message\api::get_blocked_users($USER->id));
4492      }
4493  
4494      /**
4495       * Test returning contacts with unread message count.
4496       */
4497      public function test_get_contacts_with_unread_message_count() {
4498          global $DB;
4499  
4500          $user1 = self::getDataGenerator()->create_user();
4501          $user2 = self::getDataGenerator()->create_user();
4502          $user3 = self::getDataGenerator()->create_user();
4503          $user4 = self::getDataGenerator()->create_user();
4504  
4505          // Add the users to each of their contacts.
4506          \core_message\api::add_contact($user1->id, $user2->id);
4507          \core_message\api::add_contact($user2->id, $user3->id);
4508  
4509          $this->send_fake_message($user1, $user2);
4510          $this->send_fake_message($user1, $user2);
4511          $this->send_fake_message($user1, $user2);
4512          $message4id = $this->send_fake_message($user1, $user2);
4513  
4514          $this->send_fake_message($user3, $user2);
4515          $message6id = $this->send_fake_message($user3, $user2);
4516          $this->send_fake_message($user3, $user2);
4517          $this->send_fake_message($user3, $user2);
4518          $this->send_fake_message($user3, $user2);
4519  
4520          // Send a message that should never be included as the user is not a contact.
4521          $this->send_fake_message($user4, $user2);
4522  
4523          // Get the contacts and the unread message count.
4524          $messages = \core_message\api::get_contacts_with_unread_message_count($user2->id);
4525  
4526          // Confirm the size is correct.
4527          $this->assertCount(2, $messages);
4528          ksort($messages);
4529  
4530          $messageinfo1 = array_shift($messages);
4531          $messageinfo2 = array_shift($messages);
4532  
4533          $this->assertEquals($user1->id, $messageinfo1->id);
4534          $this->assertEquals(4, $messageinfo1->messagecount);
4535          $this->assertEquals($user3->id, $messageinfo2->id);
4536          $this->assertEquals(5, $messageinfo2->messagecount);
4537  
4538          // Mark some of the messages as read.
4539          $m4 = $DB->get_record('messages', ['id' => $message4id]);
4540          $m6 = $DB->get_record('messages', ['id' => $message6id]);
4541          \core_message\api::mark_message_as_read($user2->id, $m4);
4542          \core_message\api::mark_message_as_read($user2->id, $m6);
4543  
4544          // Get the contacts and the unread message count.
4545          $messages = \core_message\api::get_contacts_with_unread_message_count($user2->id);
4546  
4547          // Confirm the size is correct.
4548          $this->assertCount(2, $messages);
4549          ksort($messages);
4550  
4551          // Confirm read messages are not included.
4552          $messageinfo1 = array_shift($messages);
4553          $messageinfo2 = array_shift($messages);
4554          $this->assertEquals($user1->id, $messageinfo1->id);
4555          $this->assertEquals(3, $messageinfo1->messagecount);
4556          $this->assertEquals($user3->id, $messageinfo2->id);
4557          $this->assertEquals(4, $messageinfo2->messagecount);
4558  
4559          // Now, let's populate the database with messages from user2 to user 1.
4560          $this->send_fake_message($user2, $user1);
4561          $this->send_fake_message($user2, $user1);
4562          $messageid = $this->send_fake_message($user2, $user1);
4563  
4564          // Send a message that should never be included as the user is not a contact.
4565          $this->send_fake_message($user4, $user1);
4566  
4567          // Get the contacts and the unread message count.
4568          $messages = \core_message\api::get_contacts_with_unread_message_count($user1->id);
4569  
4570          // Confirm the size is correct.
4571          $this->assertCount(1, $messages);
4572          $messageinfo1 = array_shift($messages);
4573          $this->assertEquals($user2->id, $messageinfo1->id);
4574          $this->assertEquals(3, $messageinfo1->messagecount);
4575  
4576          // Mark the last message as read.
4577          $m = $DB->get_record('messages', ['id' => $messageid]);
4578          \core_message\api::mark_message_as_read($user1->id, $m);
4579  
4580          $messages = \core_message\api::get_contacts_with_unread_message_count($user1->id);
4581  
4582          // Confirm the size is correct.
4583          $this->assertCount(1, $messages);
4584  
4585          // Confirm read messages are not included.
4586          $messageinfo1 = array_shift($messages);
4587          $this->assertEquals($user2->id, $messageinfo1->id);
4588          $this->assertEquals(2, $messageinfo1->messagecount);
4589      }
4590  
4591      /**
4592       * Test returning contacts with unread message count when there are no messages.
4593       */
4594      public function test_get_contacts_with_unread_message_count_no_messages() {
4595          $user1 = self::getDataGenerator()->create_user();
4596          $user2 = self::getDataGenerator()->create_user();
4597  
4598          // Add the users to each of their contacts.
4599          \core_message\api::add_contact($user2->id, $user1->id);
4600  
4601          // Check we get the correct message count.
4602          $messages = \core_message\api::get_contacts_with_unread_message_count($user2->id);
4603  
4604          // Confirm the size is correct.
4605          $this->assertCount(1, $messages);
4606  
4607          $messageinfo = array_shift($messages);
4608  
4609          $this->assertEquals($user1->id, $messageinfo->id);
4610          $this->assertEquals(0, $messageinfo->messagecount);
4611      }
4612  
4613      /**
4614       * Test returning non-contacts with unread message count.
4615       */
4616      public function test_get_non_contacts_with_unread_message_count() {
4617          global $DB;
4618  
4619          $user1 = self::getDataGenerator()->create_user();
4620          $user2 = self::getDataGenerator()->create_user();
4621          $user3 = self::getDataGenerator()->create_user();
4622          $user4 = self::getDataGenerator()->create_user();
4623  
4624          // Add a user to the contact list of the users we are testing this function with.
4625          \core_message\api::add_contact($user1->id, $user4->id);
4626          \core_message\api::add_contact($user2->id, $user4->id);
4627  
4628          $this->send_fake_message($user1, $user2);
4629          $this->send_fake_message($user1, $user2);
4630          $this->send_fake_message($user1, $user2);
4631          $message4id = $this->send_fake_message($user1, $user2);
4632  
4633          $this->send_fake_message($user3, $user2);
4634          $message6id = $this->send_fake_message($user3, $user2);
4635          $this->send_fake_message($user3, $user2);
4636          $this->send_fake_message($user3, $user2);
4637          $this->send_fake_message($user3, $user2);
4638  
4639          // Send a message that should never be included as the user is a contact.
4640          $this->send_fake_message($user4, $user2);
4641  
4642          // Get the non-contacts and the unread message count.
4643          $messages = \core_message\api::get_non_contacts_with_unread_message_count($user2->id);
4644  
4645          // Check we get the correct message count.
4646          ksort($messages);
4647          $this->assertCount(2, $messages);
4648          $messageinfo1 = array_shift($messages);
4649          $messageinfo2 = array_shift($messages);
4650          $this->assertEquals($user1->id, $messageinfo1->id);
4651          $this->assertEquals(4, $messageinfo1->messagecount);
4652          $this->assertEquals($user3->id, $messageinfo2->id);
4653          $this->assertEquals(5, $messageinfo2->messagecount);
4654  
4655          // Mark some of the messages as read.
4656          $m4 = $DB->get_record('messages', ['id' => $message4id]);
4657          $m6 = $DB->get_record('messages', ['id' => $message6id]);
4658          \core_message\api::mark_message_as_read($user2->id, $m4);
4659          \core_message\api::mark_message_as_read($user2->id, $m6);
4660  
4661          // Get the non-contacts and the unread message count.
4662          $messages = \core_message\api::get_non_contacts_with_unread_message_count($user2->id);
4663  
4664          // Check the marked message is not returned in the message count.
4665          ksort($messages);
4666          $this->assertCount(2, $messages);
4667          $messageinfo1 = array_shift($messages);
4668          $messageinfo2 = array_shift($messages);
4669          $this->assertEquals($user1->id, $messageinfo1->id);
4670          $this->assertEquals(3, $messageinfo1->messagecount);
4671          $this->assertEquals($user3->id, $messageinfo2->id);
4672          $this->assertEquals(4, $messageinfo2->messagecount);
4673  
4674          // Now, let's populate the database with messages from user2 to user 1.
4675          $this->send_fake_message($user2, $user1);
4676          $this->send_fake_message($user2, $user1);
4677          $messageid = $this->send_fake_message($user2, $user1);
4678  
4679          // Send a message that should never be included as the user is a contact.
4680          $this->send_fake_message($user4, $user1);
4681  
4682          // Get the non-contacts and the unread message count.
4683          $messages = \core_message\api::get_non_contacts_with_unread_message_count($user1->id);
4684  
4685          // Confirm the size is correct.
4686          $this->assertCount(1, $messages);
4687          $messageinfo1 = array_shift($messages);
4688          $this->assertEquals($user2->id, $messageinfo1->id);
4689          $this->assertEquals(3, $messageinfo1->messagecount);
4690  
4691          // Mark the last message as read.
4692          $m = $DB->get_record('messages', ['id' => $messageid]);
4693          \core_message\api::mark_message_as_read($user1->id, $m);
4694  
4695          // Get the non-contacts and the unread message count.
4696          $messages = \core_message\api::get_non_contacts_with_unread_message_count($user1->id);
4697  
4698          // Check the marked message is not returned in the message count.
4699          $this->assertCount(1, $messages);
4700          $messageinfo1 = array_shift($messages);
4701          $this->assertEquals($user2->id, $messageinfo1->id);
4702          $this->assertEquals(2, $messageinfo1->messagecount);
4703      }
4704  
4705      /**
4706       * Test marking a message as read.
4707       */
4708      public function test_mark_message_as_read() {
4709          global $DB;
4710  
4711          $user1 = self::getDataGenerator()->create_user();
4712          $user2 = self::getDataGenerator()->create_user();
4713  
4714          $this->send_fake_message($user1, $user2);
4715          $m2id = $this->send_fake_message($user1, $user2);
4716          $this->send_fake_message($user2, $user1);
4717          $m4id = $this->send_fake_message($user2, $user1);
4718  
4719          $m2 = $DB->get_record('messages', ['id' => $m2id]);
4720          $m4 = $DB->get_record('messages', ['id' => $m4id]);
4721          \core_message\api::mark_message_as_read($user2->id, $m2, 11);
4722          \core_message\api::mark_message_as_read($user1->id, $m4, 12);
4723  
4724          // Confirm there are two user actions.
4725          $muas = $DB->get_records('message_user_actions', [], 'timecreated ASC');
4726          $this->assertEquals(2, count($muas));
4727  
4728          // Confirm they are correct.
4729          $mua1 = array_shift($muas);
4730          $mua2 = array_shift($muas);
4731  
4732          // Confirm first action.
4733          $this->assertEquals($user2->id, $mua1->userid);
4734          $this->assertEquals($m2id, $mua1->messageid);
4735          $this->assertEquals(\core_message\api::MESSAGE_ACTION_READ, $mua1->action);
4736          $this->assertEquals(11, $mua1->timecreated);
4737  
4738          // Confirm second action.
4739          $this->assertEquals($user1->id, $mua2->userid);
4740          $this->assertEquals($m4id, $mua2->messageid);
4741          $this->assertEquals(\core_message\api::MESSAGE_ACTION_READ, $mua2->action);
4742          $this->assertEquals(12, $mua2->timecreated);
4743      }
4744  
4745      /**
4746       * Test marking a notification as read.
4747       */
4748      public function test_mark_notification_as_read() {
4749          global $DB;
4750  
4751          $user1 = self::getDataGenerator()->create_user();
4752          $user2 = self::getDataGenerator()->create_user();
4753  
4754          $this->send_fake_message($user1, $user2, 'Notification 1', 1);
4755          $n2id = $this->send_fake_message($user1, $user2, 'Notification 2', 1);
4756          $this->send_fake_message($user2, $user1, 'Notification 3', 1);
4757          $n4id = $this->send_fake_message($user2, $user1, 'Notification 4', 1);
4758  
4759          $n2 = $DB->get_record('notifications', ['id' => $n2id]);
4760          $n4 = $DB->get_record('notifications', ['id' => $n4id]);
4761  
4762          \core_message\api::mark_notification_as_read($n2, 11);
4763          \core_message\api::mark_notification_as_read($n4, 12);
4764  
4765          // Retrieve the notifications.
4766          $n2 = $DB->get_record('notifications', ['id' => $n2id]);
4767          $n4 = $DB->get_record('notifications', ['id' => $n4id]);
4768  
4769          // Confirm they have been marked as read.
4770          $this->assertEquals(11, $n2->timeread);
4771          $this->assertEquals(12, $n4->timeread);
4772      }
4773  
4774      /**
4775       * Test a conversation is not returned if there is none.
4776       */
4777      public function test_get_conversation_between_users_no_conversation() {
4778          $user1 = self::getDataGenerator()->create_user();
4779          $user2 = self::getDataGenerator()->create_user();
4780  
4781          $this->assertFalse(\core_message\api::get_conversation_between_users([$user1->id, $user2->id]));
4782      }
4783  
4784      /**
4785       * Test we can return a conversation that exists between users.
4786       */
4787      public function test_get_conversation_between_users_with_existing_conversation() {
4788          $user1 = self::getDataGenerator()->create_user();
4789          $user2 = self::getDataGenerator()->create_user();
4790  
4791          $conversationid = \core_message\api::create_conversation_between_users([$user1->id, $user2->id]);
4792          $this->assertDebuggingCalled();
4793  
4794          $this->assertEquals($conversationid,
4795              \core_message\api::get_conversation_between_users([$user1->id, $user2->id]));
4796      }
4797  
4798      /**
4799       * Test count_conversation_members for non existing conversation.
4800       */
4801      public function test_count_conversation_members_no_existing_conversation() {
4802          $this->assertEquals(0,
4803              \core_message\api::count_conversation_members(0));
4804      }
4805  
4806      /**
4807       * Test count_conversation_members for existing conversation.
4808       */
4809      public function test_count_conversation_members_existing_conversation() {
4810          $user1 = self::getDataGenerator()->create_user();
4811          $user2 = self::getDataGenerator()->create_user();
4812  
4813          $conversation = \core_message\api::create_conversation(
4814              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4815              [
4816                  $user1->id,
4817                  $user2->id
4818              ]
4819          );
4820          $conversationid = $conversation->id;
4821  
4822          $this->assertEquals(2,
4823              \core_message\api::count_conversation_members($conversationid));
4824      }
4825  
4826      /**
4827       * Test add_members_to_conversation for an individual conversation.
4828       */
4829      public function test_add_members_to_individual_conversation() {
4830          $user1 = self::getDataGenerator()->create_user();
4831          $user2 = self::getDataGenerator()->create_user();
4832          $user3 = self::getDataGenerator()->create_user();
4833  
4834          $conversation = \core_message\api::create_conversation(
4835              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4836              [
4837                  $user1->id,
4838                  $user2->id
4839              ]
4840          );
4841          $conversationid = $conversation->id;
4842  
4843          $this->expectException('moodle_exception');
4844          \core_message\api::add_members_to_conversation([$user3->id], $conversationid);
4845      }
4846  
4847      /**
4848       * Test add_members_to_conversation for existing conversation.
4849       */
4850      public function test_add_members_to_existing_conversation() {
4851          $user1 = self::getDataGenerator()->create_user();
4852          $user2 = self::getDataGenerator()->create_user();
4853          $user3 = self::getDataGenerator()->create_user();
4854  
4855          $conversation = \core_message\api::create_conversation(
4856              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4857              [
4858                  $user1->id,
4859                  $user2->id
4860              ]
4861          );
4862          $conversationid = $conversation->id;
4863  
4864          $this->assertNull(\core_message\api::add_members_to_conversation([$user3->id], $conversationid));
4865          $this->assertEquals(3,
4866              \core_message\api::count_conversation_members($conversationid));
4867      }
4868  
4869      /**
4870       * Test add_members_to_conversation for non existing conversation.
4871       */
4872      public function test_add_members_to_no_existing_conversation() {
4873          $user1 = self::getDataGenerator()->create_user();
4874  
4875          // Throw dml_missing_record_exception for non existing conversation.
4876          $this->expectException('dml_missing_record_exception');
4877          \core_message\api::add_members_to_conversation([$user1->id], 0);
4878      }
4879  
4880      /**
4881       * Test add_member_to_conversation for non existing user.
4882       */
4883      public function test_add_members_to_no_existing_user() {
4884          $user1 = self::getDataGenerator()->create_user();
4885          $user2 = self::getDataGenerator()->create_user();
4886  
4887          $conversation = \core_message\api::create_conversation(
4888              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4889              [
4890                  $user1->id,
4891                  $user2->id
4892              ]
4893          );
4894          $conversationid = $conversation->id;
4895  
4896          // Don't throw an error for non existing user, but don't add it as a member.
4897          $this->assertNull(\core_message\api::add_members_to_conversation([0], $conversationid));
4898          $this->assertEquals(2,
4899              \core_message\api::count_conversation_members($conversationid));
4900      }
4901  
4902      /**
4903       * Test add_members_to_conversation for current conversation member.
4904       */
4905      public function test_add_members_to_current_conversation_member() {
4906          $user1 = self::getDataGenerator()->create_user();
4907          $user2 = self::getDataGenerator()->create_user();
4908  
4909          $conversation = \core_message\api::create_conversation(
4910              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4911              [
4912                  $user1->id,
4913                  $user2->id
4914              ]
4915          );
4916          $conversationid = $conversation->id;
4917  
4918          // Don't add as a member a user that is already conversation member.
4919          $this->assertNull(\core_message\api::add_members_to_conversation([$user1->id], $conversationid));
4920          $this->assertEquals(2,
4921              \core_message\api::count_conversation_members($conversationid));
4922      }
4923  
4924      /**
4925       * Test add_members_to_conversation for multiple users.
4926       */
4927      public function test_add_members_for_multiple_users() {
4928          $user1 = self::getDataGenerator()->create_user();
4929          $user2 = self::getDataGenerator()->create_user();
4930          $user3 = self::getDataGenerator()->create_user();
4931          $user4 = self::getDataGenerator()->create_user();
4932  
4933          $conversation = \core_message\api::create_conversation(
4934              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4935              [
4936                  $user1->id,
4937                  $user2->id
4938              ]
4939          );
4940          $conversationid = $conversation->id;
4941  
4942          $this->assertNull(\core_message\api::add_members_to_conversation([$user3->id, $user4->id], $conversationid));
4943          $this->assertEquals(4,
4944              \core_message\api::count_conversation_members($conversationid));
4945      }
4946  
4947      /**
4948       * Test add_members_to_conversation for multiple users, included non existing and current conversation members
4949       */
4950      public function test_add_members_for_multiple_not_valid_users() {
4951          $user1 = self::getDataGenerator()->create_user();
4952          $user2 = self::getDataGenerator()->create_user();
4953          $user3 = self::getDataGenerator()->create_user();
4954  
4955          $conversation = \core_message\api::create_conversation(
4956              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4957              [
4958                  $user1->id,
4959                  $user2->id
4960              ]
4961          );
4962          $conversationid = $conversation->id;
4963  
4964          // Don't throw errors, but don't add as members users don't exist or are already conversation members.
4965          $this->assertNull(\core_message\api::add_members_to_conversation([$user3->id, $user1->id, 0], $conversationid));
4966          $this->assertEquals(3,
4967              \core_message\api::count_conversation_members($conversationid));
4968      }
4969  
4970      /**
4971       * Test remove_members_from_conversation for individual conversation.
4972       */
4973      public function test_remove_members_from_individual_conversation() {
4974          $user1 = self::getDataGenerator()->create_user();
4975          $user2 = self::getDataGenerator()->create_user();
4976  
4977          $conversation = \core_message\api::create_conversation(
4978              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4979              [
4980                  $user1->id,
4981                  $user2->id
4982              ]
4983          );
4984          $conversationid = $conversation->id;
4985  
4986          $this->expectException('moodle_exception');
4987          \core_message\api::remove_members_from_conversation([$user1->id], $conversationid);
4988      }
4989  
4990      /**
4991       * Test remove_members_from_conversation for existing conversation.
4992       */
4993      public function test_remove_members_from_existing_conversation() {
4994          $user1 = self::getDataGenerator()->create_user();
4995          $user2 = self::getDataGenerator()->create_user();
4996  
4997          $conversation = \core_message\api::create_conversation(
4998              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
4999              [
5000                  $user1->id,
5001                  $user2->id
5002              ]
5003          );
5004          $conversationid = $conversation->id;
5005  
5006          $this->assertNull(\core_message\api::remove_members_from_conversation([$user1->id], $conversationid));
5007          $this->assertEquals(1,
5008              \core_message\api::count_conversation_members($conversationid));
5009      }
5010  
5011      /**
5012       * Test remove_members_from_conversation for non existing conversation.
5013       */
5014      public function test_remove_members_from_no_existing_conversation() {
5015          $user1 = self::getDataGenerator()->create_user();
5016  
5017          // Throw dml_missing_record_exception for non existing conversation.
5018          $this->expectException('dml_missing_record_exception');
5019          \core_message\api::remove_members_from_conversation([$user1->id], 0);
5020      }
5021  
5022      /**
5023       * Test remove_members_from_conversation for non existing user.
5024       */
5025      public function test_remove_members_for_no_existing_user() {
5026          $user1 = self::getDataGenerator()->create_user();
5027          $user2 = self::getDataGenerator()->create_user();
5028  
5029          $conversation = \core_message\api::create_conversation(
5030              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5031              [
5032                  $user1->id,
5033                  $user2->id
5034              ]
5035          );
5036          $conversationid = $conversation->id;
5037  
5038          $this->assertNull(\core_message\api::remove_members_from_conversation([0], $conversationid));
5039          $this->assertEquals(2,
5040              \core_message\api::count_conversation_members($conversationid));
5041      }
5042  
5043      /**
5044       * Test remove_members_from_conversation for multiple users.
5045       */
5046      public function test_remove_members_for_multiple_users() {
5047          $user1 = self::getDataGenerator()->create_user();
5048          $user2 = self::getDataGenerator()->create_user();
5049          $user3 = self::getDataGenerator()->create_user();
5050          $user4 = self::getDataGenerator()->create_user();
5051  
5052          $conversation = \core_message\api::create_conversation(
5053              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5054              [
5055                  $user1->id,
5056                  $user2->id
5057              ]
5058          );
5059          $conversationid = $conversation->id;
5060  
5061          $this->assertNull(\core_message\api::add_members_to_conversation([$user3->id, $user4->id], $conversationid));
5062          $this->assertNull(\core_message\api::remove_members_from_conversation([$user3->id, $user4->id], $conversationid));
5063          $this->assertEquals(2,
5064              \core_message\api::count_conversation_members($conversationid));
5065      }
5066  
5067      /**
5068       * Test remove_members_from_conversation for multiple non valid users.
5069       */
5070      public function test_remove_members_for_multiple_no_valid_users() {
5071          $user1 = self::getDataGenerator()->create_user();
5072          $user2 = self::getDataGenerator()->create_user();
5073          $user3 = self::getDataGenerator()->create_user();
5074          $user4 = self::getDataGenerator()->create_user();
5075  
5076          $conversation = \core_message\api::create_conversation(
5077              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5078              [
5079                  $user1->id,
5080                  $user2->id
5081              ]
5082          );
5083          $conversationid = $conversation->id;
5084  
5085          $this->assertNull(\core_message\api::add_members_to_conversation([$user3->id], $conversationid));
5086          $this->assertNull(
5087              \core_message\api::remove_members_from_conversation([$user2->id, $user3->id, $user4->id, 0], $conversationid)
5088          );
5089          $this->assertEquals(1,
5090              \core_message\api::count_conversation_members($conversationid));
5091      }
5092  
5093      /**
5094       * Test count_conversation_members for empty conversation.
5095       */
5096      public function test_count_conversation_members_empty_conversation() {
5097          $user1 = self::getDataGenerator()->create_user();
5098          $user2 = self::getDataGenerator()->create_user();
5099  
5100          $conversation = \core_message\api::create_conversation(
5101              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5102              [
5103                  $user1->id,
5104                  $user2->id
5105              ]
5106          );
5107          $conversationid = $conversation->id;
5108  
5109          $this->assertNull(\core_message\api::remove_members_from_conversation([$user1->id, $user2->id], $conversationid));
5110  
5111          $this->assertEquals(0,
5112              \core_message\api::count_conversation_members($conversationid));
5113      }
5114  
5115      /**
5116       * Test can create a contact request.
5117       */
5118      public function test_can_create_contact_request() {
5119          global $CFG;
5120  
5121          $user1 = self::getDataGenerator()->create_user();
5122          $user2 = self::getDataGenerator()->create_user();
5123  
5124          // Disable messaging.
5125          $CFG->messaging = 0;
5126          $this->assertFalse(\core_message\api::can_create_contact($user1->id, $user2->id));
5127  
5128          // Re-enable messaging.
5129          $CFG->messaging = 1;
5130  
5131          // Allow users to message anyone site-wide.
5132          $CFG->messagingallusers = 1;
5133          $this->assertTrue(\core_message\api::can_create_contact($user1->id, $user2->id));
5134  
5135          // Disallow users from messaging anyone site-wide.
5136          $CFG->messagingallusers = 0;
5137          $this->assertFalse(\core_message\api::can_create_contact($user1->id, $user2->id));
5138  
5139          // Put the users in the same course so a contact request should be possible.
5140          $course = self::getDataGenerator()->create_course();
5141          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
5142          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
5143          $this->assertTrue(\core_message\api::can_create_contact($user1->id, $user2->id));
5144      }
5145  
5146      /**
5147       * Test creating a contact request.
5148       */
5149      public function test_create_contact_request() {
5150          global $DB;
5151  
5152          $user1 = self::getDataGenerator()->create_user();
5153          $user2 = self::getDataGenerator()->create_user();
5154  
5155          $sink = $this->redirectMessages();
5156          $request = \core_message\api::create_contact_request($user1->id, $user2->id);
5157          $messages = $sink->get_messages();
5158          $sink->close();
5159          // Test customdata.
5160          $customdata = json_decode($messages[0]->customdata);
5161          $this->assertObjectHasAttribute('notificationiconurl', $customdata);
5162          $this->assertObjectHasAttribute('actionbuttons', $customdata);
5163          $this->assertCount(2, (array) $customdata->actionbuttons);
5164  
5165          $this->assertEquals($user1->id, $request->userid);
5166          $this->assertEquals($user2->id, $request->requesteduserid);
5167      }
5168  
5169      /**
5170       * Test confirming a contact request.
5171       */
5172      public function test_confirm_contact_request() {
5173          global $DB;
5174  
5175          $user1 = self::getDataGenerator()->create_user();
5176          $user2 = self::getDataGenerator()->create_user();
5177  
5178          \core_message\api::create_contact_request($user1->id, $user2->id);
5179  
5180          \core_message\api::confirm_contact_request($user1->id, $user2->id);
5181  
5182          $this->assertEquals(0, $DB->count_records('message_contact_requests'));
5183  
5184          $contact = $DB->get_records('message_contacts');
5185  
5186          $this->assertCount(1, $contact);
5187  
5188          $contact = reset($contact);
5189  
5190          $this->assertEquals($user1->id, $contact->userid);
5191          $this->assertEquals($user2->id, $contact->contactid);
5192      }
5193  
5194      /**
5195       * Test declining a contact request.
5196       */
5197      public function test_decline_contact_request() {
5198          global $DB;
5199  
5200          $user1 = self::getDataGenerator()->create_user();
5201          $user2 = self::getDataGenerator()->create_user();
5202  
5203          \core_message\api::create_contact_request($user1->id, $user2->id);
5204  
5205          \core_message\api::decline_contact_request($user1->id, $user2->id);
5206  
5207          $this->assertEquals(0, $DB->count_records('message_contact_requests'));
5208          $this->assertEquals(0, $DB->count_records('message_contacts'));
5209      }
5210  
5211      /**
5212       * Test retrieving contact requests.
5213       */
5214      public function test_get_contact_requests() {
5215          global $PAGE;
5216  
5217          $user1 = self::getDataGenerator()->create_user();
5218          $user2 = self::getDataGenerator()->create_user();
5219          $user3 = self::getDataGenerator()->create_user();
5220  
5221          // Block one user, their request should not show up.
5222          \core_message\api::block_user($user1->id, $user3->id);
5223  
5224          \core_message\api::create_contact_request($user2->id, $user1->id);
5225          \core_message\api::create_contact_request($user3->id, $user1->id);
5226  
5227          $requests = \core_message\api::get_contact_requests($user1->id);
5228  
5229          $this->assertCount(1, $requests);
5230  
5231          $request = reset($requests);
5232          $userpicture = new \user_picture($user2);
5233          $profileimageurl = $userpicture->get_url($PAGE)->out(false);
5234  
5235          $this->assertEquals($user2->id, $request->id);
5236          $this->assertEquals(fullname($user2), $request->fullname);
5237          $this->assertObjectHasAttribute('profileimageurl', $request);
5238          $this->assertObjectHasAttribute('profileimageurlsmall', $request);
5239          $this->assertObjectHasAttribute('isonline', $request);
5240          $this->assertObjectHasAttribute('showonlinestatus', $request);
5241          $this->assertObjectHasAttribute('isblocked', $request);
5242          $this->assertObjectHasAttribute('iscontact', $request);
5243      }
5244  
5245      /**
5246       * Test the get_contact_requests() function when the user has blocked the sender of the request.
5247       */
5248      public function test_get_contact_requests_blocked_sender() {
5249          $user1 = self::getDataGenerator()->create_user();
5250          $user2 = self::getDataGenerator()->create_user();
5251  
5252          // User1 blocks User2.
5253          \core_message\api::block_user($user1->id, $user2->id);
5254  
5255          // User2 tries to add User1 as a contact.
5256          \core_message\api::create_contact_request($user2->id, $user1->id);
5257  
5258          // Verify we don't see the contact request from the blocked user User2 in the requests for User1.
5259          $requests = \core_message\api::get_contact_requests($user1->id);
5260          $this->assertEmpty($requests);
5261      }
5262  
5263      /**
5264       * Test getting contact requests when there are none.
5265       */
5266      public function test_get_contact_requests_no_requests() {
5267          $this->resetAfterTest();
5268  
5269          $user1 = self::getDataGenerator()->create_user();
5270  
5271          $requests = \core_message\api::get_contact_requests($user1->id);
5272  
5273          $this->assertEmpty($requests);
5274      }
5275  
5276      /**
5277       * Test getting contact requests with limits.
5278       */
5279      public function test_get_contact_requests_with_limits() {
5280          $this->resetAfterTest();
5281  
5282          $user1 = self::getDataGenerator()->create_user();
5283          $user2 = self::getDataGenerator()->create_user();
5284          $user3 = self::getDataGenerator()->create_user();
5285  
5286          \core_message\api::create_contact_request($user2->id, $user1->id);
5287          \core_message\api::create_contact_request($user3->id, $user1->id);
5288  
5289          $requests = \core_message\api::get_contact_requests($user1->id, 0, 1);
5290  
5291          $this->assertCount(1, $requests);
5292      }
5293  
5294      /**
5295       * Test adding contacts.
5296       */
5297      public function test_add_contact() {
5298          global $DB;
5299  
5300          $user1 = self::getDataGenerator()->create_user();
5301          $user2 = self::getDataGenerator()->create_user();
5302  
5303          \core_message\api::add_contact($user1->id, $user2->id);
5304  
5305          $contact = $DB->get_records('message_contacts');
5306  
5307          $this->assertCount(1, $contact);
5308  
5309          $contact = reset($contact);
5310  
5311          $this->assertEquals($user1->id, $contact->userid);
5312          $this->assertEquals($user2->id, $contact->contactid);
5313      }
5314  
5315      /**
5316       * Test removing contacts.
5317       */
5318      public function test_remove_contact() {
5319          global $DB;
5320  
5321          $user1 = self::getDataGenerator()->create_user();
5322          $user2 = self::getDataGenerator()->create_user();
5323  
5324          \core_message\api::add_contact($user1->id, $user2->id);
5325          \core_message\api::remove_contact($user1->id, $user2->id);
5326  
5327          $this->assertEquals(0, $DB->count_records('message_contacts'));
5328      }
5329  
5330      /**
5331       * Test blocking users.
5332       */
5333      public function test_block_user() {
5334          global $DB;
5335  
5336          $user1 = self::getDataGenerator()->create_user();
5337          $user2 = self::getDataGenerator()->create_user();
5338  
5339          \core_message\api::block_user($user1->id, $user2->id);
5340  
5341          $blockedusers = $DB->get_records('message_users_blocked');
5342  
5343          $this->assertCount(1, $blockedusers);
5344  
5345          $blockeduser = reset($blockedusers);
5346  
5347          $this->assertEquals($user1->id, $blockeduser->userid);
5348          $this->assertEquals($user2->id, $blockeduser->blockeduserid);
5349      }
5350  
5351      /**
5352       * Test unblocking users.
5353       */
5354      public function test_unblock_user() {
5355          global $DB;
5356  
5357          $user1 = self::getDataGenerator()->create_user();
5358          $user2 = self::getDataGenerator()->create_user();
5359  
5360          \core_message\api::block_user($user1->id, $user2->id);
5361          \core_message\api::unblock_user($user1->id, $user2->id);
5362  
5363          $this->assertEquals(0, $DB->count_records('message_users_blocked'));
5364      }
5365  
5366      /**
5367       * Test muting a conversation.
5368       */
5369      public function test_mute_conversation() {
5370          global $DB;
5371  
5372          $user1 = self::getDataGenerator()->create_user();
5373          $user2 = self::getDataGenerator()->create_user();
5374  
5375          $conversation = \core_message\api::create_conversation(
5376              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5377              [
5378                  $user1->id,
5379                  $user2->id
5380              ]
5381          );
5382          $conversationid = $conversation->id;
5383  
5384          \core_message\api::mute_conversation($user1->id, $conversationid);
5385  
5386          $mutedconversation = $DB->get_records('message_conversation_actions');
5387  
5388          $this->assertCount(1, $mutedconversation);
5389  
5390          $mutedconversation = reset($mutedconversation);
5391  
5392          $this->assertEquals($user1->id, $mutedconversation->userid);
5393          $this->assertEquals($conversationid, $mutedconversation->conversationid);
5394          $this->assertEquals(\core_message\api::CONVERSATION_ACTION_MUTED, $mutedconversation->action);
5395      }
5396  
5397      /**
5398       * Test unmuting a conversation.
5399       */
5400      public function test_unmute_conversation() {
5401          global $DB;
5402  
5403          $user1 = self::getDataGenerator()->create_user();
5404          $user2 = self::getDataGenerator()->create_user();
5405  
5406          $conversation = \core_message\api::create_conversation(
5407              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5408              [
5409                  $user1->id,
5410                  $user2->id
5411              ]
5412          );
5413          $conversationid = $conversation->id;
5414  
5415          \core_message\api::mute_conversation($user1->id, $conversationid);
5416          \core_message\api::unmute_conversation($user1->id, $conversationid);
5417  
5418          $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
5419      }
5420  
5421      /**
5422       * Test if a conversation is muted.
5423       */
5424      public function test_is_conversation_muted() {
5425          $user1 = self::getDataGenerator()->create_user();
5426          $user2 = self::getDataGenerator()->create_user();
5427  
5428          $conversation = \core_message\api::create_conversation(
5429              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5430              [
5431                  $user1->id,
5432                  $user2->id
5433              ]
5434          );
5435          $conversationid = $conversation->id;
5436  
5437          $this->assertFalse(\core_message\api::is_conversation_muted($user1->id, $conversationid));
5438  
5439          \core_message\api::mute_conversation($user1->id, $conversationid);
5440  
5441          $this->assertTrue(\core_message\api::is_conversation_muted($user1->id, $conversationid));
5442      }
5443  
5444      /**
5445       * Test is contact check.
5446       */
5447      public function test_is_contact() {
5448          $user1 = self::getDataGenerator()->create_user();
5449          $user2 = self::getDataGenerator()->create_user();
5450          $user3 = self::getDataGenerator()->create_user();
5451  
5452          \core_message\api::add_contact($user1->id, $user2->id);
5453  
5454          $this->assertTrue(\core_message\api::is_contact($user1->id, $user2->id));
5455          $this->assertTrue(\core_message\api::is_contact($user2->id, $user1->id));
5456          $this->assertFalse(\core_message\api::is_contact($user2->id, $user3->id));
5457      }
5458  
5459      /**
5460       * Test get contact.
5461       */
5462      public function test_get_contact() {
5463          $user1 = self::getDataGenerator()->create_user();
5464          $user2 = self::getDataGenerator()->create_user();
5465  
5466          \core_message\api::add_contact($user1->id, $user2->id);
5467  
5468          $contact = \core_message\api::get_contact($user1->id, $user2->id);
5469  
5470          $this->assertEquals($user1->id, $contact->userid);
5471          $this->assertEquals($user2->id, $contact->contactid);
5472      }
5473  
5474      /**
5475       * Test is blocked checked.
5476       */
5477      public function test_is_blocked() {
5478          $user1 = self::getDataGenerator()->create_user();
5479          $user2 = self::getDataGenerator()->create_user();
5480  
5481          $this->assertFalse(\core_message\api::is_blocked($user1->id, $user2->id));
5482          $this->assertFalse(\core_message\api::is_blocked($user2->id, $user1->id));
5483  
5484          \core_message\api::block_user($user1->id, $user2->id);
5485  
5486          $this->assertTrue(\core_message\api::is_blocked($user1->id, $user2->id));
5487          $this->assertFalse(\core_message\api::is_blocked($user2->id, $user1->id));
5488      }
5489  
5490      /**
5491       * Test the contact request exist check.
5492       */
5493      public function test_does_contact_request_exist() {
5494          $user1 = self::getDataGenerator()->create_user();
5495          $user2 = self::getDataGenerator()->create_user();
5496  
5497          $this->assertFalse(\core_message\api::does_contact_request_exist($user1->id, $user2->id));
5498          $this->assertFalse(\core_message\api::does_contact_request_exist($user2->id, $user1->id));
5499  
5500          \core_message\api::create_contact_request($user1->id, $user2->id);
5501  
5502          $this->assertTrue(\core_message\api::does_contact_request_exist($user1->id, $user2->id));
5503          $this->assertTrue(\core_message\api::does_contact_request_exist($user2->id, $user1->id));
5504      }
5505  
5506      /**
5507       * Test the get_received_contact_requests_count() function.
5508       */
5509      public function test_get_received_contact_requests_count() {
5510          $user1 = self::getDataGenerator()->create_user();
5511          $user2 = self::getDataGenerator()->create_user();
5512          $user3 = self::getDataGenerator()->create_user();
5513          $user4 = self::getDataGenerator()->create_user();
5514  
5515          $this->assertEquals(0, \core_message\api::get_received_contact_requests_count($user1->id));
5516  
5517          \core_message\api::create_contact_request($user2->id, $user1->id);
5518  
5519          $this->assertEquals(1, \core_message\api::get_received_contact_requests_count($user1->id));
5520  
5521          \core_message\api::create_contact_request($user3->id, $user1->id);
5522  
5523          $this->assertEquals(2, \core_message\api::get_received_contact_requests_count($user1->id));
5524  
5525          \core_message\api::create_contact_request($user1->id, $user4->id);
5526          // Function should ignore sent requests.
5527          $this->assertEquals(2, \core_message\api::get_received_contact_requests_count($user1->id));
5528      }
5529  
5530      /**
5531       * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request.
5532       */
5533      public function test_get_received_contact_requests_count_blocked_sender() {
5534          $user1 = self::getDataGenerator()->create_user();
5535          $user2 = self::getDataGenerator()->create_user();
5536  
5537          // User1 blocks User2.
5538          \core_message\api::block_user($user1->id, $user2->id);
5539  
5540          // User2 tries to add User1 as a contact.
5541          \core_message\api::create_contact_request($user2->id, $user1->id);
5542  
5543          // Verify we don't see the contact request from the blocked user User2 in the count for User1.
5544          $this->assertEquals(0, \core_message\api::get_received_contact_requests_count($user1->id));
5545      }
5546  
5547      /**
5548       * Test the get_contact_requests_between_users() function.
5549       */
5550      public function test_get_contact_requests_between_users() {
5551          $user1 = self::getDataGenerator()->create_user();
5552          $user2 = self::getDataGenerator()->create_user();
5553          $user3 = self::getDataGenerator()->create_user();
5554          $user4 = self::getDataGenerator()->create_user();
5555  
5556          $this->assertEquals([], \core_message\api::get_contact_requests_between_users($user1->id, $user2->id));
5557  
5558          $request1 = \core_message\api::create_contact_request($user2->id, $user1->id);
5559          $results = \core_message\api::get_contact_requests_between_users($user1->id, $user2->id);
5560          $results = array_values($results);
5561  
5562          $this->assertCount(1, $results);
5563          $result = $results[0];
5564          $this->assertEquals($request1->id, $result->id);
5565  
5566          $request2 = \core_message\api::create_contact_request($user1->id, $user2->id);
5567          $results = \core_message\api::get_contact_requests_between_users($user1->id, $user2->id);
5568          $results = array_values($results);
5569  
5570          $this->assertCount(2, $results);
5571          $actual = [(int) $results[0]->id, (int) $results[1]->id];
5572          $expected = [(int) $request1->id, (int) $request2->id];
5573  
5574          sort($actual);
5575          sort($expected);
5576  
5577          $this->assertEquals($expected, $actual);
5578  
5579          // Request from a different user.
5580          \core_message\api::create_contact_request($user3->id, $user1->id);
5581  
5582          $results = \core_message\api::get_contact_requests_between_users($user1->id, $user2->id);
5583          $results = array_values($results);
5584  
5585          $this->assertCount(2, $results);
5586          $actual = [(int) $results[0]->id, (int) $results[1]->id];
5587          $expected = [(int) $request1->id, (int) $request2->id];
5588  
5589          sort($actual);
5590          sort($expected);
5591  
5592          $this->assertEquals($expected, $actual);
5593      }
5594  
5595      /**
5596       * Test the user in conversation check.
5597       */
5598      public function test_is_user_in_conversation() {
5599          $user1 = self::getDataGenerator()->create_user();
5600          $user2 = self::getDataGenerator()->create_user();
5601  
5602          $conversation = \core_message\api::create_conversation(
5603              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5604              [
5605                  $user1->id,
5606                  $user2->id
5607              ]
5608          );
5609          $conversationid = $conversation->id;
5610  
5611          $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $conversationid));
5612      }
5613  
5614      /**
5615       * Test the user in conversation check when they are not.
5616       */
5617      public function test_is_user_in_conversation_when_not() {
5618          $user1 = self::getDataGenerator()->create_user();
5619          $user2 = self::getDataGenerator()->create_user();
5620          $user3 = self::getDataGenerator()->create_user();
5621  
5622          $conversation = \core_message\api::create_conversation(
5623              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5624              [
5625                  $user1->id,
5626                  $user2->id
5627              ]
5628          );
5629          $conversationid = $conversation->id;
5630  
5631          $this->assertFalse(\core_message\api::is_user_in_conversation($user3->id, $conversationid));
5632      }
5633  
5634      /**
5635       * Test can create a group conversation.
5636       */
5637      public function test_can_create_group_conversation() {
5638          global $CFG;
5639  
5640          $student = self::getDataGenerator()->create_user();
5641          $teacher = self::getDataGenerator()->create_user();
5642          $course = self::getDataGenerator()->create_course();
5643  
5644          $coursecontext = context_course::instance($course->id);
5645  
5646          $this->getDataGenerator()->enrol_user($student->id, $course->id);
5647          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
5648  
5649          // Disable messaging.
5650          $CFG->messaging = 0;
5651          $this->assertFalse(\core_message\api::can_create_group_conversation($student->id, $coursecontext));
5652  
5653          // Re-enable messaging.
5654          $CFG->messaging = 1;
5655  
5656          // Student shouldn't be able to.
5657          $this->assertFalse(\core_message\api::can_create_group_conversation($student->id, $coursecontext));
5658  
5659          // Teacher should.
5660          $this->assertTrue(\core_message\api::can_create_group_conversation($teacher->id, $coursecontext));
5661      }
5662  
5663      /**
5664       * Test creating an individual conversation.
5665       */
5666      public function test_create_conversation_individual() {
5667          $user1 = self::getDataGenerator()->create_user();
5668          $user2 = self::getDataGenerator()->create_user();
5669  
5670          $conversation = \core_message\api::create_conversation(
5671              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5672              [
5673                  $user1->id,
5674                  $user2->id
5675              ],
5676              'A conversation name'
5677          );
5678  
5679          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversation->type);
5680          $this->assertEquals('A conversation name', $conversation->name);
5681          $this->assertEquals(\core_message\helper::get_conversation_hash([$user1->id, $user2->id]), $conversation->convhash);
5682  
5683          $this->assertCount(2, $conversation->members);
5684  
5685          $member1 = array_shift($conversation->members);
5686          $member2 = array_shift($conversation->members);
5687  
5688          $this->assertEquals($user1->id, $member1->userid);
5689          $this->assertEquals($conversation->id, $member1->conversationid);
5690  
5691          $this->assertEquals($user2->id, $member2->userid);
5692          $this->assertEquals($conversation->id, $member2->conversationid);
5693      }
5694  
5695      /**
5696       * Test creating a group conversation.
5697       */
5698      public function test_create_conversation_group() {
5699          $user1 = self::getDataGenerator()->create_user();
5700          $user2 = self::getDataGenerator()->create_user();
5701          $user3 = self::getDataGenerator()->create_user();
5702  
5703          $conversation = \core_message\api::create_conversation(
5704              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5705              [
5706                  $user1->id,
5707                  $user2->id,
5708                  $user3->id
5709              ],
5710              'A conversation name'
5711          );
5712  
5713          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversation->type);
5714          $this->assertEquals('A conversation name', $conversation->name);
5715          $this->assertNull($conversation->convhash);
5716  
5717          $this->assertCount(3, $conversation->members);
5718  
5719          $member1 = array_shift($conversation->members);
5720          $member2 = array_shift($conversation->members);
5721          $member3 = array_shift($conversation->members);
5722  
5723          $this->assertEquals($user1->id, $member1->userid);
5724          $this->assertEquals($conversation->id, $member1->conversationid);
5725  
5726          $this->assertEquals($user2->id, $member2->userid);
5727          $this->assertEquals($conversation->id, $member2->conversationid);
5728  
5729          $this->assertEquals($user3->id, $member3->userid);
5730          $this->assertEquals($conversation->id, $member3->conversationid);
5731      }
5732  
5733      /**
5734       * Test creating an invalid conversation.
5735       */
5736      public function test_create_conversation_invalid() {
5737          $this->expectException('moodle_exception');
5738          \core_message\api::create_conversation(3, [1, 2, 3]);
5739      }
5740  
5741      /**
5742       * Test creating an individual conversation with too many members.
5743       */
5744      public function test_create_conversation_individual_too_many_members() {
5745          $this->expectException('moodle_exception');
5746          \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, [1, 2, 3]);
5747      }
5748  
5749      /**
5750       * Test create message conversation with area.
5751       */
5752      public function test_create_conversation_with_area() {
5753          $contextid = 111;
5754          $itemid = 222;
5755          $name = 'Name of conversation';
5756          $conversation = \core_message\api::create_conversation(
5757              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5758              [],
5759              $name,
5760              \core_message\api::MESSAGE_CONVERSATION_DISABLED,
5761              'core_group',
5762              'groups',
5763              $itemid,
5764              $contextid
5765          );
5766  
5767          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_DISABLED, $conversation->enabled);
5768          $this->assertEquals('core_group', $conversation->component);
5769          $this->assertEquals('groups', $conversation->itemtype);
5770          $this->assertEquals($itemid, $conversation->itemid);
5771          $this->assertEquals($contextid, $conversation->contextid);
5772      }
5773  
5774      /**
5775       * Test get_conversation_by_area.
5776       */
5777      public function test_get_conversation_by_area() {
5778          $contextid = 111;
5779          $itemid = 222;
5780          $name = 'Name of conversation';
5781          $createconversation = \core_message\api::create_conversation(
5782              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5783              [],
5784              $name,
5785              \core_message\api::MESSAGE_CONVERSATION_DISABLED,
5786              'core_group',
5787              'groups',
5788              $itemid,
5789              $contextid
5790          );
5791          $conversation = \core_message\api::get_conversation_by_area('core_group', 'groups', $itemid, $contextid);
5792  
5793          $this->assertEquals($createconversation->id, $conversation->id);
5794          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_DISABLED, $conversation->enabled);
5795          $this->assertEquals('core_group', $conversation->component);
5796          $this->assertEquals('groups', $conversation->itemtype);
5797          $this->assertEquals($itemid, $conversation->itemid);
5798          $this->assertEquals($contextid, $conversation->contextid);
5799      }
5800  
5801      /**
5802       * Test enable_conversation.
5803       */
5804      public function test_enable_conversation() {
5805          global $DB;
5806  
5807          $name = 'Name of conversation';
5808  
5809          $conversation = \core_message\api::create_conversation(
5810              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5811              [],
5812              $name,
5813              \core_message\api::MESSAGE_CONVERSATION_DISABLED
5814          );
5815  
5816          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_DISABLED, $conversation->enabled);
5817          \core_message\api::enable_conversation($conversation->id);
5818          $conversationenabled = $DB->get_field('message_conversations', 'enabled', ['id' => $conversation->id]);
5819          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_ENABLED, $conversationenabled);
5820      }
5821  
5822      /**
5823       * Test disable_conversation.
5824       */
5825      public function test_disable_conversation() {
5826          global $DB;
5827  
5828          $name = 'Name of conversation';
5829  
5830          $conversation = \core_message\api::create_conversation(
5831              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
5832              [],
5833              $name,
5834              \core_message\api::MESSAGE_CONVERSATION_ENABLED
5835          );
5836  
5837          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_ENABLED, $conversation->enabled);
5838          \core_message\api::disable_conversation($conversation->id);
5839          $conversationenabled = $DB->get_field('message_conversations', 'enabled', ['id' => $conversation->id]);
5840          $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_DISABLED, $conversationenabled);
5841      }
5842  
5843      /**
5844       * Test update_conversation_name.
5845       */
5846      public function test_update_conversation_name() {
5847          global $DB;
5848  
5849          $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, []);
5850  
5851          $newname = 'New name of conversation';
5852          \core_message\api::update_conversation_name($conversation->id, $newname);
5853  
5854          $this->assertEquals(
5855                  $newname,
5856                  $DB->get_field('message_conversations', 'name', ['id' => $conversation->id])
5857          );
5858      }
5859  
5860  
5861      /**
5862       * Test an empty array returned when no args given.
5863       */
5864      public function test_get_individual_conversations_between_users_no_user_sets() {
5865          $this->assertEmpty(\core_message\api::get_individual_conversations_between_users([]));
5866          $this->assertDebuggingCalled();
5867      }
5868  
5869      /**
5870       * Test a conversation is not returned if there is none.
5871       */
5872      public function test_get_individual_conversations_between_users_no_conversation() {
5873          $generator = $this->getDataGenerator();
5874          $user1 = $generator->create_user();
5875          $user2 = $generator->create_user();
5876  
5877          $this->assertEquals(
5878              [null],
5879              \core_message\api::get_individual_conversations_between_users([[$user1->id, $user2->id]])
5880          );
5881          $this->assertDebuggingCalled();
5882      }
5883  
5884      /**
5885       * Test the result set includes null if there is no conversation between users.
5886       */
5887      public function test_get_individual_conversations_between_users_partial_conversations() {
5888          $generator = $this->getDataGenerator();
5889          $user1 = $generator->create_user();
5890          $user2 = $generator->create_user();
5891          $user3 = $generator->create_user();
5892          $type = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
5893  
5894          $conversation1 = \core_message\api::create_conversation($type, [$user1->id, $user2->id]);
5895          $conversation2 = \core_message\api::create_conversation($type, [$user1->id, $user3->id]);
5896  
5897          $results = \core_message\api::get_individual_conversations_between_users([
5898              [$user1->id, $user2->id],
5899              [$user2->id, $user3->id],
5900              [$user1->id, $user3->id]
5901          ]);
5902          $this->assertDebuggingCalled();
5903  
5904          $result = array_map(function($result) {
5905              if ($result) {
5906                  return $result->id;
5907              } else {
5908                  return $result;
5909              }
5910          }, $results);
5911  
5912          $this->assertEquals(
5913              [$conversation1->id, null, $conversation2->id],
5914              $result
5915          );
5916      }
5917  
5918      /**
5919       * Test all conversations are returned if each set has a conversation.
5920       */
5921      public function test_get_individual_conversations_between_users_all_conversations() {
5922          $generator = $this->getDataGenerator();
5923          $user1 = $generator->create_user();
5924          $user2 = $generator->create_user();
5925          $user3 = $generator->create_user();
5926          $type = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
5927  
5928          $conversation1 = \core_message\api::create_conversation($type, [$user1->id, $user2->id]);
5929          $conversation2 = \core_message\api::create_conversation($type, [$user2->id, $user3->id]);
5930          $conversation3 = \core_message\api::create_conversation($type, [$user1->id, $user3->id]);
5931  
5932          $results = \core_message\api::get_individual_conversations_between_users([
5933              [$user1->id, $user2->id],
5934              [$user2->id, $user3->id],
5935              [$user1->id, $user3->id]
5936          ]);
5937          $this->assertDebuggingCalled();
5938  
5939          $result = array_map(function($result) {
5940              if ($result) {
5941                  return $result->id;
5942              } else {
5943                  return $result;
5944              }
5945          }, $results);
5946  
5947          $this->assertEquals(
5948              [$conversation1->id, $conversation2->id, $conversation3->id],
5949              $result
5950          );
5951      }
5952  
5953      /**
5954       * Test that the results are ordered to match the order of the parameters.
5955       */
5956      public function test_get_individual_conversations_between_users_ordering() {
5957          $generator = $this->getDataGenerator();
5958          $user1 = $generator->create_user();
5959          $user2 = $generator->create_user();
5960          $user3 = $generator->create_user();
5961          $type = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
5962  
5963          $conversation1 = \core_message\api::create_conversation($type, [$user1->id, $user2->id]);
5964          $conversation2 = \core_message\api::create_conversation($type, [$user2->id, $user3->id]);
5965          $conversation3 = \core_message\api::create_conversation($type, [$user1->id, $user3->id]);
5966  
5967          $results = \core_message\api::get_individual_conversations_between_users([
5968              [$user1->id, $user2->id],
5969              [$user2->id, $user3->id],
5970              [$user1->id, $user3->id]
5971          ]);
5972          $this->assertDebuggingCalled();
5973  
5974          $result = array_map(function($result) {
5975              if ($result) {
5976                  return $result->id;
5977              } else {
5978                  return $result;
5979              }
5980          }, $results);
5981  
5982          $this->assertEquals(
5983              [$conversation1->id, $conversation2->id, $conversation3->id],
5984              $result
5985          );
5986  
5987          $results = \core_message\api::get_individual_conversations_between_users([
5988              [$user2->id, $user3->id],
5989              [$user1->id, $user2->id],
5990              [$user1->id, $user3->id]
5991          ]);
5992          $this->assertDebuggingCalled();
5993  
5994          $result = array_map(function($result) {
5995              if ($result) {
5996                  return $result->id;
5997              } else {
5998                  return $result;
5999              }
6000          }, $results);
6001  
6002          $this->assertEquals(
6003              [$conversation2->id, $conversation1->id, $conversation3->id],
6004              $result
6005          );
6006      }
6007  
6008      /**
6009       * Test returning members in a conversation with no contact requests.
6010       */
6011      public function test_get_conversation_members() {
6012          $lastaccess = new stdClass();
6013          $lastaccess->lastaccess = time();
6014  
6015          $user1 = self::getDataGenerator()->create_user($lastaccess);
6016          $user2 = self::getDataGenerator()->create_user();
6017          $user3 = self::getDataGenerator()->create_user();
6018  
6019          // This user will not be in the conversation, but a contact request will exist for them.
6020          $user4 = self::getDataGenerator()->create_user();
6021  
6022          // Add some contact requests.
6023          \core_message\api::create_contact_request($user1->id, $user3->id);
6024          \core_message\api::create_contact_request($user1->id, $user4->id);
6025          \core_message\api::create_contact_request($user2->id, $user3->id);
6026  
6027          // User 1 and 2 are already contacts.
6028          \core_message\api::add_contact($user1->id, $user2->id);
6029  
6030          // User 1 has blocked user 3.
6031          \core_message\api::block_user($user1->id, $user3->id);
6032          $conversation = \core_message\api::create_conversation(
6033              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
6034              [
6035                  $user1->id,
6036                  $user2->id,
6037                  $user3->id
6038              ]
6039          );
6040          $conversationid = $conversation->id;
6041          $members = \core_message\api::get_conversation_members($user1->id, $conversationid, false);
6042  
6043          // Sort them by id.
6044          ksort($members);
6045          $this->assertCount(3, $members);
6046          $member1 = array_shift($members);
6047          $member2 = array_shift($members);
6048          $member3 = array_shift($members);
6049  
6050          // Confirm the standard fields are OK.
6051          $this->assertEquals($user1->id, $member1->id);
6052          $this->assertEquals(fullname($user1), $member1->fullname);
6053          $this->assertEquals(true, $member1->isonline);
6054          $this->assertEquals(true, $member1->showonlinestatus);
6055          $this->assertEquals(false, $member1->iscontact);
6056          $this->assertEquals(false, $member1->isblocked);
6057          $this->assertObjectHasAttribute('contactrequests', $member1);
6058          $this->assertEmpty($member1->contactrequests);
6059  
6060          $this->assertEquals($user2->id, $member2->id);
6061          $this->assertEquals(fullname($user2), $member2->fullname);
6062          $this->assertEquals(false, $member2->isonline);
6063          $this->assertEquals(true, $member2->showonlinestatus);
6064          $this->assertEquals(true, $member2->iscontact);
6065          $this->assertEquals(false, $member2->isblocked);
6066          $this->assertObjectHasAttribute('contactrequests', $member2);
6067          $this->assertEmpty($member2->contactrequests);
6068  
6069          $this->assertEquals($user3->id, $member3->id);
6070          $this->assertEquals(fullname($user3), $member3->fullname);
6071          $this->assertEquals(false, $member3->isonline);
6072          $this->assertEquals(true, $member3->showonlinestatus);
6073          $this->assertEquals(false, $member3->iscontact);
6074          $this->assertEquals(true, $member3->isblocked);
6075          $this->assertObjectHasAttribute('contactrequests', $member3);
6076          $this->assertEmpty($member3->contactrequests);
6077      }
6078  
6079      /**
6080       * Test returning members in a conversation with contact requests.
6081       */
6082      public function test_get_conversation_members_with_contact_requests() {
6083          $lastaccess = new stdClass();
6084          $lastaccess->lastaccess = time();
6085  
6086          $user1 = self::getDataGenerator()->create_user($lastaccess);
6087          $user2 = self::getDataGenerator()->create_user();
6088          $user3 = self::getDataGenerator()->create_user();
6089  
6090          // This user will not be in the conversation, but a contact request will exist for them.
6091          $user4 = self::getDataGenerator()->create_user();
6092          // Add some contact requests.
6093          \core_message\api::create_contact_request($user1->id, $user2->id);
6094          \core_message\api::create_contact_request($user1->id, $user3->id);
6095          \core_message\api::create_contact_request($user1->id, $user4->id);
6096          \core_message\api::create_contact_request($user2->id, $user3->id);
6097  
6098          // User 1 and 2 are already contacts.
6099          \core_message\api::add_contact($user1->id, $user2->id);
6100          // User 1 has blocked user 3.
6101          \core_message\api::block_user($user1->id, $user3->id);
6102  
6103          $conversation = \core_message\api::create_conversation(
6104              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
6105              [
6106                  $user1->id,
6107                  $user2->id,
6108                  $user3->id
6109              ]
6110          );
6111          $conversationid = $conversation->id;
6112  
6113          $members = \core_message\api::get_conversation_members($user1->id, $conversationid, true);
6114  
6115          // Sort them by id.
6116          ksort($members);
6117  
6118          $this->assertCount(3, $members);
6119  
6120          $member1 = array_shift($members);
6121          $member2 = array_shift($members);
6122          $member3 = array_shift($members);
6123  
6124          // Confirm the standard fields are OK.
6125          $this->assertEquals($user1->id, $member1->id);
6126          $this->assertEquals(fullname($user1), $member1->fullname);
6127          $this->assertEquals(true, $member1->isonline);
6128          $this->assertEquals(true, $member1->showonlinestatus);
6129          $this->assertEquals(false, $member1->iscontact);
6130          $this->assertEquals(false, $member1->isblocked);
6131          $this->assertCount(2, $member1->contactrequests);
6132  
6133          $this->assertEquals($user2->id, $member2->id);
6134          $this->assertEquals(fullname($user2), $member2->fullname);
6135          $this->assertEquals(false, $member2->isonline);
6136          $this->assertEquals(true, $member2->showonlinestatus);
6137          $this->assertEquals(true, $member2->iscontact);
6138          $this->assertEquals(false, $member2->isblocked);
6139          $this->assertCount(1, $member2->contactrequests);
6140  
6141          $this->assertEquals($user3->id, $member3->id);
6142          $this->assertEquals(fullname($user3), $member3->fullname);
6143          $this->assertEquals(false, $member3->isonline);
6144          $this->assertEquals(true, $member3->showonlinestatus);
6145          $this->assertEquals(false, $member3->iscontact);
6146          $this->assertEquals(true, $member3->isblocked);
6147          $this->assertCount(1, $member3->contactrequests);
6148  
6149          // Confirm the contact requests are OK.
6150          $request1 = array_shift($member1->contactrequests);
6151          $request2 = array_shift($member1->contactrequests);
6152  
6153          $this->assertEquals($user1->id, $request1->userid);
6154          $this->assertEquals($user2->id, $request1->requesteduserid);
6155  
6156          $this->assertEquals($user1->id, $request2->userid);
6157          $this->assertEquals($user3->id, $request2->requesteduserid);
6158  
6159          $request1 = array_shift($member2->contactrequests);
6160  
6161          $this->assertEquals($user1->id, $request1->userid);
6162          $this->assertEquals($user2->id, $request1->requesteduserid);
6163  
6164          $request1 = array_shift($member3->contactrequests);
6165  
6166          $this->assertEquals($user1->id, $request1->userid);
6167          $this->assertEquals($user3->id, $request1->requesteduserid);
6168      }
6169  
6170      /**
6171       * Test returning members of a self conversation.
6172       */
6173      public function test_get_conversation_members_with_self_conversation() {
6174          $lastaccess = new stdClass();
6175          $lastaccess->lastaccess = time();
6176  
6177          $user1 = self::getDataGenerator()->create_user($lastaccess);
6178  
6179          $selfconversation = \core_message\api::get_self_conversation($user1->id);
6180          testhelper::send_fake_message_to_conversation($user1, $selfconversation->id, 'This is a self-message!');
6181  
6182          // Get the members for the self-conversation.
6183          $members = \core_message\api::get_conversation_members($user1->id, $selfconversation->id);
6184          $this->assertCount(1, $members);
6185  
6186          $member1 = array_shift($members);
6187  
6188          // Confirm the standard fields are OK.
6189          $this->assertEquals($user1->id, $member1->id);
6190          $this->assertEquals(fullname($user1), $member1->fullname);
6191          $this->assertEquals(true, $member1->isonline);
6192          $this->assertEquals(true, $member1->showonlinestatus);
6193          $this->assertEquals(false, $member1->iscontact);
6194          $this->assertEquals(false, $member1->isblocked);
6195      }
6196  
6197      /**
6198       * Test verifying that messages can be sent to existing individual conversations.
6199       */
6200      public function test_send_message_to_conversation_individual_conversation() {
6201          // Get a bunch of conversations, some group, some individual and in different states.
6202          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
6203              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
6204  
6205          // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
6206          $course = $this->getDataGenerator()->create_course();
6207          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
6208          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
6209          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
6210          $this->getDataGenerator()->enrol_user($user4->id, $course->id);
6211  
6212          // Redirect messages.
6213          // This marks messages as read, but we can still observe and verify the number of conversation recipients,
6214          // based on the message_viewed events generated as part of marking the message as read for each user.
6215          $this->preventResetByRollback();
6216          $sink = $this->redirectMessages();
6217  
6218          // Send a message to an individual conversation.
6219          $sink = $this->redirectEvents();
6220          $messagessink = $this->redirectMessages();
6221          $message1 = \core_message\api::send_message_to_conversation($user1->id, $ic1->id, 'this is a message', FORMAT_MOODLE);
6222          $events = $sink->get_events();
6223          $messages = $messagessink->get_messages();
6224          // Test customdata.
6225          $customdata = json_decode($messages[0]->customdata);
6226          $this->assertObjectHasAttribute('notificationiconurl', $customdata);
6227          $this->assertObjectHasAttribute('actionbuttons', $customdata);
6228          $this->assertCount(1, (array) $customdata->actionbuttons);
6229          $this->assertObjectHasAttribute('placeholders', $customdata);
6230          $this->assertCount(1, (array) $customdata->placeholders);
6231  
6232          // Verify the message returned.
6233          $this->assertInstanceOf(\stdClass::class, $message1);
6234          $this->assertObjectHasAttribute('id', $message1);
6235          $this->assertAttributeEquals($user1->id, 'useridfrom', $message1);
6236          $this->assertAttributeEquals('this is a message', 'text', $message1);
6237          $this->assertObjectHasAttribute('timecreated', $message1);
6238  
6239          // Verify events. Note: the event is a message read event because of an if (PHPUNIT) conditional within message_send(),
6240          // however, we can still determine the number and ids of any recipients this way.
6241          $this->assertCount(1, $events);
6242          $userids = array_column($events, 'userid');
6243          $this->assertNotContains($user1->id, $userids);
6244          $this->assertContains($user2->id, $userids);
6245      }
6246  
6247      /**
6248       * Test verifying that messages can be sent to existing group conversations.
6249       */
6250      public function test_send_message_to_conversation_group_conversation() {
6251          // Get a bunch of conversations, some group, some individual and in different states.
6252          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
6253              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
6254  
6255          // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
6256          $course = $this->getDataGenerator()->create_course();
6257          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
6258          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
6259          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
6260          $this->getDataGenerator()->enrol_user($user4->id, $course->id);
6261  
6262          // Redirect messages.
6263          // This marks messages as read, but we can still observe and verify the number of conversation recipients,
6264          // based on the message_viewed events generated as part of marking the message as read for each user.
6265          $this->preventResetByRollback();
6266          $sink = $this->redirectMessages();
6267  
6268          // Send a message to a group conversation.
6269          $sink = $this->redirectEvents();
6270          $messagessink = $this->redirectMessages();
6271          $message1 = \core_message\api::send_message_to_conversation($user1->id, $gc2->id, 'message to the group', FORMAT_MOODLE);
6272          $events = $sink->get_events();
6273          $messages = $messagessink->get_messages();
6274          // Verify the message returned.
6275          $this->assertInstanceOf(\stdClass::class, $message1);
6276          $this->assertObjectHasAttribute('id', $message1);
6277          $this->assertAttributeEquals($user1->id, 'useridfrom', $message1);
6278          $this->assertAttributeEquals('message to the group', 'text', $message1);
6279          $this->assertObjectHasAttribute('timecreated', $message1);
6280          // Test customdata.
6281          $customdata = json_decode($messages[0]->customdata);
6282          $this->assertObjectHasAttribute('actionbuttons', $customdata);
6283          $this->assertCount(1, (array) $customdata->actionbuttons);
6284          $this->assertObjectHasAttribute('placeholders', $customdata);
6285          $this->assertCount(1, (array) $customdata->placeholders);
6286          $this->assertObjectNotHasAttribute('notificationiconurl', $customdata);    // No group image means no image.
6287  
6288          // Verify events. Note: the event is a message read event because of an if (PHPUNIT) conditional within message_send(),
6289          // however, we can still determine the number and ids of any recipients this way.
6290          $this->assertCount(2, $events);
6291          $userids = array_column($events, 'userid');
6292          $this->assertNotContains($user1->id, $userids);
6293          $this->assertContains($user3->id, $userids);
6294          $this->assertContains($user4->id, $userids);
6295      }
6296  
6297      /**
6298       * Test verifying that messages can be sent to existing linked group conversations.
6299       */
6300      public function test_send_message_to_conversation_linked_group_conversation() {
6301          global $CFG, $PAGE;
6302  
6303          // Create some users.
6304          $user1 = self::getDataGenerator()->create_user();
6305          $user2 = self::getDataGenerator()->create_user();
6306          $user3 = self::getDataGenerator()->create_user();
6307  
6308          $course = $this->getDataGenerator()->create_course();
6309  
6310          // Create a group with a linked conversation and a valid image.
6311          $this->setAdminUser();
6312          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
6313          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
6314          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
6315          $group = $this->getDataGenerator()->create_group([
6316              'courseid' => $course->id,
6317              'enablemessaging' => 1,
6318              'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
6319          ]);
6320  
6321          // Add users to group.
6322          $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $user1->id));
6323          $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $user2->id));
6324  
6325          // Verify the group with the image works as expected.
6326          $conversations = \core_message\api::get_conversations($user1->id);
6327          $this->assertEquals(2, $conversations[0]->membercount);
6328          $this->assertEquals($course->shortname, $conversations[0]->subname);
6329          $groupimageurl = get_group_picture_url($group, $group->courseid, true);
6330          $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
6331  
6332          // Redirect messages.
6333          // This marks messages as read, but we can still observe and verify the number of conversation recipients,
6334          // based on the message_viewed events generated as part of marking the message as read for each user.
6335          $this->preventResetByRollback();
6336          $sink = $this->redirectMessages();
6337  
6338          // Send a message to a group conversation.
6339          $messagessink = $this->redirectMessages();
6340          $message1 = \core_message\api::send_message_to_conversation($user1->id, $conversations[0]->id,
6341              'message to the group', FORMAT_MOODLE);
6342          $messages = $messagessink->get_messages();
6343          // Verify the message returned.
6344          $this->assertInstanceOf(\stdClass::class, $message1);
6345          $this->assertObjectHasAttribute('id', $message1);
6346          $this->assertAttributeEquals($user1->id, 'useridfrom', $message1);
6347          $this->assertAttributeEquals('message to the group', 'text', $message1);
6348          $this->assertObjectHasAttribute('timecreated', $message1);
6349          // Test customdata.
6350          $customdata = json_decode($messages[0]->customdata);
6351          $this->assertObjectHasAttribute('notificationiconurl', $customdata);
6352          $this->assertObjectHasAttribute('notificationsendericonurl', $customdata);
6353          $this->assertEquals($groupimageurl, $customdata->notificationiconurl);
6354          $this->assertEquals($group->name, $customdata->conversationname);
6355          $userpicture = new \user_picture($user1);
6356          $userpicture->size = 1; // Use f1 size.
6357          $this->assertEquals($userpicture->get_url($PAGE)->out(false), $customdata->notificationsendericonurl);
6358      }
6359  
6360      /**
6361       * Test verifying that messages cannot be sent to conversations that don't exist.
6362       */
6363      public function test_send_message_to_conversation_non_existent_conversation() {
6364          // Get a bunch of conversations, some group, some individual and in different states.
6365          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
6366              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
6367  
6368          $this->expectException(\moodle_exception::class);
6369          \core_message\api::send_message_to_conversation($user1->id, 0, 'test', FORMAT_MOODLE);
6370      }
6371  
6372      /**
6373       * Test verifying that messages cannot be sent to conversations by users who are not members.
6374       */
6375      public function test_send_message_to_conversation_non_member() {
6376          // Get a bunch of conversations, some group, some individual and in different states.
6377          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
6378              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
6379  
6380          // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
6381          $course = $this->getDataGenerator()->create_course();
6382          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
6383          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
6384          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
6385          $this->getDataGenerator()->enrol_user($user4->id, $course->id);
6386  
6387          $this->expectException(\moodle_exception::class);
6388          \core_message\api::send_message_to_conversation($user3->id, $ic1->id, 'test', FORMAT_MOODLE);
6389      }
6390  
6391      /**
6392       * Test verifying that messages cannot be sent to conversations by users who are not members.
6393       */
6394      public function test_send_message_to_conversation_blocked_user() {
6395          // Get a bunch of conversations, some group, some individual and in different states.
6396          list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
6397              $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
6398  
6399          // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
6400          $course = $this->getDataGenerator()->create_course();
6401          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
6402          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
6403          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
6404          $this->getDataGenerator()->enrol_user($user4->id, $course->id);
6405  
6406          // User 1 blocks user 2.
6407          \core_message\api::block_user($user1->id, $user2->id);
6408  
6409          // Verify that a message can be sent to any group conversation in which user1 and user2 are members.
6410          $this->assertNotEmpty(\core_message\api::send_message_to_conversation($user1->id, $gc2->id, 'Hey guys', FORMAT_PLAIN));
6411  
6412          // User 2 cannot send a message to the conversation with user 1.
6413          $this->expectException(\moodle_exception::class);
6414          \core_message\api::send_message_to_conversation($user2->id, $ic1->id, 'test', FORMAT_MOODLE);
6415      }
6416  
6417      /**
6418       * Test the get_conversation() function with a muted conversation.
6419       */
6420      public function test_get_conversation_with_muted_conversation() {
6421          $this->resetAfterTest();
6422  
6423          $user1 = self::getDataGenerator()->create_user();
6424          $user2 = self::getDataGenerator()->create_user();
6425  
6426          $this->setUser($user1);
6427  
6428          $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
6429              [$user1->id, $user2->id]);
6430  
6431          $conversation = \core_message\api::get_conversation($user1->id, $conversation->id);
6432  
6433          $this->assertFalse($conversation->ismuted);
6434  
6435          // Now, mute the conversation.
6436          \core_message\api::mute_conversation($user1->id, $conversation->id);
6437  
6438          $conversation = \core_message\api::get_conversation($user1->id, $conversation->id);
6439  
6440          $this->assertTrue($conversation->ismuted);
6441      }
6442  
6443      /**
6444       * Data provider for test_get_conversation_counts().
6445       */
6446      public function get_conversation_counts_test_cases() {
6447          $typeindividual = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
6448          $typegroup = \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP;
6449          $typeself = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF;
6450          list($user1, $user2, $user3, $user4, $user5, $user6, $user7, $user8) = [0, 1, 2, 3, 4, 5, 6, 7];
6451          $conversations = [
6452              [
6453                  'type' => $typeindividual,
6454                  'users' => [$user1, $user2],
6455                  'messages' => [$user1, $user2, $user2],
6456                  'favourites' => [$user1],
6457                  'enabled' => null // Individual conversations cannot be disabled.
6458              ],
6459              [
6460                  'type' => $typeindividual,
6461                  'users' => [$user1, $user3],
6462                  'messages' => [$user1, $user3, $user1],
6463                  'favourites' => [],
6464                  'enabled' => null // Individual conversations cannot be disabled.
6465              ],
6466              [
6467                  'type' => $typegroup,
6468                  'users' => [$user1, $user2, $user3, $user4],
6469                  'messages' => [$user1, $user2, $user3, $user4],
6470                  'favourites' => [],
6471                  'enabled' => true
6472              ],
6473              [
6474                  'type' => $typegroup,
6475                  'users' => [$user2, $user3, $user4],
6476                  'messages' => [$user2, $user3, $user4],
6477                  'favourites' => [],
6478                  'enabled' => true
6479              ],
6480              [
6481                  'type' => $typegroup,
6482                  'users' => [$user6, $user7],
6483                  'messages' => [$user6, $user7, $user7],
6484                  'favourites' => [$user6],
6485                  'enabled' => false
6486              ],
6487              [
6488                  'type' => $typeself,
6489                  'users' => [$user8],
6490                  'messages' => [$user8],
6491                  'favourites' => [],
6492                  'enabled' => null // Self-conversations cannot be disabled.
6493              ],
6494          ];
6495  
6496          return [
6497              'No conversations' => [
6498                  'conversationConfigs' => $conversations,
6499                  'deletemessagesuser' => null,
6500                  'deletemessages' => [],
6501                  'arguments' => [$user5],
6502                  'expectedcounts' => ['favourites' => 1, 'types' => [
6503                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6504                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6505                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6506                  ]],
6507                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6508                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6509                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6510                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6511                  ]],
6512                  'deletedusers' => []
6513              ],
6514              'No individual conversations, 2 group conversations' => [
6515                  'conversationConfigs' => $conversations,
6516                  'deletemessagesuser' => null,
6517                  'deletemessages' => [],
6518                  'arguments' => [$user4],
6519                  'expectedcounts' => ['favourites' => 1, 'types' => [
6520                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6521                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6522                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6523                  ]],
6524                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6525                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6526                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6527                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6528                  ]],
6529                  'deletedusers' => []
6530              ],
6531              '2 individual conversations (one favourited), 1 group conversation' => [
6532                  'conversationConfigs' => $conversations,
6533                  'deletemessagesuser' => null,
6534                  'deletemessages' => [],
6535                  'arguments' => [$user1],
6536                  'expectedcounts' => ['favourites' => 2, 'types' => [
6537                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6538                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6539                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6540                  ]],
6541                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6542                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6543                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6544                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6545                  ]],
6546                  'deletedusers' => []
6547              ],
6548              '1 individual conversation, 2 group conversations' => [
6549                  'conversationConfigs' => $conversations,
6550                  'deletemessagesuser' => null,
6551                  'deletemessages' => [],
6552                  'arguments' => [$user2],
6553                  'expectedcounts' => ['favourites' => 1, 'types' => [
6554                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6555                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6556                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6557                  ]],
6558                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6559                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6560                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6561                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6562                  ]],
6563                  'deletedusers' => []
6564              ],
6565              '2 group conversations only' => [
6566                  'conversationConfigs' => $conversations,
6567                  'deletemessagesuser' => null,
6568                  'deletemessages' => [],
6569                  'arguments' => [$user4],
6570                  'expectedcounts' => ['favourites' => 1, 'types' => [
6571                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6572                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6573                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6574                  ]],
6575                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6576                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6577                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6578                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6579                  ]],
6580                  'deletedusers' => []
6581              ],
6582              'All conversation types, delete a message from individual favourited, messages remaining' => [
6583                  'conversationConfigs' => $conversations,
6584                  'deletemessagesuser' => $user1,
6585                  'deletemessages' => [0],
6586                  'arguments' => [$user1],
6587                  'expectedcounts' => ['favourites' => 2, 'types' => [
6588                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6589                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6590                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6591                  ]],
6592                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6593                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6594                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6595                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6596                  ]],
6597                  'deletedusers' => []
6598              ],
6599              'All conversation types, delete a message from individual non-favourited, messages remaining' => [
6600                  'conversationConfigs' => $conversations,
6601                  'deletemessagesuser' => $user1,
6602                  'deletemessages' => [3],
6603                  'arguments' => [$user1],
6604                  'expectedcounts' => ['favourites' => 2, 'types' => [
6605                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6606                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6607                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6608                  ]],
6609                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6610                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6611                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6612                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6613                  ]],
6614                  'deletedusers' => []
6615              ],
6616              'All conversation types, delete all messages from individual favourited, no messages remaining' => [
6617                  'conversationConfigs' => $conversations,
6618                  'deletemessagesuser' => $user1,
6619                  'deletemessages' => [0, 1, 2],
6620                  'arguments' => [$user1],
6621                  'expectedcounts' => ['favourites' => 1, 'types' => [
6622                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6623                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6624                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6625                  ]],
6626                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6627                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6628                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6629                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6630                  ]],
6631                  'deletedusers' => []
6632              ],
6633              'All conversation types, delete all messages from individual non-favourited, no messages remaining' => [
6634                  'conversationConfigs' => $conversations,
6635                  'deletemessagesuser' => $user1,
6636                  'deletemessages' => [3, 4, 5],
6637                  'arguments' => [$user1],
6638                  'expectedcounts' => ['favourites' => 2, 'types' => [
6639                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6640                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6641                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6642                  ]],
6643                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6644                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6645                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6646                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6647                  ]],
6648                  'deletedusers' => []
6649              ],
6650              'All conversation types, delete all messages from individual favourited, no messages remaining, different user' => [
6651                  'conversationConfigs' => $conversations,
6652                  'deletemessagesuser' => $user1,
6653                  'deletemessages' => [0, 1, 2],
6654                  'arguments' => [$user2],
6655                  'expectedcounts' => ['favourites' => 1, 'types' => [
6656                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6657                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6658                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6659                  ]],
6660                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6661                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6662                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6663                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6664                  ]],
6665                  'deletedusers' => []
6666              ],
6667              'All conversation types, delete all messages from individual non-favourited, no messages remaining, different user' => [
6668                  'conversationConfigs' => $conversations,
6669                  'deletemessagesuser' => $user1,
6670                  'deletemessages' => [3, 4, 5],
6671                  'arguments' => [$user3],
6672                  'expectedcounts' => ['favourites' => 1, 'types' => [
6673                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6674                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6675                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6676                  ]],
6677                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6678                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6679                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
6680                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6681                  ]],
6682                  'deletedusers' => []
6683              ],
6684              'All conversation types, delete some messages from group non-favourited, messages remaining,' => [
6685                  'conversationConfigs' => $conversations,
6686                  'deletemessagesuser' => $user1,
6687                  'deletemessages' => [6, 7],
6688                  'arguments' => [$user1],
6689                  'expectedcounts' => ['favourites' => 2, 'types' => [
6690                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6691                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6692                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6693                  ]],
6694                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6695                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6696                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6697                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6698                  ]],
6699                  'deletedusers' => []
6700              ],
6701              'All conversation types, delete all messages from group non-favourited, no messages remaining,' => [
6702                  'conversationConfigs' => $conversations,
6703                  'deletemessagesuser' => $user1,
6704                  'deletemessages' => [6, 7, 8, 9],
6705                  'arguments' => [$user1],
6706                  'expectedcounts' => ['favourites' => 2, 'types' => [
6707                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6708                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6709                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6710                  ]],
6711                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6712                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6713                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6714                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6715                  ]],
6716                  'deletedusers' => []
6717              ],
6718              'All conversation types, another user soft deleted' => [
6719                  'conversationConfigs' => $conversations,
6720                  'deletemessagesuser' => null,
6721                  'deletemessages' => [],
6722                  'arguments' => [$user1],
6723                  'expectedcounts' => ['favourites' => 2, 'types' => [
6724                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6725                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6726                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6727                  ]],
6728                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6729                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6730                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6731                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6732                  ]],
6733                  'deletedusers' => [$user2]
6734              ],
6735              'All conversation types, all group users soft deleted' => [
6736                  'conversationConfigs' => $conversations,
6737                  'deletemessagesuser' => null,
6738                  'deletemessages' => [],
6739                  'arguments' => [$user1],
6740                  'expectedcounts' => ['favourites' => 2, 'types' => [
6741                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6742                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6743                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6744                  ]],
6745                  'expectedunreadcounts' => ['favourites' => 1, 'types' => [
6746                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
6747                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
6748                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6749                  ]],
6750                  'deletedusers' => [$user2, $user3, $user4]
6751              ],
6752              'Group conversation which is disabled, favourited' => [
6753                  'conversationConfigs' => $conversations,
6754                  'deletemessagesuser' => null,
6755                  'deletemessages' => [],
6756                  'arguments' => [$user6],
6757                  'expectedcounts' => ['favourites' => 1, 'types' => [
6758                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6759                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6760                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6761                  ]],
6762                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6763                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6764                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6765                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6766                  ]],
6767                  'deletedusers' => []
6768              ],
6769              'Group conversation which is disabled, non-favourited' => [
6770                  'conversationConfigs' => $conversations,
6771                  'deletemessagesuser' => null,
6772                  'deletemessages' => [],
6773                  'arguments' => [$user7],
6774                  'expectedcounts' => ['favourites' => 1, 'types' => [
6775                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6776                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6777                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6778                  ]],
6779                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6780                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6781                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6782                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6783                  ]],
6784                  'deletedusers' => []
6785              ],
6786              'Conversation with self' => [
6787                  'conversationConfigs' => $conversations,
6788                  'deletemessagesuser' => null,
6789                  'deletemessages' => [],
6790                  'arguments' => [$user8],
6791                  'expectedcounts' => ['favourites' => 0, 'types' => [
6792                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6793                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6794                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 1
6795                  ]],
6796                  'expectedunreadcounts' => ['favourites' => 0, 'types' => [
6797                      \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
6798                      \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
6799                      \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0
6800                  ]],
6801                  'deletedusers' => []
6802              ],
6803          ];
6804      }
6805  
6806      /**
6807       * Test the get_conversation_counts() function.
6808       *
6809       * @dataProvider get_conversation_counts_test_cases
6810       * @param array $conversationconfigs Conversations to create
6811       * @param int $deletemessagesuser The user who is deleting the messages
6812       * @param array $deletemessages The list of messages to delete (by index)
6813       * @param array $arguments Arguments for the count conversations function
6814       * @param array $expectedcounts the expected conversation counts
6815       * @param array $expectedunreadcounts the expected unread conversation counts
6816       * @param array $deletedusers the array of users to soft delete.
6817       */
6818      public function test_get_conversation_counts(
6819          $conversationconfigs,
6820          $deletemessagesuser,
6821          $deletemessages,
6822          $arguments,
6823          $expectedcounts,
6824          $expectedunreadcounts,
6825          $deletedusers
6826      ) {
6827          $generator = $this->getDataGenerator();
6828          $users = [
6829              $generator->create_user(),
6830              $generator->create_user(),
6831              $generator->create_user(),
6832              $generator->create_user(),
6833              $generator->create_user(),
6834              $generator->create_user(),
6835              $generator->create_user(),
6836              $generator->create_user()
6837          ];
6838  
6839          $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null;
6840          $arguments[0] = $users[$arguments[0]]->id;
6841          $systemcontext = \context_system::instance();
6842          $conversations = [];
6843          $messageids = [];
6844  
6845          foreach ($conversationconfigs as $config) {
6846              $conversation = \core_message\api::create_conversation(
6847                  $config['type'],
6848                  array_map(function($userindex) use ($users) {
6849                      return $users[$userindex]->id;
6850                  }, $config['users']),
6851                  null,
6852                  ($config['enabled'] ?? true)
6853              );
6854  
6855              foreach ($config['messages'] as $userfromindex) {
6856                  $userfrom = $users[$userfromindex];
6857                  $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id);
6858              }
6859  
6860              // Remove the self conversations created by the generator,
6861              // so we can choose to set that ourself and honour the original intention of the test.
6862              $userids = array_map(function($userindex) use ($users) {
6863                  return $users[$userindex]->id;
6864              }, $config['users']);
6865              foreach ($userids as $userid) {
6866                  if ($conversation->type == \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) {
6867                      \core_message\api::unset_favourite_conversation($conversation->id, $userid);
6868                  }
6869              }
6870  
6871              foreach ($config['favourites'] as $userfromindex) {
6872                  $userfrom = $users[$userfromindex];
6873                  $usercontext = \context_user::instance($userfrom->id);
6874                  $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
6875                  $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext);
6876              }
6877  
6878              $conversations[] = $conversation;
6879          }
6880  
6881          foreach ($deletemessages as $messageindex) {
6882              \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]);
6883          }
6884  
6885          foreach ($deletedusers as $deleteduser) {
6886              delete_user($users[$deleteduser]);
6887          }
6888  
6889          $counts = \core_message\api::get_conversation_counts(...$arguments);
6890  
6891          $this->assertEquals($expectedcounts['favourites'], $counts['favourites']);
6892          $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL],
6893              $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
6894          $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP],
6895              $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]);
6896          $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF],
6897              $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
6898      }
6899  
6900      /**
6901       * Test the count_contacts() function.
6902       */
6903      public function test_count_contacts() {
6904          $user1 = self::getDataGenerator()->create_user();
6905          $user2 = self::getDataGenerator()->create_user();
6906          $user3 = self::getDataGenerator()->create_user();
6907  
6908          $this->assertEquals(0, \core_message\api::count_contacts($user1->id));
6909  
6910          \core_message\api::create_contact_request($user1->id, $user2->id);
6911  
6912          // Still zero until the request is confirmed.
6913          $this->assertEquals(0, \core_message\api::count_contacts($user1->id));
6914  
6915          \core_message\api::confirm_contact_request($user1->id, $user2->id);
6916  
6917          $this->assertEquals(1, \core_message\api::count_contacts($user1->id));
6918  
6919          \core_message\api::create_contact_request($user3->id, $user1->id);
6920  
6921          // Still one until the request is confirmed.
6922          $this->assertEquals(1, \core_message\api::count_contacts($user1->id));
6923  
6924          \core_message\api::confirm_contact_request($user3->id, $user1->id);
6925  
6926          $this->assertEquals(2, \core_message\api::count_contacts($user1->id));
6927      }
6928  
6929      /**
6930       * Test the get_unread_conversation_counts() function.
6931       *
6932       * @dataProvider get_conversation_counts_test_cases
6933       * @param array $conversationconfigs Conversations to create
6934       * @param int $deletemessagesuser The user who is deleting the messages
6935       * @param array $deletemessages The list of messages to delete (by index)
6936       * @param array $arguments Arguments for the count conversations function
6937       * @param array $expectedcounts the expected conversation counts
6938       * @param array $expectedunreadcounts the expected unread conversation counts
6939       * @param array $deletedusers the list of users to soft-delete.
6940       */
6941      public function test_get_unread_conversation_counts(
6942          $conversationconfigs,
6943          $deletemessagesuser,
6944          $deletemessages,
6945          $arguments,
6946          $expectedcounts,
6947          $expectedunreadcounts,
6948          $deletedusers
6949      ) {
6950          $this->resetAfterTest();
6951          $generator = $this->getDataGenerator();
6952          $users = [
6953              $generator->create_user(),
6954              $generator->create_user(),
6955              $generator->create_user(),
6956              $generator->create_user(),
6957              $generator->create_user(),
6958              $generator->create_user(),
6959              $generator->create_user(),
6960              $generator->create_user()
6961          ];
6962  
6963          $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null;
6964          $this->setUser($users[$arguments[0]]);
6965          $arguments[0] = $users[$arguments[0]]->id;
6966          $systemcontext = \context_system::instance();
6967          $conversations = [];
6968          $messageids = [];
6969  
6970          foreach ($conversationconfigs as $config) {
6971              $conversation = \core_message\api::create_conversation(
6972                  $config['type'],
6973                  array_map(function($userindex) use ($users) {
6974                      return $users[$userindex]->id;
6975                  }, $config['users']),
6976                  null,
6977                  ($config['enabled'] ?? true)
6978              );
6979  
6980              foreach ($config['messages'] as $userfromindex) {
6981                  $userfrom = $users[$userfromindex];
6982                  $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id);
6983              }
6984  
6985              foreach ($config['favourites'] as $userfromindex) {
6986                  $userfrom = $users[$userfromindex];
6987                  $usercontext = \context_user::instance($userfrom->id);
6988                  $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
6989                  $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext);
6990              }
6991  
6992              $conversations[] = $conversation;
6993          }
6994  
6995          foreach ($deletemessages as $messageindex) {
6996              \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]);
6997          }
6998  
6999          foreach ($deletedusers as $deleteduser) {
7000              delete_user($users[$deleteduser]);
7001          }
7002  
7003          $counts = \core_message\api::get_unread_conversation_counts(...$arguments);
7004  
7005          $this->assertEquals($expectedunreadcounts['favourites'], $counts['favourites']);
7006          $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL],
7007              $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
7008          $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP],
7009              $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]);
7010          $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF],
7011              $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]);
7012      }
7013  
7014      public function test_delete_all_conversation_data() {
7015          global $DB;
7016  
7017          $this->resetAfterTest();
7018  
7019          $this->setAdminUser();
7020  
7021          $course1 = $this->getDataGenerator()->create_course();
7022          $coursecontext1 = context_course::instance($course1->id);
7023  
7024          $user1 = $this->getDataGenerator()->create_user();
7025          $user2 = $this->getDataGenerator()->create_user();
7026  
7027          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
7028          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
7029  
7030          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id, 'enablemessaging' => 1));
7031          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id, 'enablemessaging' => 1));
7032  
7033          // Add users to both groups.
7034          $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
7035          $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
7036  
7037          $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user1->id));
7038          $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
7039  
7040          $groupconversation1 = \core_message\api::get_conversation_by_area(
7041              'core_group',
7042              'groups',
7043              $group1->id,
7044              $coursecontext1->id
7045          );
7046  
7047          $groupconversation2 = \core_message\api::get_conversation_by_area(
7048              'core_group',
7049              'groups',
7050              $group2->id,
7051              $coursecontext1->id
7052          );
7053  
7054          // Send a few messages.
7055          $g1m1 = \core_message\tests\helper::send_fake_message_to_conversation($user1, $groupconversation1->id);
7056          $g1m2 = \core_message\tests\helper::send_fake_message_to_conversation($user2, $groupconversation1->id);
7057          $g1m3 = \core_message\tests\helper::send_fake_message_to_conversation($user1, $groupconversation1->id);
7058          $g1m4 = \core_message\tests\helper::send_fake_message_to_conversation($user2, $groupconversation1->id);
7059  
7060          $g2m1 = \core_message\tests\helper::send_fake_message_to_conversation($user1, $groupconversation2->id);
7061          $g2m2 = \core_message\tests\helper::send_fake_message_to_conversation($user2, $groupconversation2->id);
7062          $g2m3 = \core_message\tests\helper::send_fake_message_to_conversation($user1, $groupconversation2->id);
7063          $g2m4 = \core_message\tests\helper::send_fake_message_to_conversation($user2, $groupconversation2->id);
7064  
7065          // Favourite the conversation for several of the users.
7066          \core_message\api::set_favourite_conversation($groupconversation1->id, $user1->id);
7067          \core_message\api::set_favourite_conversation($groupconversation1->id, $user2->id);
7068  
7069          // Delete a few messages.
7070          \core_message\api::delete_message($user1->id, $g1m1);
7071          \core_message\api::delete_message($user1->id, $g1m2);
7072          \core_message\api::delete_message($user1->id, $g2m1);
7073          \core_message\api::delete_message($user1->id, $g2m2);
7074  
7075          // Mute the conversations.
7076          \core_message\api::mute_conversation($user1->id, $groupconversation1->id);
7077          \core_message\api::mute_conversation($user1->id, $groupconversation2->id);
7078  
7079          // Now, delete all the data for the group 1 conversation.
7080          \core_message\api::delete_all_conversation_data($groupconversation1->id);
7081  
7082          // Confirm group conversation was deleted just for the group 1 conversation.
7083          $this->assertEquals(0, $DB->count_records('message_conversations', ['id' => $groupconversation1->id]));
7084          $this->assertEquals(1, $DB->count_records('message_conversations', ['id' => $groupconversation2->id]));
7085  
7086          // Confirm conversation members were deleted just for the group 1 conversation.
7087          $this->assertEquals(0, $DB->count_records('message_conversation_members', ['conversationid' => $groupconversation1->id]));
7088          $this->assertEquals(2, $DB->count_records('message_conversation_members', ['conversationid' => $groupconversation2->id]));
7089  
7090          // Confirm message conversation actions were deleted just for the group 1 conversation.
7091          $this->assertEquals(0, $DB->count_records('message_conversation_actions', ['conversationid' => $groupconversation1->id]));
7092          $this->assertEquals(1, $DB->count_records('message_conversation_actions', ['conversationid' => $groupconversation2->id]));
7093  
7094          // Confirm message user actions were deleted just for the group 1 conversation.
7095          $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m1]));
7096          $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m2]));
7097          $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m3]));
7098          $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m4]));
7099          $this->assertEquals(1, $DB->count_records('message_user_actions', ['messageid' => $g2m1]));
7100          $this->assertEquals(1, $DB->count_records('message_user_actions', ['messageid' => $g2m2]));
7101          $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g2m3]));
7102          $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g2m4]));
7103  
7104          // Confirm messages were deleted just for the group 1 conversation.
7105          $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m1]));
7106          $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m2]));
7107          $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m3]));
7108          $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m4]));
7109          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m1]));
7110          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m2]));
7111          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m3]));
7112          $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m4]));
7113  
7114          // Confirm favourites were deleted for both users.
7115          $user1service = \core_favourites\service_factory::get_service_for_user_context(context_user::instance($user1->id));
7116          $this->assertFalse($user1service->favourite_exists('core_message', 'message_conversations', $groupconversation1->id,
7117              $coursecontext1));
7118          $user2service = \core_favourites\service_factory::get_service_for_user_context(context_user::instance($user1->id));
7119          $this->assertFalse($user2service->favourite_exists('core_message', 'message_conversations', $groupconversation1->id,
7120              $coursecontext1));
7121      }
7122  
7123      /**
7124       * Tests the user can delete message for all users as a teacher.
7125       */
7126      public function test_can_delete_message_for_all_users_teacher() {
7127          global $DB;
7128          $this->resetAfterTest(true);
7129  
7130          // Create fake data to test it.
7131          list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
7132  
7133          // Allow Teacher can delete messages for all.
7134          $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']);
7135          assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, context_system::instance());
7136  
7137          // Set as the first user.
7138          $this->setUser($teacher);
7139  
7140          // Send a message to private conversation and in a group conversation.
7141          $messageidind = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convindividual->id);
7142          $messageidgrp = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convgroup->id);
7143  
7144          // Teacher cannot delete message for everyone in a private conversation.
7145          $this->assertFalse(\core_message\api::can_delete_message_for_all_users($teacher->id, $messageidind));
7146  
7147          // Teacher can delete message for everyone in a group conversation.
7148          $this->assertTrue(\core_message\api::can_delete_message_for_all_users($teacher->id, $messageidgrp));
7149      }
7150  
7151      /**
7152       * Tests the user can delete message for all users as a student.
7153       */
7154      public function test_can_delete_message_for_all_users_student() {
7155          $this->resetAfterTest(true);
7156  
7157          // Create fake data to test it.
7158          list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
7159  
7160          // Set as the first user.
7161          $this->setUser($student1);
7162  
7163          // Send a message to private conversation and in a group conversation.
7164          $messageidind = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convindividual->id);
7165          $messageidgrp = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convgroup->id);
7166  
7167          // Student1 cannot delete message for everyone in a private conversation.
7168          $this->assertFalse(\core_message\api::can_delete_message_for_all_users($student1->id, $messageidind));
7169  
7170          // Student1 cannot delete message for everyone in a group conversation.
7171          $this->assertFalse(\core_message\api::can_delete_message_for_all_users($student1->id, $messageidgrp));
7172      }
7173  
7174      /**
7175       * Tests tdelete message for all users in group conversation.
7176       */
7177      public function test_delete_message_for_all_users_group_conversation() {
7178          global $DB;
7179          $this->resetAfterTest(true);
7180  
7181          // Create fake data to test it.
7182          list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
7183  
7184          // Send 3 messages to a group conversation.
7185          $mgid1 = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convgroup->id);
7186          $mgid2 = \core_message\tests\helper::send_fake_message_to_conversation($student1, $convgroup->id);
7187          $mgid3 = \core_message\tests\helper::send_fake_message_to_conversation($student2, $convgroup->id);
7188  
7189          // Delete message 1 for all users.
7190          \core_message\api::delete_message_for_all_users($mgid1);
7191  
7192          // Get the messages to check if the message 1 was deleted for teacher.
7193          $convmessages1 = \core_message\api::get_conversation_messages($teacher->id, $convgroup->id);
7194          // Only has to remains 2 messages.
7195          $this->assertCount(2, $convmessages1['messages']);
7196          // Check if no one of the two messages is message 1.
7197          foreach ($convmessages1['messages'] as $message) {
7198              $this->assertNotEquals($mgid1, $message->id);
7199          }
7200  
7201          // Get the messages to check if the message 1 was deleted for student1.
7202          $convmessages2 = \core_message\api::get_conversation_messages($student1->id, $convgroup->id);
7203          // Only has to remains 2 messages.
7204          $this->assertCount(2, $convmessages2['messages']);
7205          // Check if no one of the two messages is message 1.
7206          foreach ($convmessages2['messages'] as $message) {
7207              $this->assertNotEquals($mgid1, $message->id);
7208          }
7209  
7210          // Get the messages to check if the message 1 was deleted for student2.
7211          $convmessages3 = \core_message\api::get_conversation_messages($student2->id, $convgroup->id);
7212          // Only has to remains 2 messages.
7213          $this->assertCount(2, $convmessages3['messages']);
7214          // Check if no one of the two messages is message 1.
7215          foreach ($convmessages3['messages'] as $message) {
7216              $this->assertNotEquals($mgid1, $message->id);
7217          }
7218      }
7219  
7220      /**
7221       * Tests delete message for all users in private conversation.
7222       */
7223      public function test_delete_message_for_all_users_individual_conversation() {
7224          global $DB;
7225          $this->resetAfterTest(true);
7226  
7227          // Create fake data to test it.
7228          list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
7229  
7230          // Send 2 messages in a individual conversation.
7231          $mid1 = \core_message\tests\helper::send_fake_message_to_conversation($teacher, $convindividual->id);
7232          $mid2 = \core_message\tests\helper::send_fake_message_to_conversation($student1, $convindividual->id);
7233  
7234          // Delete the first message for all users.
7235          \core_message\api::delete_message_for_all_users($mid1);
7236  
7237          // Get the messages to check if the message 1 was deleted for teacher.
7238          $convmessages1 = \core_message\api::get_conversation_messages($teacher->id, $convindividual->id);
7239          // Only has to remains 1 messages for teacher.
7240          $this->assertCount(1, $convmessages1['messages']);
7241          // Check the one messages remains not is the first message.
7242          $this->assertNotEquals($mid1, $convmessages1['messages'][0]->id);
7243  
7244          // Get the messages to check if the message 1 was deleted for student1.
7245          $convmessages2 = \core_message\api::get_conversation_messages($student1->id, $convindividual->id);
7246          // Only has to remains 1 messages for student1.
7247          $this->assertCount(1, $convmessages2['messages']);
7248          // Check the one messages remains not is the first message.
7249          $this->assertNotEquals($mid1, $convmessages2['messages'][0]->id);
7250      }
7251  
7252      /**
7253       * Test retrieving conversation messages by providing a timefrom higher than last message timecreated. It should return no
7254       * messages but keep the return structure to not break when called from the ws.
7255       */
7256      public function test_get_conversation_messages_timefrom_higher_than_last_timecreated() {
7257          // Create some users.
7258          $user1 = self::getDataGenerator()->create_user();
7259          $user2 = self::getDataGenerator()->create_user();
7260          $user3 = self::getDataGenerator()->create_user();
7261          $user4 = self::getDataGenerator()->create_user();
7262  
7263          // Create group conversation.
7264          $conversation = \core_message\api::create_conversation(
7265              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
7266              [$user1->id, $user2->id, $user3->id, $user4->id]
7267          );
7268  
7269          // The person doing the search.
7270          $this->setUser($user1);
7271  
7272          // Send some messages back and forth.
7273          $time = 1;
7274          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
7275          testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
7276          testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
7277          testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
7278  
7279          // Retrieve the messages from $time + 5, which should return no messages.
7280          $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, '', $time + 5);
7281  
7282          // Confirm the conversation id is correct.
7283          $this->assertEquals($conversation->id, $convmessages['id']);
7284  
7285          // Confirm the message data is correct.
7286          $messages = $convmessages['messages'];
7287          $this->assertEquals(0, count($messages));
7288  
7289          // Confirm that members key is present.
7290          $this->assertArrayHasKey('members', $convmessages);
7291      }
7292  
7293      /**
7294       * Helper to seed the database with initial state with data.
7295       */
7296      protected function create_delete_message_test_data() {
7297          // Create some users.
7298          $teacher = self::getDataGenerator()->create_user();
7299          $student1 = self::getDataGenerator()->create_user();
7300          $student2 = self::getDataGenerator()->create_user();
7301  
7302          // Create a course and enrol the users.
7303          $course = $this->getDataGenerator()->create_course();
7304          $coursecontext = context_course::instance($course->id);
7305          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
7306          $this->getDataGenerator()->enrol_user($student1->id, $course->id, 'student');
7307          $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student');
7308  
7309          // Create a group and added the users into.
7310          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
7311          groups_add_member($group1->id, $teacher->id);
7312          groups_add_member($group1->id, $student1->id);
7313          groups_add_member($group1->id, $student2->id);
7314  
7315          // Create a group conversation linked with the course.
7316          $convgroup = \core_message\api::create_conversation(
7317              \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
7318              [$teacher->id, $student1->id, $student2->id],
7319              'Group test delete for everyone', \core_message\api::MESSAGE_CONVERSATION_ENABLED,
7320              'core_group',
7321              'groups',
7322              $group1->id,
7323              context_course::instance($course->id)->id
7324          );
7325  
7326          // Create and individual conversation.
7327          $convindividual = \core_message\api::create_conversation(
7328              \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
7329              [$teacher->id, $student1->id]
7330          );
7331  
7332          return [$teacher, $student1, $student2, $convgroup, $convindividual];
7333      }
7334  
7335      /**
7336       * Comparison function for sorting contacts.
7337       *
7338       * @param stdClass $a
7339       * @param stdClass $b
7340       * @return bool
7341       */
7342      protected static function sort_contacts($a, $b) {
7343          return $a->userid > $b->userid;
7344      }
7345  }