Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_message; 18 19 use core_message\tests\helper as testhelper; 20 use core_message_external; 21 use externallib_advanced_testcase; 22 23 defined('MOODLE_INTERNAL') || die(); 24 25 global $CFG; 26 27 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 28 require_once($CFG->dirroot . '/message/externallib.php'); 29 30 /** 31 * External message functions unit tests 32 * 33 * @package core_message 34 * @category external 35 * @copyright 2012 Jerome Mouneyrac 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class externallib_test extends externallib_advanced_testcase { 39 40 /** 41 * Tests set up 42 */ 43 protected function setUp(): void { 44 global $CFG; 45 46 require_once($CFG->dirroot . '/message/lib.php'); 47 } 48 49 /** 50 * Send a fake message. 51 * 52 * {@link message_send()} does not support transaction, this function will simulate a message 53 * sent from a user to another. We should stop using it once {@link message_send()} will support 54 * transactions. This is not clean at all, this is just used to add rows to the table. 55 * 56 * @param \stdClass $userfrom user object of the one sending the message. 57 * @param \stdClass $userto user object of the one receiving the message. 58 * @param string $message message to send. 59 * @param int $notification is the message a notification. 60 * @param int $time the time the message was sent 61 */ 62 protected function send_message($userfrom, $userto, $message = 'Hello world!', $notification = 0, $time = 0) { 63 global $DB; 64 65 if (empty($time)) { 66 $time = time(); 67 } 68 69 if ($notification) { 70 $record = new \stdClass(); 71 $record->useridfrom = $userfrom->id; 72 $record->useridto = $userto->id; 73 $record->subject = 'No subject'; 74 $record->fullmessage = $message; 75 $record->smallmessage = $message; 76 $record->timecreated = $time; 77 78 return $DB->insert_record('notifications', $record); 79 } 80 81 if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) { 82 $conversation = \core_message\api::create_conversation( 83 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 84 [ 85 $userfrom->id, 86 $userto->id 87 ] 88 ); 89 $conversationid = $conversation->id; 90 } 91 92 // Ok, send the message. 93 $record = new \stdClass(); 94 $record->useridfrom = $userfrom->id; 95 $record->conversationid = $conversationid; 96 $record->subject = 'No subject'; 97 $record->fullmessage = $message; 98 $record->smallmessage = $message; 99 $record->timecreated = $time; 100 101 return $DB->insert_record('messages', $record); 102 } 103 104 /** 105 * Test send_instant_messages. 106 */ 107 public function test_send_instant_messages() { 108 global $DB, $USER; 109 110 $this->resetAfterTest(); 111 112 // Transactions used in tests, tell phpunit use alternative reset method. 113 $this->preventResetByRollback(); 114 115 $user1 = self::getDataGenerator()->create_user(); 116 $user2 = self::getDataGenerator()->create_user(); 117 118 $this->setUser($user1); 119 120 // Create test message data. 121 $message1 = array(); 122 $message1['touserid'] = $user2->id; 123 $message1['text'] = 'the message.'; 124 $message1['clientmsgid'] = 4; 125 $messages = array($message1); 126 127 $sentmessages = core_message_external::send_instant_messages($messages); 128 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 129 $this->assertEquals( 130 get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message1['touserid']))), 131 array_pop($sentmessages)['errormessage'] 132 ); 133 134 // Add the user1 as a contact. 135 \core_message\api::add_contact($user1->id, $user2->id); 136 137 // Send message again. Now it should work properly. 138 $sentmessages = core_message_external::send_instant_messages($messages); 139 // We need to execute the return values cleaning process to simulate the web service server. 140 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 141 142 $sentmessage = reset($sentmessages); 143 144 $sql = "SELECT m.*, mcm.userid as useridto 145 FROM {messages} m 146 INNER JOIN {message_conversations} mc 147 ON m.conversationid = mc.id 148 INNER JOIN {message_conversation_members} mcm 149 ON mcm.conversationid = mc.id 150 WHERE mcm.userid != ? 151 AND m.id = ?"; 152 $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]); 153 154 // Confirm that the message was inserted correctly. 155 $this->assertEquals($themessage->useridfrom, $user1->id); 156 $this->assertEquals($themessage->useridto, $message1['touserid']); 157 $this->assertEquals($themessage->smallmessage, $message1['text']); 158 $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']); 159 } 160 161 /** 162 * Test send_instant_messages with a message text longer than permitted. 163 */ 164 public function test_send_instant_messages_long_text() { 165 global $CFG; 166 167 $this->resetAfterTest(true); 168 169 // Transactions used in tests, tell phpunit use alternative reset method. 170 $this->preventResetByRollback(); 171 172 $user1 = self::getDataGenerator()->create_user(); 173 $user2 = self::getDataGenerator()->create_user(); 174 175 $this->setUser($user1); 176 177 // Create test message data. 178 $message1 = [ 179 'touserid' => $user2->id, 180 'text' => str_repeat("M", \core_message\api::MESSAGE_MAX_LENGTH + 100), 181 'clientmsgid' => 4, 182 ]; 183 $messages = [$message1]; 184 185 // Add the user1 as a contact. 186 \core_message\api::add_contact($user1->id, $user2->id); 187 188 $sentmessages = core_message_external::send_instant_messages($messages); 189 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 190 $this->assertEquals( 191 get_string('errormessagetoolong', 'message'), 192 array_pop($sentmessages)['errormessage'] 193 ); 194 } 195 196 /** 197 * Test send_instant_messages to a user who has blocked you. 198 */ 199 public function test_send_instant_messages_blocked_user() { 200 global $DB; 201 202 $this->resetAfterTest(); 203 204 // Transactions used in tests, tell phpunit use alternative reset method. 205 $this->preventResetByRollback(); 206 207 $user1 = self::getDataGenerator()->create_user(); 208 $user2 = self::getDataGenerator()->create_user(); 209 210 $this->setUser($user1); 211 212 \core_message\api::block_user($user2->id, $user1->id); 213 214 // Create test message data. 215 $message1 = array(); 216 $message1['touserid'] = $user2->id; 217 $message1['text'] = 'the message.'; 218 $message1['clientmsgid'] = 4; 219 $messages = array($message1); 220 221 $sentmessages = core_message_external::send_instant_messages($messages); 222 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 223 224 $sentmessage = reset($sentmessages); 225 226 $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']); 227 228 $this->assertEquals(0, $DB->count_records('messages')); 229 } 230 231 /** 232 * Test send_instant_messages when sending a message to a non-contact who has blocked non-contacts. 233 */ 234 public function test_send_instant_messages_block_non_contacts() { 235 global $DB; 236 237 $this->resetAfterTest(true); 238 239 // Transactions used in tests, tell phpunit use alternative reset method. 240 $this->preventResetByRollback(); 241 242 $user1 = self::getDataGenerator()->create_user(); 243 $user2 = self::getDataGenerator()->create_user(); 244 245 $this->setUser($user1); 246 247 // Set the user preference so user 2 does not accept messages from non-contacts. 248 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2); 249 250 // Create test message data. 251 $message1 = array(); 252 $message1['touserid'] = $user2->id; 253 $message1['text'] = 'the message.'; 254 $message1['clientmsgid'] = 4; 255 $messages = array($message1); 256 257 $sentmessages = core_message_external::send_instant_messages($messages); 258 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 259 260 $sentmessage = reset($sentmessages); 261 262 $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']); 263 264 $this->assertEquals(0, $DB->count_records('messages')); 265 } 266 267 /** 268 * Test send_instant_messages when sending a message to a contact who has blocked non-contacts. 269 */ 270 public function test_send_instant_messages_block_non_contacts_but_am_contact() { 271 global $DB, $USER; 272 273 $this->resetAfterTest(true); 274 275 // Transactions used in tests, tell phpunit use alternative reset method. 276 $this->preventResetByRollback(); 277 278 $user1 = self::getDataGenerator()->create_user(); 279 $user2 = self::getDataGenerator()->create_user(); 280 281 $this->setUser($user1); 282 283 // Set the user preference so user 2 does not accept messages from non-contacts. 284 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2); 285 286 \core_message\api::add_contact($user1->id, $user2->id); 287 288 // Create test message data. 289 $message1 = array(); 290 $message1['touserid'] = $user2->id; 291 $message1['text'] = 'the message.'; 292 $message1['clientmsgid'] = 4; 293 $messages = array($message1); 294 295 $sentmessages = core_message_external::send_instant_messages($messages); 296 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 297 298 $sentmessage = reset($sentmessages); 299 300 $sql = "SELECT m.*, mcm.userid as useridto 301 FROM {messages} m 302 INNER JOIN {message_conversations} mc 303 ON m.conversationid = mc.id 304 INNER JOIN {message_conversation_members} mcm 305 ON mcm.conversationid = mc.id 306 WHERE mcm.userid != ? 307 AND m.id = ?"; 308 $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]); 309 310 // Confirm that the message was inserted correctly. 311 $this->assertEquals($themessage->useridfrom, $user1->id); 312 $this->assertEquals($themessage->useridto, $message1['touserid']); 313 $this->assertEquals($themessage->smallmessage, $message1['text']); 314 $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']); 315 } 316 317 /** 318 * Test send_instant_messages with no capabilities 319 */ 320 public function test_send_instant_messages_no_capability() { 321 global $DB; 322 323 $this->resetAfterTest(true); 324 325 // Transactions used in tests, tell phpunit use alternative reset method. 326 $this->preventResetByRollback(); 327 328 $user1 = self::getDataGenerator()->create_user(); 329 $user2 = self::getDataGenerator()->create_user(); 330 331 $this->setUser($user1); 332 333 // Unset the required capabilities by the external function. 334 $contextid = \context_system::instance()->id; 335 $userrole = $DB->get_record('role', array('shortname' => 'user')); 336 $this->unassignUserCapability('moodle/site:sendmessage', $contextid, $userrole->id); 337 338 // Create test message data. 339 $message1 = array(); 340 $message1['touserid'] = $user2->id; 341 $message1['text'] = 'the message.'; 342 $message1['clientmsgid'] = 4; 343 $messages = array($message1); 344 345 $this->expectException('required_capability_exception'); 346 core_message_external::send_instant_messages($messages); 347 } 348 349 /** 350 * Test send_instant_messages when messaging is disabled. 351 */ 352 public function test_send_instant_messages_messaging_disabled() { 353 global $CFG; 354 355 $this->resetAfterTest(true); 356 357 // Transactions used in tests, tell phpunit use alternative reset method. 358 $this->preventResetByRollback(); 359 360 $user1 = self::getDataGenerator()->create_user(); 361 $user2 = self::getDataGenerator()->create_user(); 362 363 $this->setUser($user1); 364 365 // Disable messaging. 366 $CFG->messaging = 0; 367 368 // Create test message data. 369 $message1 = array(); 370 $message1['touserid'] = $user2->id; 371 $message1['text'] = 'the message.'; 372 $message1['clientmsgid'] = 4; 373 $messages = array($message1); 374 375 $this->expectException('moodle_exception'); 376 core_message_external::send_instant_messages($messages); 377 } 378 379 /** 380 * Test delete_contacts. 381 */ 382 public function test_delete_contacts() { 383 $this->resetAfterTest(true); 384 385 $user1 = self::getDataGenerator()->create_user(); 386 $user2 = self::getDataGenerator()->create_user(); 387 $user3 = self::getDataGenerator()->create_user(); 388 $user4 = self::getDataGenerator()->create_user(); 389 $user5 = self::getDataGenerator()->create_user(); 390 $user6 = self::getDataGenerator()->create_user(); 391 $this->setUser($user1); 392 393 \core_message\api::add_contact($user1->id, $user3->id); 394 \core_message\api::add_contact($user1->id, $user4->id); 395 \core_message\api::add_contact($user1->id, $user5->id); 396 \core_message\api::add_contact($user1->id, $user6->id); 397 398 // Removing a non-contact. 399 $return = core_message_external::delete_contacts(array($user2->id)); 400 $this->assertNull($return); 401 402 // Removing one contact. 403 $return = core_message_external::delete_contacts(array($user3->id)); 404 $this->assertNull($return); 405 406 // Removing multiple contacts. 407 $return = core_message_external::delete_contacts(array($user4->id, $user5->id)); 408 $this->assertNull($return); 409 410 // Removing contact from unexisting user. 411 $return = core_message_external::delete_contacts(array(99999)); 412 $this->assertNull($return); 413 414 // Removing mixed valid and invalid data. 415 $return = core_message_external::delete_contacts(array($user6->id, 99999)); 416 $this->assertNull($return); 417 418 // Try to delete a contact of another user contact list, should throw an exception. 419 // All assertions must be added before this point. 420 $this->expectException('required_capability_exception'); 421 core_message_external::delete_contacts(array($user2->id), $user3->id); 422 } 423 424 /** 425 * Test getting contact requests. 426 */ 427 public function test_get_contact_requests() { 428 global $PAGE; 429 430 $this->resetAfterTest(); 431 432 $user1 = self::getDataGenerator()->create_user(); 433 $user2 = self::getDataGenerator()->create_user(); 434 $user3 = self::getDataGenerator()->create_user(); 435 436 $this->setUser($user1); 437 438 // Block one user, their request should not show up. 439 \core_message\api::block_user($user1->id, $user3->id); 440 441 \core_message\api::create_contact_request($user2->id, $user1->id); 442 \core_message\api::create_contact_request($user3->id, $user1->id); 443 444 $requests = core_message_external::get_contact_requests($user1->id); 445 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 446 447 $this->assertCount(1, $requests); 448 449 $request = reset($requests); 450 $userpicture = new \user_picture($user2); 451 $profileimageurl = $userpicture->get_url($PAGE)->out(false); 452 453 $this->assertEquals($user2->id, $request['id']); 454 $this->assertEquals(fullname($user2), $request['fullname']); 455 $this->assertArrayHasKey('profileimageurl', $request); 456 $this->assertArrayHasKey('profileimageurlsmall', $request); 457 $this->assertArrayHasKey('isonline', $request); 458 $this->assertArrayHasKey('showonlinestatus', $request); 459 $this->assertArrayHasKey('isblocked', $request); 460 $this->assertArrayHasKey('iscontact', $request); 461 } 462 463 /** 464 * Test the get_contact_requests() function when the user has blocked the sender of the request. 465 */ 466 public function test_get_contact_requests_blocked_sender() { 467 $this->resetAfterTest(); 468 $user1 = self::getDataGenerator()->create_user(); 469 $user2 = self::getDataGenerator()->create_user(); 470 471 // User1 blocks User2. 472 \core_message\api::block_user($user1->id, $user2->id); 473 474 // User2 tries to add User1 as a contact. 475 \core_message\api::create_contact_request($user2->id, $user1->id); 476 477 // Verify we don't see the contact request from the blocked user User2 in the requests for User1. 478 $this->setUser($user1); 479 $requests = core_message_external::get_contact_requests($user1->id); 480 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 481 482 $this->assertCount(0, $requests); 483 } 484 485 /** 486 * Test getting contact requests when there are none. 487 */ 488 public function test_get_contact_requests_no_requests() { 489 $this->resetAfterTest(); 490 491 $user1 = self::getDataGenerator()->create_user(); 492 493 $this->setUser($user1); 494 495 $requests = core_message_external::get_contact_requests($user1->id); 496 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 497 498 $this->assertEmpty($requests); 499 } 500 501 /** 502 * Test getting contact requests with limits. 503 */ 504 public function test_get_contact_requests_with_limits() { 505 $this->resetAfterTest(); 506 507 $user1 = self::getDataGenerator()->create_user(); 508 $user2 = self::getDataGenerator()->create_user(); 509 $user3 = self::getDataGenerator()->create_user(); 510 511 $this->setUser($user1); 512 513 \core_message\api::create_contact_request($user2->id, $user1->id); 514 \core_message\api::create_contact_request($user3->id, $user1->id); 515 516 $requests = core_message_external::get_contact_requests($user1->id, 0, 1); 517 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 518 519 $this->assertCount(1, $requests); 520 } 521 522 /** 523 * Test getting contact requests with messaging disabled. 524 */ 525 public function test_get_contact_requests_messaging_disabled() { 526 global $CFG; 527 528 $this->resetAfterTest(); 529 530 // Create some skeleton data just so we can call the WS. 531 $user1 = self::getDataGenerator()->create_user(); 532 533 $this->setUser($user1); 534 535 // Disable messaging. 536 $CFG->messaging = 0; 537 538 // Ensure an exception is thrown. 539 $this->expectException('moodle_exception'); 540 core_message_external::get_contact_requests($user1->id); 541 } 542 543 /** 544 * Test getting contact requests with no permission. 545 */ 546 public function test_get_contact_requests_no_permission() { 547 $this->resetAfterTest(); 548 549 // Create some skeleton data just so we can call the WS. 550 $user1 = self::getDataGenerator()->create_user(); 551 $user2 = self::getDataGenerator()->create_user(); 552 $user3 = self::getDataGenerator()->create_user(); 553 554 $this->setUser($user3); 555 556 // Ensure an exception is thrown. 557 $this->expectException('required_capability_exception'); 558 core_message_external::create_contact_request($user1->id, $user2->id); 559 } 560 561 /** 562 * Test getting the number of received contact requests. 563 */ 564 public function test_get_received_contact_requests_count() { 565 $this->resetAfterTest(); 566 567 $user1 = self::getDataGenerator()->create_user(); 568 $user2 = self::getDataGenerator()->create_user(); 569 $user3 = self::getDataGenerator()->create_user(); 570 $user4 = self::getDataGenerator()->create_user(); 571 572 $this->setUser($user1); 573 574 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 575 $contactrequestnumber = \external_api::clean_returnvalue( 576 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 577 $this->assertEquals(0, $contactrequestnumber); 578 579 \core_message\api::create_contact_request($user2->id, $user1->id); 580 581 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 582 $contactrequestnumber = \external_api::clean_returnvalue( 583 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 584 $this->assertEquals(1, $contactrequestnumber); 585 586 \core_message\api::create_contact_request($user3->id, $user1->id); 587 588 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 589 $contactrequestnumber = \external_api::clean_returnvalue( 590 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 591 $this->assertEquals(2, $contactrequestnumber); 592 593 \core_message\api::create_contact_request($user1->id, $user4->id); 594 595 // Web service should ignore sent requests. 596 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 597 $contactrequestnumber = \external_api::clean_returnvalue( 598 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 599 $this->assertEquals(2, $contactrequestnumber); 600 } 601 602 /** 603 * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request. 604 */ 605 public function test_get_received_contact_requests_count_blocked_sender() { 606 $this->resetAfterTest(); 607 $user1 = self::getDataGenerator()->create_user(); 608 $user2 = self::getDataGenerator()->create_user(); 609 610 // User1 blocks User2. 611 \core_message\api::block_user($user1->id, $user2->id); 612 613 // User2 tries to add User1 as a contact. 614 \core_message\api::create_contact_request($user2->id, $user1->id); 615 616 // Verify we don't see the contact request from the blocked user User2 in the count for User1. 617 $this->setUser($user1); 618 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 619 $contactrequestnumber = \external_api::clean_returnvalue( 620 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 621 $this->assertEquals(0, $contactrequestnumber); 622 } 623 624 /** 625 * Test getting the number of received contact requests with no permissions. 626 */ 627 public function test_get_received_contact_requests_count_no_permission() { 628 $this->resetAfterTest(); 629 630 // Create some skeleton data just so we can call the WS. 631 $user1 = self::getDataGenerator()->create_user(); 632 $user2 = self::getDataGenerator()->create_user(); 633 634 $this->setUser($user2); 635 636 // Ensure an exception is thrown. 637 $this->expectException('required_capability_exception'); 638 core_message_external::get_received_contact_requests_count($user1->id); 639 } 640 641 /** 642 * Test getting the number of received contact requests with messaging disabled. 643 */ 644 public function test_get_received_contact_requests_count_messaging_disabled() { 645 global $CFG; 646 647 $this->resetAfterTest(); 648 649 // Create some skeleton data just so we can call the WS. 650 $user1 = self::getDataGenerator()->create_user(); 651 652 $this->setUser($user1); 653 654 // Disable messaging. 655 $CFG->messaging = 0; 656 657 // Ensure an exception is thrown. 658 $this->expectException('moodle_exception'); 659 core_message_external::get_received_contact_requests_count($user1->id); 660 } 661 662 /** 663 * Test creating a contact request. 664 */ 665 public function test_create_contact_request() { 666 global $CFG, $DB; 667 668 $this->resetAfterTest(); 669 670 $user1 = self::getDataGenerator()->create_user(); 671 $user2 = self::getDataGenerator()->create_user(); 672 673 $this->setUser($user1); 674 675 // Allow users to message anyone site-wide. 676 $CFG->messagingallusers = 1; 677 678 $return = core_message_external::create_contact_request($user1->id, $user2->id); 679 $return = \external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return); 680 $this->assertEquals([], $return['warnings']); 681 682 $request = $DB->get_records('message_contact_requests'); 683 684 $this->assertCount(1, $request); 685 686 $request = reset($request); 687 688 $this->assertEquals($request->id, $return['request']['id']); 689 $this->assertEquals($request->userid, $return['request']['userid']); 690 $this->assertEquals($request->requesteduserid, $return['request']['requesteduserid']); 691 $this->assertEquals($request->timecreated, $return['request']['timecreated']); 692 } 693 694 /** 695 * Test creating a contact request when not allowed. 696 */ 697 public function test_create_contact_request_not_allowed() { 698 global $CFG; 699 700 $this->resetAfterTest(); 701 702 $user1 = self::getDataGenerator()->create_user(); 703 $user2 = self::getDataGenerator()->create_user(); 704 705 $this->setUser($user1); 706 707 $CFG->messagingallusers = 0; 708 709 $return = core_message_external::create_contact_request($user1->id, $user2->id); 710 $return = \external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return); 711 712 $warning = reset($return['warnings']); 713 714 $this->assertEquals('user', $warning['item']); 715 $this->assertEquals($user2->id, $warning['itemid']); 716 $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']); 717 $this->assertEquals('You are unable to create a contact request for this user', $warning['message']); 718 } 719 720 /** 721 * Test creating a contact request with messaging disabled. 722 */ 723 public function test_create_contact_request_messaging_disabled() { 724 global $CFG; 725 726 $this->resetAfterTest(); 727 728 // Create some skeleton data just so we can call the WS. 729 $user1 = self::getDataGenerator()->create_user(); 730 $user2 = self::getDataGenerator()->create_user(); 731 732 $this->setUser($user1); 733 734 // Disable messaging. 735 $CFG->messaging = 0; 736 737 // Ensure an exception is thrown. 738 $this->expectException('moodle_exception'); 739 core_message_external::create_contact_request($user1->id, $user2->id); 740 } 741 742 /** 743 * Test creating a contact request with no permission. 744 */ 745 public function test_create_contact_request_no_permission() { 746 $this->resetAfterTest(); 747 748 // Create some skeleton data just so we can call the WS. 749 $user1 = self::getDataGenerator()->create_user(); 750 $user2 = self::getDataGenerator()->create_user(); 751 $user3 = self::getDataGenerator()->create_user(); 752 753 $this->setUser($user3); 754 755 // Ensure an exception is thrown. 756 $this->expectException('required_capability_exception'); 757 core_message_external::create_contact_request($user1->id, $user2->id); 758 } 759 760 /** 761 * Test confirming a contact request. 762 */ 763 public function test_confirm_contact_request() { 764 global $DB; 765 766 $this->resetAfterTest(); 767 768 $user1 = self::getDataGenerator()->create_user(); 769 $user2 = self::getDataGenerator()->create_user(); 770 771 $this->setUser($user1); 772 773 \core_message\api::create_contact_request($user1->id, $user2->id); 774 775 $this->setUser($user2); 776 777 $return = core_message_external::confirm_contact_request($user1->id, $user2->id); 778 $return = \external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return); 779 $this->assertEquals(array(), $return); 780 781 $this->assertEquals(0, $DB->count_records('message_contact_requests')); 782 783 $contact = $DB->get_records('message_contacts'); 784 785 $this->assertCount(1, $contact); 786 787 $contact = reset($contact); 788 789 $this->assertEquals($user1->id, $contact->userid); 790 $this->assertEquals($user2->id, $contact->contactid); 791 } 792 793 /** 794 * Test confirming a contact request with messaging disabled. 795 */ 796 public function test_confirm_contact_request_messaging_disabled() { 797 global $CFG; 798 799 $this->resetAfterTest(); 800 801 // Create some skeleton data just so we can call the WS. 802 $user1 = self::getDataGenerator()->create_user(); 803 $user2 = self::getDataGenerator()->create_user(); 804 805 $this->setUser($user1); 806 807 // Disable messaging. 808 $CFG->messaging = 0; 809 810 // Ensure an exception is thrown. 811 $this->expectException('moodle_exception'); 812 core_message_external::confirm_contact_request($user1->id, $user2->id); 813 } 814 815 /** 816 * Test confirming a contact request with no permission. 817 */ 818 public function test_confirm_contact_request_no_permission() { 819 $this->resetAfterTest(); 820 821 // Create some skeleton data just so we can call the WS. 822 $user1 = self::getDataGenerator()->create_user(); 823 $user2 = self::getDataGenerator()->create_user(); 824 $user3 = self::getDataGenerator()->create_user(); 825 826 $this->setUser($user3); 827 828 // Ensure an exception is thrown. 829 $this->expectException('required_capability_exception'); 830 core_message_external::confirm_contact_request($user1->id, $user2->id); 831 } 832 833 /** 834 * Test declining a contact request. 835 */ 836 public function test_decline_contact_request() { 837 global $DB; 838 839 $this->resetAfterTest(); 840 841 $user1 = self::getDataGenerator()->create_user(); 842 $user2 = self::getDataGenerator()->create_user(); 843 844 $this->setUser($user1); 845 846 \core_message\api::create_contact_request($user1->id, $user2->id); 847 848 $this->setUser($user2); 849 850 $return = core_message_external::decline_contact_request($user1->id, $user2->id); 851 $return = \external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return); 852 $this->assertEquals(array(), $return); 853 854 $this->assertEquals(0, $DB->count_records('message_contact_requests')); 855 $this->assertEquals(0, $DB->count_records('message_contacts')); 856 } 857 858 /** 859 * Test declining a contact request with messaging disabled. 860 */ 861 public function test_decline_contact_request_messaging_disabled() { 862 global $CFG; 863 864 $this->resetAfterTest(); 865 866 // Create some skeleton data just so we can call the WS. 867 $user1 = self::getDataGenerator()->create_user(); 868 $user2 = self::getDataGenerator()->create_user(); 869 870 $this->setUser($user1); 871 872 // Disable messaging. 873 $CFG->messaging = 0; 874 875 // Ensure an exception is thrown. 876 $this->expectException('moodle_exception'); 877 core_message_external::decline_contact_request($user1->id, $user2->id); 878 } 879 880 /** 881 * Test declining a contact request with no permission. 882 */ 883 public function test_decline_contact_request_no_permission() { 884 $this->resetAfterTest(); 885 886 // Create some skeleton data just so we can call the WS. 887 $user1 = self::getDataGenerator()->create_user(); 888 $user2 = self::getDataGenerator()->create_user(); 889 $user3 = self::getDataGenerator()->create_user(); 890 891 $this->setUser($user3); 892 893 // Ensure an exception is thrown. 894 $this->expectException('required_capability_exception'); 895 core_message_external::decline_contact_request($user1->id, $user2->id); 896 } 897 898 /** 899 * Test muting conversations. 900 */ 901 public function test_mute_conversations() { 902 global $DB; 903 904 $this->resetAfterTest(true); 905 906 $user1 = self::getDataGenerator()->create_user(); 907 $user2 = self::getDataGenerator()->create_user(); 908 909 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 910 [$user1->id, $user2->id]); 911 912 $this->setUser($user1); 913 914 // Muting a conversation. 915 $return = core_message_external::mute_conversations($user1->id, [$conversation->id]); 916 $return = \external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return); 917 $this->assertEquals(array(), $return); 918 919 // Get list of muted conversations. 920 $mca = $DB->get_record('message_conversation_actions', []); 921 922 $this->assertEquals($user1->id, $mca->userid); 923 $this->assertEquals($conversation->id, $mca->conversationid); 924 $this->assertEquals(\core_message\api::CONVERSATION_ACTION_MUTED, $mca->action); 925 926 // Muting a conversation that is already muted. 927 $return = core_message_external::mute_conversations($user1->id, [$conversation->id]); 928 $return = \external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return); 929 $this->assertEquals(array(), $return); 930 931 $this->assertEquals(1, $DB->count_records('message_conversation_actions')); 932 } 933 934 /** 935 * Test muting a conversation with messaging disabled. 936 */ 937 public function test_mute_conversations_messaging_disabled() { 938 global $CFG; 939 940 $this->resetAfterTest(); 941 942 // Create some skeleton data just so we can call the WS. 943 $user1 = self::getDataGenerator()->create_user(); 944 $user2 = self::getDataGenerator()->create_user(); 945 946 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 947 [$user1->id, $user2->id]); 948 949 $this->setUser($user1); 950 951 // Disable messaging. 952 $CFG->messaging = 0; 953 954 // Ensure an exception is thrown. 955 $this->expectException('moodle_exception'); 956 core_message_external::mute_conversations($user1->id, [$conversation->id]); 957 } 958 959 /** 960 * Test muting a conversation with no permission. 961 */ 962 public function test_mute_conversations_no_permission() { 963 $this->resetAfterTest(); 964 965 // Create some skeleton data just so we can call the WS. 966 $user1 = self::getDataGenerator()->create_user(); 967 $user2 = self::getDataGenerator()->create_user(); 968 $user3 = self::getDataGenerator()->create_user(); 969 970 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 971 [$user1->id, $user2->id]); 972 973 $this->setUser($user3); 974 975 // Ensure an exception is thrown. 976 $this->expectException('required_capability_exception'); 977 core_message_external::mute_conversations($user1->id, [$conversation->id]); 978 } 979 980 /** 981 * Test unmuting conversations. 982 */ 983 public function test_unmute_conversations() { 984 global $DB; 985 986 $this->resetAfterTest(true); 987 988 $user1 = self::getDataGenerator()->create_user(); 989 $user2 = self::getDataGenerator()->create_user(); 990 991 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 992 [$user1->id, $user2->id]); 993 994 $this->setUser($user1); 995 996 // Mute the conversation. 997 \core_message\api::mute_conversation($user1->id, $conversation->id); 998 999 // Unmuting a conversation. 1000 $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]); 1001 $return = \external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return); 1002 $this->assertEquals(array(), $return); 1003 1004 $this->assertEquals(0, $DB->count_records('message_conversation_actions')); 1005 1006 // Unmuting a conversation which is already unmuted. 1007 $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]); 1008 $return = \external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return); 1009 $this->assertEquals(array(), $return); 1010 1011 $this->assertEquals(0, $DB->count_records('message_conversation_actions')); 1012 } 1013 1014 /** 1015 * Test unmuting a conversation with messaging disabled. 1016 */ 1017 public function test_unmute_conversation_messaging_disabled() { 1018 global $CFG; 1019 1020 $this->resetAfterTest(); 1021 1022 // Create some skeleton data just so we can call the WS. 1023 $user1 = self::getDataGenerator()->create_user(); 1024 $user2 = self::getDataGenerator()->create_user(); 1025 1026 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 1027 [$user1->id, $user2->id]); 1028 1029 $this->setUser($user1); 1030 1031 // Disable messaging. 1032 $CFG->messaging = 0; 1033 1034 // Ensure an exception is thrown. 1035 $this->expectException('moodle_exception'); 1036 core_message_external::unmute_conversations($user1->id, [$user2->id]); 1037 } 1038 1039 /** 1040 * Test unmuting a conversation with no permission. 1041 */ 1042 public function test_unmute_conversation_no_permission() { 1043 $this->resetAfterTest(); 1044 1045 // Create some skeleton data just so we can call the WS. 1046 $user1 = self::getDataGenerator()->create_user(); 1047 $user2 = self::getDataGenerator()->create_user(); 1048 $user3 = self::getDataGenerator()->create_user(); 1049 1050 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 1051 [$user1->id, $user2->id]); 1052 1053 $this->setUser($user3); 1054 1055 // Ensure an exception is thrown. 1056 $this->expectException('required_capability_exception'); 1057 core_message_external::unmute_conversations($user1->id, [$conversation->id]); 1058 } 1059 1060 /** 1061 * Test blocking a user. 1062 */ 1063 public function test_block_user() { 1064 global $DB; 1065 1066 $this->resetAfterTest(true); 1067 1068 $user1 = self::getDataGenerator()->create_user(); 1069 $user2 = self::getDataGenerator()->create_user(); 1070 1071 $this->setUser($user1); 1072 1073 // Blocking a user. 1074 $return = core_message_external::block_user($user1->id, $user2->id); 1075 $return = \external_api::clean_returnvalue(core_message_external::block_user_returns(), $return); 1076 $this->assertEquals(array(), $return); 1077 1078 // Get list of blocked users. 1079 $record = $DB->get_record('message_users_blocked', []); 1080 1081 $this->assertEquals($user1->id, $record->userid); 1082 $this->assertEquals($user2->id, $record->blockeduserid); 1083 1084 // Blocking a user who is already blocked. 1085 $return = core_message_external::block_user($user1->id, $user2->id); 1086 $return = \external_api::clean_returnvalue(core_message_external::block_user_returns(), $return); 1087 $this->assertEquals(array(), $return); 1088 1089 $this->assertEquals(1, $DB->count_records('message_users_blocked')); 1090 } 1091 1092 /** 1093 * Test blocking a user. 1094 */ 1095 public function test_block_user_when_ineffective() { 1096 global $DB; 1097 1098 $this->resetAfterTest(true); 1099 1100 $user1 = self::getDataGenerator()->create_user(); 1101 $user2 = self::getDataGenerator()->create_user(); 1102 1103 $this->setUser($user1); 1104 1105 $authenticateduser = $DB->get_record('role', array('shortname' => 'user')); 1106 assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, \context_system::instance(), true); 1107 1108 // Blocking a user. 1109 $return = core_message_external::block_user($user1->id, $user2->id); 1110 $return = \external_api::clean_returnvalue(core_message_external::block_user_returns(), $return); 1111 $this->assertEquals(array(), $return); 1112 1113 $this->assertEquals(0, $DB->count_records('message_users_blocked')); 1114 } 1115 1116 /** 1117 * Test blocking a user with messaging disabled. 1118 */ 1119 public function test_block_user_messaging_disabled() { 1120 global $CFG; 1121 1122 $this->resetAfterTest(); 1123 1124 // Create some skeleton data just so we can call the WS. 1125 $user1 = self::getDataGenerator()->create_user(); 1126 $user2 = self::getDataGenerator()->create_user(); 1127 1128 $this->setUser($user1); 1129 1130 // Disable messaging. 1131 $CFG->messaging = 0; 1132 1133 // Ensure an exception is thrown. 1134 $this->expectException('moodle_exception'); 1135 core_message_external::block_user($user1->id, $user2->id); 1136 } 1137 1138 /** 1139 * Test blocking a user with no permission. 1140 */ 1141 public function test_block_user_no_permission() { 1142 $this->resetAfterTest(); 1143 1144 // Create some skeleton data just so we can call the WS. 1145 $user1 = self::getDataGenerator()->create_user(); 1146 $user2 = self::getDataGenerator()->create_user(); 1147 $user3 = self::getDataGenerator()->create_user(); 1148 1149 $this->setUser($user3); 1150 1151 // Ensure an exception is thrown. 1152 $this->expectException('required_capability_exception'); 1153 core_message_external::block_user($user1->id, $user2->id); 1154 } 1155 1156 /** 1157 * Test unblocking a user. 1158 */ 1159 public function test_unblock_user() { 1160 global $DB; 1161 1162 $this->resetAfterTest(true); 1163 1164 $user1 = self::getDataGenerator()->create_user(); 1165 $user2 = self::getDataGenerator()->create_user(); 1166 1167 $this->setUser($user1); 1168 1169 // Block the user. 1170 \core_message\api::block_user($user1->id, $user2->id); 1171 1172 // Unblocking a user. 1173 $return = core_message_external::unblock_user($user1->id, $user2->id); 1174 $return = \external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return); 1175 $this->assertEquals(array(), $return); 1176 1177 $this->assertEquals(0, $DB->count_records('message_users_blocked')); 1178 1179 // Unblocking a user who is already unblocked. 1180 $return = core_message_external::unblock_user($user1->id, $user2->id); 1181 $return = \external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return); 1182 $this->assertEquals(array(), $return); 1183 1184 $this->assertEquals(0, $DB->count_records('message_users_blocked')); 1185 } 1186 1187 /** 1188 * Test unblocking a user with messaging disabled. 1189 */ 1190 public function test_unblock_user_messaging_disabled() { 1191 global $CFG; 1192 1193 $this->resetAfterTest(); 1194 1195 // Create some skeleton data just so we can call the WS. 1196 $user1 = self::getDataGenerator()->create_user(); 1197 $user2 = self::getDataGenerator()->create_user(); 1198 1199 $this->setUser($user1); 1200 1201 // Disable messaging. 1202 $CFG->messaging = 0; 1203 1204 // Ensure an exception is thrown. 1205 $this->expectException('moodle_exception'); 1206 core_message_external::unblock_user($user1->id, $user2->id); 1207 } 1208 1209 /** 1210 * Test unblocking a user with no permission. 1211 */ 1212 public function test_unblock_user_no_permission() { 1213 $this->resetAfterTest(); 1214 1215 // Create some skeleton data just so we can call the WS. 1216 $user1 = self::getDataGenerator()->create_user(); 1217 $user2 = self::getDataGenerator()->create_user(); 1218 $user3 = self::getDataGenerator()->create_user(); 1219 1220 $this->setUser($user3); 1221 1222 // Ensure an exception is thrown. 1223 $this->expectException('required_capability_exception'); 1224 core_message_external::unblock_user($user1->id, $user2->id); 1225 } 1226 1227 /** 1228 * Test search_contacts. 1229 */ 1230 public function test_search_contacts() { 1231 global $DB; 1232 $this->resetAfterTest(true); 1233 1234 $course1 = $this->getDataGenerator()->create_course(); 1235 $course2 = $this->getDataGenerator()->create_course(); 1236 1237 $user1 = new \stdClass(); 1238 $user1->firstname = 'X'; 1239 $user1->lastname = 'X'; 1240 $user1 = $this->getDataGenerator()->create_user($user1); 1241 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 1242 $this->getDataGenerator()->enrol_user($user1->id, $course2->id); 1243 1244 $user2 = new \stdClass(); 1245 $user2->firstname = 'Eric'; 1246 $user2->lastname = 'Cartman'; 1247 $user2 = self::getDataGenerator()->create_user($user2); 1248 $user3 = new \stdClass(); 1249 $user3->firstname = 'Stan'; 1250 $user3->lastname = 'Marsh'; 1251 $user3 = self::getDataGenerator()->create_user($user3); 1252 self::getDataGenerator()->enrol_user($user3->id, $course1->id); 1253 $user4 = new \stdClass(); 1254 $user4->firstname = 'Kyle'; 1255 $user4->lastname = 'Broflovski'; 1256 $user4 = self::getDataGenerator()->create_user($user4); 1257 $user5 = new \stdClass(); 1258 $user5->firstname = 'Kenny'; 1259 $user5->lastname = 'McCormick'; 1260 $user5 = self::getDataGenerator()->create_user($user5); 1261 self::getDataGenerator()->enrol_user($user5->id, $course2->id); 1262 1263 $this->setUser($user1); 1264 1265 $results = core_message_external::search_contacts('r'); 1266 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1267 $this->assertCount(5, $results); // Users 2 through 5 + admin 1268 1269 $results = core_message_external::search_contacts('r', true); 1270 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1271 $this->assertCount(2, $results); 1272 1273 $results = core_message_external::search_contacts('Kyle', false); 1274 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1275 $this->assertCount(1, $results); 1276 $result = reset($results); 1277 $this->assertEquals($user4->id, $result['id']); 1278 1279 $results = core_message_external::search_contacts('y', false); 1280 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1281 $this->assertCount(2, $results); 1282 1283 $results = core_message_external::search_contacts('y', true); 1284 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1285 $this->assertCount(1, $results); 1286 $result = reset($results); 1287 $this->assertEquals($user5->id, $result['id']); 1288 1289 // Empty query, will throw an exception. 1290 $this->expectException(\moodle_exception::class); 1291 $results = core_message_external::search_contacts(''); 1292 } 1293 1294 /** 1295 * Test get_messages. 1296 */ 1297 public function test_get_messages() { 1298 global $CFG, $DB; 1299 $this->resetAfterTest(true); 1300 1301 $this->preventResetByRollback(); 1302 // This mark the messages as read!. 1303 $sink = $this->redirectMessages(); 1304 1305 $user1 = self::getDataGenerator()->create_user(); 1306 $user2 = self::getDataGenerator()->create_user(); 1307 $user3 = self::getDataGenerator()->create_user(); 1308 1309 $course = self::getDataGenerator()->create_course(); 1310 1311 // Send a message from one user to another. 1312 message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); 1313 message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE); 1314 message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); 1315 message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); 1316 message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE); 1317 1318 $this->setUser($user1); 1319 // Get read conversations from user1 to user2. 1320 $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0); 1321 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1322 $this->assertCount(1, $messages['messages']); 1323 1324 // Delete the message. 1325 $message = array_shift($messages['messages']); 1326 \core_message\api::delete_message($user1->id, $message['id']); 1327 1328 $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0); 1329 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1330 $this->assertCount(0, $messages['messages']); 1331 1332 // Get unread conversations from user1 to user2. 1333 $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0); 1334 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1335 $this->assertCount(0, $messages['messages']); 1336 1337 // Get read messages send from user1. 1338 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); 1339 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1340 $this->assertCount(1, $messages['messages']); 1341 1342 $this->setUser($user2); 1343 // Get read conversations from any user to user2. 1344 $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0); 1345 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1346 $this->assertCount(2, $messages['messages']); 1347 1348 // Conversations from user3 to user2. 1349 $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0); 1350 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1351 $this->assertCount(1, $messages['messages']); 1352 1353 // Delete the message. 1354 $message = array_shift($messages['messages']); 1355 \core_message\api::delete_message($user2->id, $message['id']); 1356 1357 $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0); 1358 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1359 $this->assertCount(0, $messages['messages']); 1360 1361 $this->setUser($user3); 1362 // Get read notifications received by user3. 1363 $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0); 1364 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1365 $this->assertCount(0, $messages['messages']); 1366 1367 // Now, create some notifications... 1368 // We are creating fake notifications but based on real ones. 1369 1370 // This one comes from a disabled plugin's provider and therefore is not sent. 1371 $eventdata = new \core\message\message(); 1372 $eventdata->courseid = $course->id; 1373 $eventdata->notification = 1; 1374 $eventdata->modulename = 'moodle'; 1375 $eventdata->component = 'enrol_paypal'; 1376 $eventdata->name = 'paypal_enrolment'; 1377 $eventdata->userfrom = get_admin(); 1378 $eventdata->userto = $user1; 1379 $eventdata->subject = "Moodle: PayPal payment"; 1380 $eventdata->fullmessage = "Your PayPal payment is pending."; 1381 $eventdata->fullmessageformat = FORMAT_PLAIN; 1382 $eventdata->fullmessagehtml = ''; 1383 $eventdata->smallmessage = ''; 1384 message_send($eventdata); 1385 $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '. 1386 'that is inactive or not allowed for the user id='.$user1->id); 1387 1388 // This one omits notification = 1. 1389 $message = new \core\message\message(); 1390 $message->courseid = $course->id; 1391 $message->component = 'enrol_manual'; 1392 $message->name = 'expiry_notification'; 1393 $message->userfrom = $user2; 1394 $message->userto = $user1; 1395 $message->subject = 'Test: This is not a notification but otherwise is valid'; 1396 $message->fullmessage = 'Test: Full message'; 1397 $message->fullmessageformat = FORMAT_MARKDOWN; 1398 $message->fullmessagehtml = markdown_to_html($message->fullmessage); 1399 $message->smallmessage = $message->subject; 1400 $message->contexturlname = $course->fullname; 1401 $message->contexturl = (string)new \moodle_url('/course/view.php', array('id' => $course->id)); 1402 message_send($message); 1403 1404 $message = new \core\message\message(); 1405 $message->courseid = $course->id; 1406 $message->notification = 1; 1407 $message->component = 'enrol_manual'; 1408 $message->name = 'expiry_notification'; 1409 $message->userfrom = $user2; 1410 $message->userto = $user1; 1411 $message->subject = 'Enrolment expired'; 1412 $message->fullmessage = 'Enrolment expired blah blah blah'; 1413 $message->fullmessageformat = FORMAT_MARKDOWN; 1414 $message->fullmessagehtml = markdown_to_html($message->fullmessage); 1415 $message->smallmessage = $message->subject; 1416 $message->contexturlname = $course->fullname; 1417 $message->contexturl = (string)new \moodle_url('/course/view.php', array('id' => $course->id)); 1418 message_send($message); 1419 1420 $userfrom = \core_user::get_noreply_user(); 1421 $userfrom->maildisplay = true; 1422 $eventdata = new \core\message\message(); 1423 $eventdata->courseid = $course->id; 1424 $eventdata->component = 'moodle'; 1425 $eventdata->name = 'badgecreatornotice'; 1426 $eventdata->userfrom = $userfrom; 1427 $eventdata->userto = $user1; 1428 $eventdata->notification = 1; 1429 $eventdata->subject = 'New badge'; 1430 $eventdata->fullmessage = format_text_email($eventdata->subject, FORMAT_HTML); 1431 $eventdata->fullmessageformat = FORMAT_PLAIN; 1432 $eventdata->fullmessagehtml = $eventdata->subject; 1433 $eventdata->smallmessage = $eventdata->subject; 1434 message_send($eventdata); 1435 1436 $eventdata = new \core\message\message(); 1437 $eventdata->courseid = $course->id; 1438 $eventdata->name = 'submission'; 1439 $eventdata->component = 'mod_feedback'; 1440 $eventdata->userfrom = $user1; 1441 $eventdata->userto = $user2; 1442 $eventdata->subject = 'Feedback submitted'; 1443 $eventdata->fullmessage = 'Feedback submitted from an user'; 1444 $eventdata->fullmessageformat = FORMAT_PLAIN; 1445 $eventdata->fullmessagehtml = '<strong>Feedback submitted</strong>'; 1446 $eventdata->smallmessage = ''; 1447 $eventdata->customdata = ['datakey' => 'data']; 1448 message_send($eventdata); 1449 1450 $this->setUser($user1); 1451 // Get read notifications from any user to user1. 1452 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0); 1453 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1454 $this->assertCount(3, $messages['messages']); 1455 1456 // Get one read notifications from any user to user1. 1457 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1); 1458 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1459 $this->assertCount(1, $messages['messages']); 1460 1461 // Get unread notifications from any user to user1. 1462 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0); 1463 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1464 $this->assertCount(0, $messages['messages']); 1465 1466 // Get read both type of messages from any user to user1. 1467 $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0); 1468 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1469 $this->assertCount(4, $messages['messages']); 1470 1471 // Get read notifications from no-reply-user to user1. 1472 $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0); 1473 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1474 $this->assertCount(1, $messages['messages']); 1475 1476 // Get notifications send by user1 to any user. 1477 $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0); 1478 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1479 $this->assertCount(1, $messages['messages']); 1480 // Check we receive custom data as a unserialisable json. 1481 $this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata'])); 1482 $this->assertEquals('mod_feedback', $messages['messages'][0]['component']); 1483 $this->assertEquals('submission', $messages['messages'][0]['eventtype']); 1484 1485 // Test warnings. 1486 $CFG->messaging = 0; 1487 1488 $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0); 1489 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1490 $this->assertCount(1, $messages['warnings']); 1491 1492 // Test exceptions. 1493 1494 // Messaging disabled. 1495 try { 1496 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); 1497 $this->fail('Exception expected due messaging disabled.'); 1498 } catch (\moodle_exception $e) { 1499 $this->assertEquals('disabled', $e->errorcode); 1500 } 1501 1502 $CFG->messaging = 1; 1503 1504 // Invalid users. 1505 try { 1506 $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0); 1507 $this->fail('Exception expected due invalid users.'); 1508 } catch (\moodle_exception $e) { 1509 $this->assertEquals('accessdenied', $e->errorcode); 1510 } 1511 1512 // Invalid user ids. 1513 try { 1514 $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0); 1515 $this->fail('Exception expected due invalid users.'); 1516 } catch (\moodle_exception $e) { 1517 $this->assertEquals('invaliduser', $e->errorcode); 1518 } 1519 1520 // Invalid users (permissions). 1521 $this->setUser($user2); 1522 try { 1523 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); 1524 $this->fail('Exception expected due invalid user.'); 1525 } catch (\moodle_exception $e) { 1526 $this->assertEquals('accessdenied', $e->errorcode); 1527 } 1528 1529 } 1530 1531 /** 1532 * Test get_messages where we want all messages from a user, sent to any user. 1533 */ 1534 public function test_get_messages_useridto_all() { 1535 $this->resetAfterTest(true); 1536 1537 $user1 = self::getDataGenerator()->create_user(); 1538 $user2 = self::getDataGenerator()->create_user(); 1539 $user3 = self::getDataGenerator()->create_user(); 1540 1541 $this->setUser($user1); 1542 1543 // Send a message from user 1 to two other users. 1544 $this->send_message($user1, $user2, 'some random text 1', 0, 1); 1545 $this->send_message($user1, $user3, 'some random text 2', 0, 2); 1546 1547 // Get messages sent from user 1. 1548 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', false, false, 0, 0); 1549 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1550 1551 // Confirm the data is correct. 1552 $messages = $messages['messages']; 1553 $this->assertCount(2, $messages); 1554 1555 $message1 = array_shift($messages); 1556 $message2 = array_shift($messages); 1557 1558 $this->assertEquals($user1->id, $message1['useridfrom']); 1559 $this->assertEquals($user2->id, $message1['useridto']); 1560 1561 $this->assertEquals($user1->id, $message2['useridfrom']); 1562 $this->assertEquals($user3->id, $message2['useridto']); 1563 } 1564 1565 /** 1566 * Test get_messages where we want all messages to a user, sent by any user. 1567 */ 1568 public function test_get_messages_useridfrom_all() { 1569 $this->resetAfterTest(); 1570 1571 $user1 = self::getDataGenerator()->create_user(); 1572 $user2 = self::getDataGenerator()->create_user(); 1573 $user3 = self::getDataGenerator()->create_user(); 1574 1575 $this->setUser($user1); 1576 1577 // Send a message to user 1 from two other users. 1578 $this->send_message($user2, $user1, 'some random text 1', 0, 1); 1579 $this->send_message($user3, $user1, 'some random text 2', 0, 2); 1580 1581 // Get messages sent to user 1. 1582 $messages = core_message_external::get_messages($user1->id, 0, 'conversations', false, false, 0, 0); 1583 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1584 1585 // Confirm the data is correct. 1586 $messages = $messages['messages']; 1587 $this->assertCount(2, $messages); 1588 1589 $message1 = array_shift($messages); 1590 $message2 = array_shift($messages); 1591 1592 $this->assertEquals($user2->id, $message1['useridfrom']); 1593 $this->assertEquals($user1->id, $message1['useridto']); 1594 1595 $this->assertEquals($user3->id, $message2['useridfrom']); 1596 $this->assertEquals($user1->id, $message2['useridto']); 1597 } 1598 1599 /** 1600 * Test get_blocked_users. 1601 */ 1602 public function test_get_blocked_users() { 1603 $this->resetAfterTest(true); 1604 1605 $user1 = self::getDataGenerator()->create_user(); 1606 $userstranger = self::getDataGenerator()->create_user(); 1607 $useroffline1 = self::getDataGenerator()->create_user(); 1608 $useroffline2 = self::getDataGenerator()->create_user(); 1609 $userblocked = self::getDataGenerator()->create_user(); 1610 1611 // Login as user1. 1612 $this->setUser($user1); 1613 1614 \core_message\api::add_contact($user1->id, $useroffline1->id); 1615 \core_message\api::add_contact($user1->id, $useroffline2->id); 1616 1617 // The userstranger sends a couple of messages to user1. 1618 $this->send_message($userstranger, $user1, 'Hello there!'); 1619 $this->send_message($userstranger, $user1, 'How you goin?'); 1620 1621 // The userblocked sends a message to user1. 1622 // Note that this user is not blocked at this point. 1623 $this->send_message($userblocked, $user1, 'Here, have some spam.'); 1624 1625 // Retrieve the list of blocked users. 1626 $this->setUser($user1); 1627 $blockedusers = core_message_external::get_blocked_users($user1->id); 1628 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1629 $this->assertCount(0, $blockedusers['users']); 1630 1631 // Block the $userblocked and retrieve again the list. 1632 \core_message\api::block_user($user1->id, $userblocked->id); 1633 $blockedusers = core_message_external::get_blocked_users($user1->id); 1634 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1635 $this->assertCount(1, $blockedusers['users']); 1636 1637 // Remove the $userblocked and check that the list now is empty. 1638 delete_user($userblocked); 1639 $blockedusers = core_message_external::get_blocked_users($user1->id); 1640 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1641 $this->assertCount(0, $blockedusers['users']); 1642 } 1643 1644 /** 1645 * Test mark_message_read. 1646 */ 1647 public function test_mark_message_read() { 1648 $this->resetAfterTest(true); 1649 1650 $user1 = self::getDataGenerator()->create_user(); 1651 $user2 = self::getDataGenerator()->create_user(); 1652 $user3 = self::getDataGenerator()->create_user(); 1653 1654 // Login as user1. 1655 $this->setUser($user1); 1656 \core_message\api::add_contact($user1->id, $user2->id); 1657 \core_message\api::add_contact($user1->id, $user3->id); 1658 1659 // The user2 sends a couple of messages to user1. 1660 $this->send_message($user2, $user1, 'Hello there!'); 1661 $this->send_message($user2, $user1, 'How you goin?'); 1662 $this->send_message($user3, $user1, 'How you goin?'); 1663 $this->send_message($user3, $user2, 'How you goin?'); 1664 1665 // Retrieve all messages sent by user2 (they are currently unread). 1666 $lastmessages = message_get_messages($user1->id, $user2->id, 0, false); 1667 1668 $messageids = array(); 1669 foreach ($lastmessages as $m) { 1670 $messageid = core_message_external::mark_message_read($m->id, time()); 1671 $messageids[] = \external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid); 1672 } 1673 1674 // Retrieve all messages sent (they are currently read). 1675 $lastmessages = message_get_messages($user1->id, $user2->id, 0, true); 1676 $this->assertCount(2, $lastmessages); 1677 $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages); 1678 $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages); 1679 1680 // Retrieve all messages sent by any user (that are currently unread). 1681 $lastmessages = message_get_messages($user1->id, 0, 0, false); 1682 $this->assertCount(1, $lastmessages); 1683 1684 // Invalid message ids. 1685 try { 1686 $messageid = core_message_external::mark_message_read(1337, time()); 1687 $this->fail('Exception expected due invalid messageid.'); 1688 } catch (\dml_missing_record_exception $e) { 1689 $this->assertEquals('invalidrecordunknown', $e->errorcode); 1690 } 1691 1692 // A message to a different user. 1693 $lastmessages = message_get_messages($user2->id, $user3->id, 0, false); 1694 $messageid = array_pop($lastmessages)->id; 1695 try { 1696 $messageid = core_message_external::mark_message_read($messageid, time()); 1697 $this->fail('Exception expected due invalid messageid.'); 1698 } catch (\invalid_parameter_exception $e) { 1699 $this->assertEquals('invalidparameter', $e->errorcode); 1700 } 1701 } 1702 1703 /** 1704 * Test mark_notification_read. 1705 */ 1706 public function test_mark_notification_read() { 1707 $this->resetAfterTest(true); 1708 1709 $user1 = self::getDataGenerator()->create_user(); 1710 $user2 = self::getDataGenerator()->create_user(); 1711 $user3 = self::getDataGenerator()->create_user(); 1712 1713 // Login as user1. 1714 $this->setUser($user1); 1715 \core_message\api::add_contact($user1->id, $user2->id); 1716 \core_message\api::add_contact($user1->id, $user3->id); 1717 1718 // The user2 sends a couple of notifications to user1. 1719 $this->send_message($user2, $user1, 'Hello there!', 1); 1720 $this->send_message($user2, $user1, 'How you goin?', 1); 1721 $this->send_message($user3, $user1, 'How you goin?', 1); 1722 $this->send_message($user3, $user2, 'How you goin?', 1); 1723 1724 // Retrieve all notifications sent by user2 (they are currently unread). 1725 $lastnotifications = message_get_messages($user1->id, $user2->id, 1, false); 1726 1727 $notificationids = array(); 1728 foreach ($lastnotifications as $n) { 1729 $notificationid = core_message_external::mark_notification_read($n->id, time()); 1730 $notificationids[] = \external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(), 1731 $notificationid); 1732 } 1733 1734 // Retrieve all notifications sent (they are currently read). 1735 $lastnotifications = message_get_messages($user1->id, $user2->id, 1, true); 1736 $this->assertCount(2, $lastnotifications); 1737 $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications); 1738 $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications); 1739 1740 // Retrieve all notifications sent by any user (that are currently unread). 1741 $lastnotifications = message_get_messages($user1->id, 0, 1, false); 1742 $this->assertCount(1, $lastnotifications); 1743 1744 // Invalid notification ids. 1745 try { 1746 $notificationid = core_message_external::mark_notification_read(1337, time()); 1747 $this->fail('Exception expected due invalid notificationid.'); 1748 } catch (\dml_missing_record_exception $e) { 1749 $this->assertEquals('invalidrecord', $e->errorcode); 1750 } 1751 1752 // A notification to a different user. 1753 $lastnotifications = message_get_messages($user2->id, $user3->id, 1, false); 1754 $notificationid = array_pop($lastnotifications)->id; 1755 try { 1756 $notificationid = core_message_external::mark_notification_read($notificationid, time()); 1757 $this->fail('Exception expected due invalid notificationid.'); 1758 } catch (\invalid_parameter_exception $e) { 1759 $this->assertEquals('invalidparameter', $e->errorcode); 1760 } 1761 } 1762 1763 /** 1764 * Test delete_message. 1765 */ 1766 public function test_delete_message() { 1767 global $DB; 1768 $this->resetAfterTest(true); 1769 1770 $user1 = self::getDataGenerator()->create_user(); 1771 $user2 = self::getDataGenerator()->create_user(); 1772 $user3 = self::getDataGenerator()->create_user(); 1773 $user4 = self::getDataGenerator()->create_user(); 1774 1775 // Login as user1. 1776 $this->setUser($user1); 1777 \core_message\api::add_contact($user1->id, $user2->id); 1778 \core_message\api::add_contact($user1->id, $user3->id); 1779 1780 // User user1 does not interchange messages with user3. 1781 $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); 1782 $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); 1783 $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); 1784 $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE); 1785 1786 // Retrieve all messages sent by user2 (they are currently unread). 1787 $lastmessages = message_get_messages($user1->id, $user2->id, 0, false); 1788 1789 // Delete a message not read, as a user from. 1790 $result = core_message_external::delete_message($m1to2, $user1->id, false); 1791 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1792 $this->assertTrue($result['status']); 1793 $this->assertCount(0, $result['warnings']); 1794 $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id)); 1795 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action); 1796 1797 // Try to delete the same message again. 1798 $result = core_message_external::delete_message($m1to2, $user1->id, false); 1799 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1800 $this->assertFalse($result['status']); 1801 1802 // Try to delete a message that does not belong to me. 1803 try { 1804 $messageid = core_message_external::delete_message($m2to3, $user3->id, false); 1805 $this->fail('Exception expected due invalid messageid.'); 1806 } catch (\moodle_exception $e) { 1807 $this->assertEquals('You do not have permission to delete this message', $e->errorcode); 1808 } 1809 1810 $this->setUser($user3); 1811 // Delete a message not read, as a user to. 1812 $result = core_message_external::delete_message($m2to3, $user3->id, false); 1813 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1814 $this->assertTrue($result['status']); 1815 $this->assertCount(0, $result['warnings']); 1816 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id, 1817 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1818 1819 // Delete a message read. 1820 $message = $DB->get_record('messages', ['id' => $m3to2]); 1821 \core_message\api::mark_message_as_read($user3->id, $message, time()); 1822 $result = core_message_external::delete_message($m3to2, $user3->id); 1823 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1824 $this->assertTrue($result['status']); 1825 $this->assertCount(0, $result['warnings']); 1826 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id, 1827 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1828 1829 // Invalid message ids. 1830 try { 1831 $result = core_message_external::delete_message(-1, $user1->id); 1832 $this->fail('Exception expected due invalid messageid.'); 1833 } catch (\dml_missing_record_exception $e) { 1834 $this->assertEquals('invalidrecord', $e->errorcode); 1835 } 1836 1837 // Invalid user. 1838 try { 1839 $result = core_message_external::delete_message($m1to2, -1, false); 1840 $this->fail('Exception expected due invalid user.'); 1841 } catch (\moodle_exception $e) { 1842 $this->assertEquals('invaliduser', $e->errorcode); 1843 } 1844 1845 // Not active user. 1846 delete_user($user2); 1847 try { 1848 $result = core_message_external::delete_message($m1to2, $user2->id, false); 1849 $this->fail('Exception expected due invalid user.'); 1850 } catch (\moodle_exception $e) { 1851 $this->assertEquals('userdeleted', $e->errorcode); 1852 } 1853 1854 // Now, as an admin, try to delete any message. 1855 $this->setAdminUser(); 1856 $result = core_message_external::delete_message($m3to4, $user4->id, false); 1857 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1858 $this->assertTrue($result['status']); 1859 $this->assertCount(0, $result['warnings']); 1860 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id, 1861 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1862 1863 } 1864 1865 public function test_mark_all_notifications_as_read_invalid_user_exception() { 1866 $this->resetAfterTest(true); 1867 1868 $this->expectException('moodle_exception'); 1869 core_message_external::mark_all_notifications_as_read(-2132131, 0); 1870 } 1871 1872 public function test_mark_all_notifications_as_read_access_denied_exception() { 1873 $this->resetAfterTest(true); 1874 1875 $sender = $this->getDataGenerator()->create_user(); 1876 $user = $this->getDataGenerator()->create_user(); 1877 1878 $this->setUser($user); 1879 $this->expectException('moodle_exception'); 1880 core_message_external::mark_all_notifications_as_read($sender->id, 0); 1881 } 1882 1883 public function test_mark_all_notifications_as_read_missing_from_user_exception() { 1884 $this->resetAfterTest(true); 1885 1886 $sender = $this->getDataGenerator()->create_user(); 1887 1888 $this->setUser($sender); 1889 $this->expectException('moodle_exception'); 1890 core_message_external::mark_all_notifications_as_read($sender->id, 99999); 1891 } 1892 1893 public function test_mark_all_notifications_as_read() { 1894 global $DB; 1895 1896 $this->resetAfterTest(true); 1897 1898 $sender1 = $this->getDataGenerator()->create_user(); 1899 $sender2 = $this->getDataGenerator()->create_user(); 1900 $sender3 = $this->getDataGenerator()->create_user(); 1901 $recipient = $this->getDataGenerator()->create_user(); 1902 1903 $this->setUser($recipient); 1904 1905 $this->send_message($sender1, $recipient, 'Notification', 1); 1906 $this->send_message($sender1, $recipient, 'Notification', 1); 1907 $this->send_message($sender2, $recipient, 'Notification', 1); 1908 $this->send_message($sender2, $recipient, 'Notification', 1); 1909 $this->send_message($sender3, $recipient, 'Notification', 1); 1910 $this->send_message($sender3, $recipient, 'Notification', 1); 1911 1912 core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id); 1913 $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]); 1914 $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]); 1915 1916 $this->assertCount(2, $readnotifications); 1917 $this->assertCount(4, $unreadnotifications); 1918 1919 core_message_external::mark_all_notifications_as_read($recipient->id, 0); 1920 $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]); 1921 $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]); 1922 1923 $this->assertCount(6, $readnotifications); 1924 $this->assertCount(0, $unreadnotifications); 1925 } 1926 1927 public function test_mark_all_notifications_as_read_time_created_to() { 1928 global $DB; 1929 1930 $this->resetAfterTest(true); 1931 1932 $sender1 = $this->getDataGenerator()->create_user(); 1933 $sender2 = $this->getDataGenerator()->create_user(); 1934 1935 $recipient = $this->getDataGenerator()->create_user(); 1936 $this->setUser($recipient); 1937 1938 // Record messages as sent on one second intervals. 1939 $time = time(); 1940 1941 $this->send_message($sender1, $recipient, 'Message 1', 1, $time); 1942 $this->send_message($sender2, $recipient, 'Message 2', 1, $time + 1); 1943 $this->send_message($sender1, $recipient, 'Message 3', 1, $time + 2); 1944 $this->send_message($sender2, $recipient, 'Message 4', 1, $time + 3); 1945 1946 // Mark notifications sent from sender1 up until the second message; should only mark the first notification as read. 1947 core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id, $time + 1); 1948 1949 $params = [$recipient->id]; 1950 1951 $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1952 $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1953 1954 // Mark all notifications as read from any sender up to the time the third message was sent. 1955 core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 2); 1956 1957 $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1958 $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1959 1960 // Mark all notifications as read from any sender with a time after all messages were sent. 1961 core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 10); 1962 1963 $this->assertEquals(4, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1964 $this->assertEquals(0, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1965 } 1966 1967 /** 1968 * Test get_user_notification_preferences 1969 */ 1970 public function test_get_user_notification_preferences() { 1971 $this->resetAfterTest(true); 1972 1973 $user = self::getDataGenerator()->create_user(); 1974 $this->setUser($user); 1975 1976 // Set a couple of preferences to test. 1977 set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user); 1978 set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user); 1979 1980 $prefs = core_message_external::get_user_notification_preferences(); 1981 $prefs = \external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs); 1982 // Check processors. 1983 $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors'])); 1984 $this->assertEquals($user->id, $prefs['preferences']['userid']); 1985 1986 // Check components. 1987 $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components'])); 1988 1989 // Check some preferences that we previously set. 1990 $found = 0; 1991 foreach ($prefs['preferences']['components'] as $component) { 1992 foreach ($component['notifications'] as $prefdata) { 1993 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') { 1994 continue; 1995 } 1996 foreach ($prefdata['processors'] as $processor) { 1997 if ($processor['name'] == 'popup') { 1998 $this->assertTrue($processor['loggedin']['checked']); 1999 $found++; 2000 } else if ($processor['name'] == 'email') { 2001 $this->assertTrue($processor['loggedoff']['checked']); 2002 $found++; 2003 } 2004 } 2005 } 2006 } 2007 $this->assertEquals(2, $found); 2008 } 2009 2010 /** 2011 * Test get_user_notification_preferences permissions 2012 */ 2013 public function test_get_user_notification_preferences_permissions() { 2014 $this->resetAfterTest(true); 2015 2016 $user = self::getDataGenerator()->create_user(); 2017 $otheruser = self::getDataGenerator()->create_user(); 2018 $this->setUser($user); 2019 2020 $this->expectException('moodle_exception'); 2021 $prefs = core_message_external::get_user_notification_preferences($otheruser->id); 2022 } 2023 2024 /** 2025 * Tests searching for users when site-wide messaging is disabled. 2026 * 2027 * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view. 2028 * If checks this by placing some users in the same course, where default caps would permit a user to view another user's 2029 * profile. 2030 */ 2031 public function test_message_search_users_messagingallusers_disabled() { 2032 global $DB; 2033 $this->resetAfterTest(); 2034 2035 // Create some users. 2036 $users = []; 2037 foreach (range(1, 8) as $i) { 2038 $user = new \stdClass(); 2039 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2040 $user->lastname = $i; 2041 $user = $this->getDataGenerator()->create_user($user); 2042 $users[$i] = $user; 2043 } 2044 2045 // Enrol a few users in the same course, but leave them as non-contacts. 2046 $course1 = $this->getDataGenerator()->create_course(); 2047 $course2 = $this->getDataGenerator()->create_course(); 2048 2049 $this->setAdminUser(); 2050 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2051 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2052 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2053 2054 // Add some other users as contacts. 2055 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2056 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2057 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2058 2059 // Enrol a user as a teacher in the course, and make the teacher role a course contact role. 2060 $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher'); 2061 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 2062 set_config('coursecontact', $teacherrole->id); 2063 2064 // Create individual conversations between some users, one contact and one non-contact. 2065 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2066 [$users[1]->id, $users[2]->id]); 2067 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2068 [$users[6]->id, $users[1]->id]); 2069 2070 // Create a group conversation between 4 users, including a contact and a non-contact. 2071 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2072 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat'); 2073 2074 // Set as the user performing the search. 2075 $this->setUser($users[1]); 2076 2077 // Perform a search with $CFG->messagingallusers disabled. 2078 set_config('messagingallusers', 0); 2079 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2080 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2081 2082 // Confirm that we returns contacts and non-contacts. 2083 $this->assertArrayHasKey('contacts', $result); 2084 $this->assertArrayHasKey('noncontacts', $result); 2085 $contacts = $result['contacts']; 2086 $noncontacts = $result['noncontacts']; 2087 2088 // Check that we retrieved the correct contacts. 2089 $this->assertCount(2, $contacts); 2090 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2091 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2092 2093 // Verify the correct conversations were returned for the contacts. 2094 $this->assertCount(2, $contacts[0]['conversations']); 2095 // We can't rely on the ordering of conversations within the results, so sort by id first. 2096 usort($contacts[0]['conversations'], function($a, $b) { 2097 return $b['id'] <=> $a['id']; 2098 }); 2099 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']); 2100 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']); 2101 2102 $this->assertCount(0, $contacts[1]['conversations']); 2103 2104 // Check that we retrieved the correct non-contacts. 2105 // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles 2106 // are visible in that course. This excludes users like course contacts. 2107 $this->assertCount(3, $noncontacts); 2108 // Self-conversation first. 2109 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2110 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2111 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2112 2113 // Verify the correct conversations were returned for the non-contacts. 2114 $this->assertCount(1, $noncontacts[1]['conversations']); 2115 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']); 2116 2117 $this->assertCount(1, $noncontacts[2]['conversations']); 2118 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']); 2119 } 2120 2121 /** 2122 * Tests searching for users when site-wide messaging is enabled. 2123 * 2124 * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user 2125 * can view their respective profile. 2126 */ 2127 public function test_message_search_users_messagingallusers_enabled() { 2128 global $DB; 2129 $this->resetAfterTest(); 2130 2131 // Create some users. 2132 $users = []; 2133 foreach (range(1, 9) as $i) { 2134 $user = new \stdClass(); 2135 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2136 $user->lastname = $i; 2137 $user = $this->getDataGenerator()->create_user($user); 2138 $users[$i] = $user; 2139 } 2140 2141 // Enrol a few users in the same course, but leave them as non-contacts. 2142 $course1 = $this->getDataGenerator()->create_course(); 2143 $course2 = $this->getDataGenerator()->create_course(); 2144 2145 $this->setAdminUser(); 2146 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2147 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2148 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2149 2150 // Add some other users as contacts. 2151 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2152 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2153 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2154 2155 // Enrol a user as a teacher in the course, and make the teacher role a course contact role. 2156 $this->getDataGenerator()->enrol_user($users[9]->id, $course2->id, 'editingteacher'); 2157 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 2158 set_config('coursecontact', $teacherrole->id); 2159 2160 // Create individual conversations between some users, one contact and one non-contact. 2161 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2162 [$users[1]->id, $users[2]->id]); 2163 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2164 [$users[6]->id, $users[1]->id]); 2165 2166 // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course. 2167 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2168 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat'); 2169 2170 // Set as the user performing the search. 2171 $this->setUser($users[1]); 2172 2173 // Perform a search with $CFG->messagingallusers enabled. 2174 set_config('messagingallusers', 1); 2175 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2176 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2177 2178 // Confirm that we returns contacts and non-contacts. 2179 $this->assertArrayHasKey('contacts', $result); 2180 $this->assertArrayHasKey('noncontacts', $result); 2181 $contacts = $result['contacts']; 2182 $noncontacts = $result['noncontacts']; 2183 2184 // Check that we retrieved the correct contacts. 2185 $this->assertCount(2, $contacts); 2186 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2187 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2188 2189 // Verify the correct conversations were returned for the contacts. 2190 $this->assertCount(2, $contacts[0]['conversations']); 2191 // We can't rely on the ordering of conversations within the results, so sort by id first. 2192 usort($contacts[0]['conversations'], function($a, $b) { 2193 return $b['id'] <=> $a['id']; 2194 }); 2195 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']); 2196 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']); 2197 2198 $this->assertCount(0, $contacts[1]['conversations']); 2199 2200 // Check that we retrieved the correct non-contacts. 2201 // If site wide messaging is enabled, we expect to be able to search for any users whose profiles we can view. 2202 // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1. 2203 $this->assertCount(4, $noncontacts); 2204 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2205 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2206 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2207 $this->assertEquals($users[9]->id, $noncontacts[3]['id']); 2208 2209 // Verify the correct conversations were returned for the non-contacts. 2210 $this->assertCount(1, $noncontacts[1]['conversations']); 2211 $this->assertCount(1, $noncontacts[2]['conversations']); 2212 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']); 2213 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']); 2214 $this->assertCount(0, $noncontacts[3]['conversations']); 2215 } 2216 2217 /** 2218 * Verify searching for users find themselves when they have self-conversations. 2219 */ 2220 public function test_message_search_users_self_conversations() { 2221 $this->resetAfterTest(); 2222 2223 // Create some users. 2224 $user1 = new \stdClass(); 2225 $user1->firstname = 'User'; 2226 $user1->lastname = 'One'; 2227 $user1 = $this->getDataGenerator()->create_user($user1); 2228 $user2 = new \stdClass(); 2229 $user2->firstname = 'User'; 2230 $user2->lastname = 'Two'; 2231 $user2 = $this->getDataGenerator()->create_user($user2); 2232 2233 // Get self-conversation for user1. 2234 $sc1 = \core_message\api::get_self_conversation($user1->id); 2235 testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!'); 2236 2237 // Perform a search as user1. 2238 $this->setUser($user1); 2239 $result = core_message_external::message_search_users($user1->id, 'One'); 2240 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2241 2242 // Check results are empty. 2243 $this->assertCount(0, $result['contacts']); 2244 $this->assertCount(1, $result['noncontacts']); 2245 } 2246 2247 /** 2248 * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found. 2249 */ 2250 public function test_message_search_users_with_empty_result() { 2251 $this->resetAfterTest(); 2252 2253 // Create some users, but make sure neither will match the search term. 2254 $user1 = new \stdClass(); 2255 $user1->firstname = 'User'; 2256 $user1->lastname = 'One'; 2257 $user1 = $this->getDataGenerator()->create_user($user1); 2258 $user2 = new \stdClass(); 2259 $user2->firstname = 'User'; 2260 $user2->lastname = 'Two'; 2261 $user2 = $this->getDataGenerator()->create_user($user2); 2262 2263 // Perform a search as user1. 2264 $this->setUser($user1); 2265 $result = core_message_external::message_search_users($user1->id, 'search'); 2266 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2267 2268 // Check results are empty. 2269 $this->assertCount(0, $result['contacts']); 2270 $this->assertCount(0, $result['noncontacts']); 2271 } 2272 2273 /** 2274 * Test verifying that limits and offsets work for both the contacts and non-contacts return data. 2275 */ 2276 public function test_message_search_users_limit_offset() { 2277 $this->resetAfterTest(); 2278 2279 // Create 20 users. 2280 $users = []; 2281 foreach (range(1, 20) as $i) { 2282 $user = new \stdClass(); 2283 $user->firstname = "User search"; 2284 $user->lastname = $i; 2285 $user = $this->getDataGenerator()->create_user($user); 2286 $users[$i] = $user; 2287 } 2288 2289 // Enrol the first 8 users in the same course, but leave them as non-contacts. 2290 $this->setAdminUser(); 2291 $course1 = $this->getDataGenerator()->create_course(); 2292 foreach (range(1, 8) as $i) { 2293 $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id); 2294 } 2295 2296 // Add 5 users, starting at the 11th user, as contacts for user1. 2297 foreach (range(11, 15) as $i) { 2298 \core_message\api::add_contact($users[1]->id, $users[$i]->id); 2299 } 2300 2301 // Set as the user performing the search. 2302 $this->setUser($users[1]); 2303 2304 // Search using a limit of 3. 2305 // This tests the case where we have more results than the limit for both contacts and non-contacts. 2306 $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3); 2307 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2308 $contacts = $result['contacts']; 2309 $noncontacts = $result['noncontacts']; 2310 2311 // Check that we retrieved the correct contacts. 2312 $this->assertCount(3, $contacts); 2313 $this->assertEquals($users[11]->id, $contacts[0]['id']); 2314 $this->assertEquals($users[12]->id, $contacts[1]['id']); 2315 $this->assertEquals($users[13]->id, $contacts[2]['id']); 2316 2317 // Check that we retrieved the correct non-contacts. 2318 // Consider first conversation is self-conversation. 2319 $this->assertCount(3, $noncontacts); 2320 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2321 $this->assertEquals($users[2]->id, $noncontacts[1]['id']); 2322 $this->assertEquals($users[3]->id, $noncontacts[2]['id']); 2323 2324 // Now, offset to get the next batch of results. 2325 // We expect to see 2 contacts, and 3 non-contacts. 2326 $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3); 2327 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2328 $contacts = $result['contacts']; 2329 $noncontacts = $result['noncontacts']; 2330 $this->assertCount(2, $contacts); 2331 $this->assertEquals($users[14]->id, $contacts[0]['id']); 2332 $this->assertEquals($users[15]->id, $contacts[1]['id']); 2333 2334 $this->assertCount(3, $noncontacts); 2335 $this->assertEquals($users[4]->id, $noncontacts[0]['id']); 2336 $this->assertEquals($users[5]->id, $noncontacts[1]['id']); 2337 $this->assertEquals($users[6]->id, $noncontacts[2]['id']); 2338 2339 // Now, offset to get the next batch of results. 2340 // We expect to see 0 contacts, and 2 non-contacts. 2341 $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3); 2342 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2343 $contacts = $result['contacts']; 2344 $noncontacts = $result['noncontacts']; 2345 $this->assertCount(0, $contacts); 2346 2347 $this->assertCount(2, $noncontacts); 2348 $this->assertEquals($users[7]->id, $noncontacts[0]['id']); 2349 $this->assertEquals($users[8]->id, $noncontacts[1]['id']); 2350 } 2351 2352 /** 2353 * Tests searching users as another user having the 'moodle/user:viewdetails' capability. 2354 */ 2355 public function test_message_search_users_with_cap() { 2356 $this->resetAfterTest(); 2357 global $DB; 2358 2359 // Create some users. 2360 $users = []; 2361 foreach (range(1, 8) as $i) { 2362 $user = new \stdClass(); 2363 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2364 $user->lastname = $i; 2365 $user = $this->getDataGenerator()->create_user($user); 2366 $users[$i] = $user; 2367 } 2368 2369 // Enrol a few users in the same course, but leave them as non-contacts. 2370 $course1 = $this->getDataGenerator()->create_course(); 2371 $this->setAdminUser(); 2372 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2373 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2374 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2375 2376 // Add some other users as contacts. 2377 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2378 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2379 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2380 2381 // Set as the user performing the search. 2382 $this->setUser($users[1]); 2383 2384 // Grant the authenticated user role the capability 'user:viewdetails' at site context. 2385 $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST); 2386 assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, \context_system::instance()); 2387 2388 // Perform a search with $CFG->messagingallusers disabled. 2389 set_config('messagingallusers', 0); 2390 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2391 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2392 $contacts = $result['contacts']; 2393 $noncontacts = $result['noncontacts']; 2394 2395 // Check that we retrieved the correct contacts. 2396 $this->assertCount(2, $contacts); 2397 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2398 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2399 2400 // Check that we retrieved the correct non-contacts. 2401 // Site-wide messaging is disabled, so we expect to be able to search for any users whose profile we can view. 2402 // Consider first conversations is self-conversation. 2403 $this->assertCount(3, $noncontacts); 2404 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2405 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2406 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2407 } 2408 2409 /** 2410 * Tests searching users as another user without the 'moodle/user:viewdetails' capability. 2411 */ 2412 public function test_message_search_users_without_cap() { 2413 $this->resetAfterTest(); 2414 2415 // Create some users. 2416 $user1 = $this->getDataGenerator()->create_user(); 2417 $user2 = $this->getDataGenerator()->create_user(); 2418 2419 // The person doing the search for another user. 2420 $this->setUser($user1); 2421 2422 // Ensure an exception is thrown. 2423 $this->expectException('moodle_exception'); 2424 core_message_external::message_search_users($user2->id, 'User'); 2425 $this->assertDebuggingCalled(); 2426 } 2427 2428 /** 2429 * Tests searching users with messaging disabled. 2430 */ 2431 public function test_message_search_users_messaging_disabled() { 2432 $this->resetAfterTest(); 2433 2434 // Create some skeleton data just so we can call the WS. 2435 $user = $this->getDataGenerator()->create_user(); 2436 2437 // The person doing the search. 2438 $this->setUser($user); 2439 2440 // Disable messaging. 2441 set_config('messaging', 0); 2442 2443 // Ensure an exception is thrown. 2444 $this->expectException('moodle_exception'); 2445 core_message_external::message_search_users($user->id, 'User'); 2446 } 2447 2448 /** 2449 * Tests searching messages. 2450 */ 2451 public function test_messagearea_search_messages() { 2452 $this->resetAfterTest(true); 2453 2454 // Create some users. 2455 $user1 = self::getDataGenerator()->create_user(); 2456 $user2 = self::getDataGenerator()->create_user(); 2457 2458 // The person doing the search. 2459 $this->setUser($user1); 2460 2461 // Send some messages back and forth. 2462 $time = time(); 2463 $this->send_message($user1, $user2, 'Yo!', 0, $time); 2464 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 2465 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 2466 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 2467 $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 2468 2469 // Perform a search. 2470 $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o'); 2471 2472 // We need to execute the return values cleaning process to simulate the web service server. 2473 $result = \external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result); 2474 2475 // Confirm the data is correct. 2476 $messages = $result['contacts']; 2477 $this->assertCount(2, $messages); 2478 2479 $message1 = $messages[0]; 2480 $message2 = $messages[1]; 2481 2482 $this->assertEquals($user2->id, $message1['userid']); 2483 $this->assertEquals(fullname($user2), $message1['fullname']); 2484 $this->assertTrue($message1['ismessaging']); 2485 $this->assertFalse($message1['sentfromcurrentuser']); 2486 $this->assertEquals('Word.', $message1['lastmessage']); 2487 $this->assertNotEmpty($message1['messageid']); 2488 $this->assertNull($message1['isonline']); 2489 $this->assertFalse($message1['isread']); 2490 $this->assertFalse($message1['isblocked']); 2491 $this->assertNull($message1['unreadcount']); 2492 $this->assertEquals($convid, $message1['conversationid']); 2493 2494 $this->assertEquals($user2->id, $message2['userid']); 2495 $this->assertEquals(fullname($user2), $message2['fullname']); 2496 $this->assertTrue($message2['ismessaging']); 2497 $this->assertTrue($message2['sentfromcurrentuser']); 2498 $this->assertEquals('Yo!', $message2['lastmessage']); 2499 $this->assertNotEmpty($message2['messageid']); 2500 $this->assertNull($message2['isonline']); 2501 $this->assertTrue($message2['isread']); 2502 $this->assertFalse($message2['isblocked']); 2503 $this->assertNull($message2['unreadcount']); 2504 $this->assertEquals($convid, $message2['conversationid']); 2505 } 2506 2507 /** 2508 * Tests searching messages as another user. 2509 */ 2510 public function test_messagearea_search_messages_as_other_user() { 2511 $this->resetAfterTest(true); 2512 2513 // The person doing the search. 2514 $this->setAdminUser(); 2515 2516 // Create some users. 2517 $user1 = self::getDataGenerator()->create_user(); 2518 $user2 = self::getDataGenerator()->create_user(); 2519 2520 // Send some messages back and forth. 2521 $time = time(); 2522 $this->send_message($user1, $user2, 'Yo!', 0, $time); 2523 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 2524 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 2525 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 2526 2527 // Perform a search. 2528 $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o'); 2529 2530 // We need to execute the return values cleaning process to simulate the web service server. 2531 $result = \external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), 2532 $result); 2533 2534 // Confirm the data is correct. 2535 $messages = $result['contacts']; 2536 $this->assertCount(2, $messages); 2537 2538 $message1 = $messages[0]; 2539 $message2 = $messages[1]; 2540 2541 $this->assertEquals($user2->id, $message1['userid']); 2542 $this->assertEquals(fullname($user2), $message1['fullname']); 2543 $this->assertTrue($message1['ismessaging']); 2544 $this->assertFalse($message1['sentfromcurrentuser']); 2545 $this->assertEquals('Word.', $message1['lastmessage']); 2546 $this->assertNotEmpty($message1['messageid']); 2547 $this->assertFalse($message1['isonline']); 2548 $this->assertFalse($message1['isread']); 2549 $this->assertFalse($message1['isblocked']); 2550 $this->assertNull($message1['unreadcount']); 2551 2552 $this->assertEquals($user2->id, $message2['userid']); 2553 $this->assertEquals(fullname($user2), $message2['fullname']); 2554 $this->assertTrue($message2['ismessaging']); 2555 $this->assertTrue($message2['sentfromcurrentuser']); 2556 $this->assertEquals('Yo!', $message2['lastmessage']); 2557 $this->assertNotEmpty($message2['messageid']); 2558 $this->assertFalse($message2['isonline']); 2559 $this->assertTrue($message2['isread']); 2560 $this->assertFalse($message2['isblocked']); 2561 $this->assertNull($message2['unreadcount']); 2562 } 2563 2564 /** 2565 * Tests searching messages as another user without the proper capabilities. 2566 */ 2567 public function test_messagearea_search_messages_as_other_user_without_cap() { 2568 $this->resetAfterTest(true); 2569 2570 // Create some users. 2571 $user1 = self::getDataGenerator()->create_user(); 2572 $user2 = self::getDataGenerator()->create_user(); 2573 2574 // The person doing the search for another user. 2575 $this->setUser($user1); 2576 2577 // Ensure an exception is thrown. 2578 $this->expectException('moodle_exception'); 2579 core_message_external::data_for_messagearea_search_messages($user2->id, 'Search'); 2580 } 2581 2582 /** 2583 * Tests searching messages with messaging disabled 2584 */ 2585 public function test_messagearea_search_messages_messaging_disabled() { 2586 global $CFG; 2587 2588 $this->resetAfterTest(true); 2589 2590 // Create some skeleton data just so we can call the WS. 2591 $user = self::getDataGenerator()->create_user(); 2592 2593 // The person doing the search . 2594 $this->setUser($user); 2595 2596 // Disable messaging. 2597 $CFG->messaging = 0; 2598 2599 // Ensure an exception is thrown. 2600 $this->expectException('moodle_exception'); 2601 core_message_external::data_for_messagearea_search_messages($user->id, 'Search'); 2602 } 2603 2604 /** 2605 * Tests retrieving contacts. 2606 */ 2607 public function test_get_user_contacts() { 2608 $this->resetAfterTest(true); 2609 2610 // Create some users. 2611 $user1 = self::getDataGenerator()->create_user(); 2612 2613 // Set as the user. 2614 $this->setUser($user1); 2615 2616 $user2 = new \stdClass(); 2617 $user2->firstname = 'User'; 2618 $user2->lastname = 'A'; 2619 $user2 = self::getDataGenerator()->create_user($user2); 2620 2621 $user3 = new \stdClass(); 2622 $user3->firstname = 'User'; 2623 $user3->lastname = 'B'; 2624 $user3 = self::getDataGenerator()->create_user($user3); 2625 2626 $user4 = new \stdClass(); 2627 $user4->firstname = 'User'; 2628 $user4->lastname = 'C'; 2629 $user4 = self::getDataGenerator()->create_user($user4); 2630 2631 $user5 = new \stdClass(); 2632 $user5->firstname = 'User'; 2633 $user5->lastname = 'D'; 2634 $user5 = self::getDataGenerator()->create_user($user5); 2635 2636 // Add some users as contacts. 2637 \core_message\api::add_contact($user1->id, $user2->id); 2638 \core_message\api::add_contact($user1->id, $user3->id); 2639 \core_message\api::add_contact($user1->id, $user4->id); 2640 2641 // Retrieve the contacts. 2642 $result = core_message_external::get_user_contacts($user1->id); 2643 2644 // We need to execute the return values cleaning process to simulate the web service server. 2645 $result = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), 2646 $result); 2647 2648 // Confirm the data is correct. 2649 $contacts = $result; 2650 usort($contacts, ['static', 'sort_contacts_id']); 2651 $this->assertCount(3, $contacts); 2652 2653 $contact1 = array_shift($contacts); 2654 $contact2 = array_shift($contacts); 2655 $contact3 = array_shift($contacts); 2656 2657 $this->assertEquals($user2->id, $contact1['id']); 2658 $this->assertEquals(fullname($user2), $contact1['fullname']); 2659 $this->assertTrue($contact1['iscontact']); 2660 2661 $this->assertEquals($user3->id, $contact2['id']); 2662 $this->assertEquals(fullname($user3), $contact2['fullname']); 2663 $this->assertTrue($contact2['iscontact']); 2664 2665 $this->assertEquals($user4->id, $contact3['id']); 2666 $this->assertEquals(fullname($user4), $contact3['fullname']); 2667 $this->assertTrue($contact3['iscontact']); 2668 } 2669 2670 /** 2671 * Tests retrieving contacts as another user. 2672 */ 2673 public function test_get_user_contacts_as_other_user() { 2674 $this->resetAfterTest(true); 2675 2676 $this->setAdminUser(); 2677 2678 // Create some users. 2679 $user1 = self::getDataGenerator()->create_user(); 2680 2681 $user2 = new \stdClass(); 2682 $user2->firstname = 'User'; 2683 $user2->lastname = 'A'; 2684 $user2 = self::getDataGenerator()->create_user($user2); 2685 2686 $user3 = new \stdClass(); 2687 $user3->firstname = 'User'; 2688 $user3->lastname = 'B'; 2689 $user3 = self::getDataGenerator()->create_user($user3); 2690 2691 $user4 = new \stdClass(); 2692 $user4->firstname = 'User'; 2693 $user4->lastname = 'C'; 2694 $user4 = self::getDataGenerator()->create_user($user4); 2695 2696 $user5 = new \stdClass(); 2697 $user5->firstname = 'User'; 2698 $user5->lastname = 'D'; 2699 $user5 = self::getDataGenerator()->create_user($user5); 2700 2701 // Add some users as contacts. 2702 \core_message\api::add_contact($user1->id, $user2->id); 2703 \core_message\api::add_contact($user1->id, $user3->id); 2704 \core_message\api::add_contact($user1->id, $user4->id); 2705 2706 // Retrieve the contacts. 2707 $result = core_message_external::get_user_contacts($user1->id); 2708 2709 // We need to execute the return values cleaning process to simulate the web service server. 2710 $result = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), 2711 $result); 2712 2713 // Confirm the data is correct. 2714 $contacts = $result; 2715 usort($contacts, ['static', 'sort_contacts_id']); 2716 $this->assertCount(3, $contacts); 2717 2718 $contact1 = array_shift($contacts); 2719 $contact2 = array_shift($contacts); 2720 $contact3 = array_shift($contacts); 2721 2722 $this->assertEquals($user2->id, $contact1['id']); 2723 $this->assertEquals(fullname($user2), $contact1['fullname']); 2724 $this->assertTrue($contact1['iscontact']); 2725 2726 $this->assertEquals($user3->id, $contact2['id']); 2727 $this->assertEquals(fullname($user3), $contact2['fullname']); 2728 $this->assertTrue($contact2['iscontact']); 2729 2730 $this->assertEquals($user4->id, $contact3['id']); 2731 $this->assertEquals(fullname($user4), $contact3['fullname']); 2732 $this->assertTrue($contact3['iscontact']); 2733 } 2734 2735 /** 2736 * Tests retrieving contacts as another user without the proper capabilities. 2737 */ 2738 public function test_get_user_contacts_as_other_user_without_cap() { 2739 $this->resetAfterTest(true); 2740 2741 // Create some users. 2742 $user1 = self::getDataGenerator()->create_user(); 2743 $user2 = self::getDataGenerator()->create_user(); 2744 2745 // The person retrieving the contacts for another user. 2746 $this->setUser($user1); 2747 2748 // Perform the WS call and ensure an exception is thrown. 2749 $this->expectException('moodle_exception'); 2750 core_message_external::get_user_contacts($user2->id); 2751 } 2752 2753 /** 2754 * Tests retrieving contacts with messaging disabled. 2755 */ 2756 public function test_get_user_contacts_messaging_disabled() { 2757 global $CFG; 2758 2759 $this->resetAfterTest(true); 2760 2761 // Create some skeleton data just so we can call the WS. 2762 $user = self::getDataGenerator()->create_user(); 2763 2764 // The person retrieving the contacts. 2765 $this->setUser($user); 2766 2767 // Disable messaging. 2768 $CFG->messaging = 0; 2769 2770 // Perform the WS call and ensure we are shown that it is disabled. 2771 $this->expectException('moodle_exception'); 2772 core_message_external::get_user_contacts($user->id); 2773 } 2774 2775 /** 2776 * Test getting contacts when there are no results. 2777 */ 2778 public function test_get_user_contacts_no_results() { 2779 $this->resetAfterTest(); 2780 2781 $user1 = self::getDataGenerator()->create_user(); 2782 2783 $this->setUser($user1); 2784 2785 $requests = core_message_external::get_user_contacts($user1->id); 2786 $requests = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), $requests); 2787 2788 $this->assertEmpty($requests); 2789 } 2790 2791 /** 2792 * Tests get_conversation_messages for retrieving messages. 2793 */ 2794 public function test_get_conversation_messages() { 2795 $this->resetAfterTest(true); 2796 2797 // Create some users. 2798 $user1 = self::getDataGenerator()->create_user(); 2799 $user2 = self::getDataGenerator()->create_user(); 2800 $user3 = self::getDataGenerator()->create_user(); 2801 $user4 = self::getDataGenerator()->create_user(); 2802 $user5 = self::getDataGenerator()->create_user(); 2803 2804 // Create group conversation. 2805 $conversation = \core_message\api::create_conversation( 2806 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2807 [$user1->id, $user2->id, $user3->id, $user4->id] 2808 ); 2809 2810 // The person asking for the messages. 2811 $this->setUser($user1); 2812 2813 // Send some messages back and forth. 2814 $time = time(); 2815 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time); 2816 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1); 2817 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2); 2818 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3); 2819 2820 // Retrieve the messages. 2821 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id); 2822 2823 // We need to execute the return values cleaning process to simulate the web service server. 2824 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2825 $result); 2826 2827 // Check the results are correct. 2828 $this->assertEquals($conversation->id, $result['id']); 2829 2830 // Confirm the members data is correct. 2831 $members = $result['members']; 2832 $this->assertCount(3, $members); 2833 $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']]; 2834 $this->assertContainsEquals($user1->id, $membersid); 2835 $this->assertContainsEquals($user2->id, $membersid); 2836 $this->assertContainsEquals($user3->id, $membersid); 2837 2838 $membersfullnames = [$members[0]['fullname'], $members[1]['fullname'], $members[2]['fullname']]; 2839 $this->assertContainsEquals(fullname($user1), $membersfullnames); 2840 $this->assertContainsEquals(fullname($user2), $membersfullnames); 2841 $this->assertContainsEquals(fullname($user3), $membersfullnames); 2842 2843 // Confirm the messages data is correct. 2844 $messages = $result['messages']; 2845 $this->assertCount(4, $messages); 2846 2847 $message1 = $messages[0]; 2848 $message2 = $messages[1]; 2849 $message3 = $messages[2]; 2850 $message4 = $messages[3]; 2851 2852 $this->assertEquals($user1->id, $message1['useridfrom']); 2853 $this->assertStringContainsString('Yo!', $message1['text']); 2854 2855 $this->assertEquals($user3->id, $message2['useridfrom']); 2856 $this->assertStringContainsString('Sup mang?', $message2['text']); 2857 2858 $this->assertEquals($user2->id, $message3['useridfrom']); 2859 $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']); 2860 2861 $this->assertEquals($user1->id, $message4['useridfrom']); 2862 $this->assertStringContainsString('Word.', $message4['text']); 2863 } 2864 2865 /** 2866 * Tests get_conversation_messages for retrieving messages using timefrom parameter. 2867 */ 2868 public function test_get_conversation_messages_timefrom() { 2869 $this->resetAfterTest(true); 2870 2871 // Create some users. 2872 $user1 = self::getDataGenerator()->create_user(); 2873 $user2 = self::getDataGenerator()->create_user(); 2874 $user3 = self::getDataGenerator()->create_user(); 2875 $user4 = self::getDataGenerator()->create_user(); 2876 2877 // Create group conversation. 2878 $conversation = \core_message\api::create_conversation( 2879 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2880 [$user1->id, $user2->id, $user3->id] 2881 ); 2882 2883 // The person asking for the messages. 2884 $this->setUser($user1); 2885 2886 // Send some messages back and forth. 2887 $time = time(); 2888 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time - 4); 2889 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time - 3); 2890 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 3', $time - 2); 2891 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 4', $time - 1); 2892 2893 // Retrieve the messages from $time - 3, which should be the 3 most recent messages. 2894 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, false, $time - 3); 2895 2896 // We need to execute the return values cleaning process to simulate the web service server. 2897 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2898 $result); 2899 2900 // Check the results are correct. 2901 $this->assertEquals($conversation->id, $result['id']); 2902 2903 // Confirm the messages data is correct. 2904 $messages = $result['messages']; 2905 $this->assertCount(3, $messages); 2906 2907 $message1 = $messages[0]; 2908 $message2 = $messages[1]; 2909 $message3 = $messages[2]; 2910 2911 $this->assertStringContainsString('Message 2', $message1['text']); 2912 $this->assertStringContainsString('Message 3', $message2['text']); 2913 $this->assertStringContainsString('Message 4', $message3['text']); 2914 2915 // Confirm the members data is correct. 2916 $members = $result['members']; 2917 $this->assertCount(1, $members); 2918 $this->assertEquals($user2->id, $members[0]['id']); 2919 } 2920 2921 /** 2922 * Tests get_conversation_messages for retrieving messages as another user. 2923 */ 2924 public function test_get_conversation_messages_as_other_user() { 2925 $this->resetAfterTest(true); 2926 2927 // Set as admin. 2928 $this->setAdminUser(); 2929 2930 // Create some users. 2931 $user1 = self::getDataGenerator()->create_user(); 2932 $user2 = self::getDataGenerator()->create_user(); 2933 $user3 = self::getDataGenerator()->create_user(); 2934 $user4 = self::getDataGenerator()->create_user(); 2935 2936 // Create group conversation. 2937 $conversation = \core_message\api::create_conversation( 2938 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2939 [$user1->id, $user2->id, $user3->id, $user4->id] 2940 ); 2941 2942 // Send some messages back and forth. 2943 $time = time(); 2944 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time); 2945 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1); 2946 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2); 2947 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3); 2948 2949 // Retrieve the messages. 2950 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id); 2951 2952 // We need to execute the return values cleaning process to simulate the web service server. 2953 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2954 $result); 2955 2956 // Check the results are correct. 2957 $this->assertEquals($conversation->id, $result['id']); 2958 2959 // Confirm the members data is correct. 2960 $members = $result['members']; 2961 $this->assertCount(3, $members); 2962 $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']]; 2963 $this->assertContainsEquals($user1->id, $membersid); 2964 $this->assertContainsEquals($user2->id, $membersid); 2965 $this->assertContainsEquals($user3->id, $membersid); 2966 2967 // Confirm the message data is correct. 2968 $messages = $result['messages']; 2969 $this->assertCount(4, $messages); 2970 2971 $message1 = $messages[0]; 2972 $message2 = $messages[1]; 2973 $message3 = $messages[2]; 2974 $message4 = $messages[3]; 2975 2976 $this->assertEquals($user1->id, $message1['useridfrom']); 2977 $this->assertStringContainsString('Yo!', $message1['text']); 2978 2979 $this->assertEquals($user3->id, $message2['useridfrom']); 2980 $this->assertStringContainsString('Sup mang?', $message2['text']); 2981 2982 $this->assertEquals($user2->id, $message3['useridfrom']); 2983 $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']); 2984 2985 $this->assertEquals($user1->id, $message4['useridfrom']); 2986 $this->assertStringContainsString('Word.', $message4['text']); 2987 } 2988 2989 /** 2990 * Tests get_conversation_messages for retrieving messages as another user without the proper capabilities. 2991 */ 2992 public function test_get_conversation_messages_as_other_user_without_cap() { 2993 $this->resetAfterTest(true); 2994 2995 // Create some users. 2996 $user1 = self::getDataGenerator()->create_user(); 2997 $user2 = self::getDataGenerator()->create_user(); 2998 $user3 = self::getDataGenerator()->create_user(); 2999 $user4 = self::getDataGenerator()->create_user(); 3000 3001 // Create group conversation. 3002 $conversation = \core_message\api::create_conversation( 3003 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3004 [$user1->id, $user2->id, $user3->id, $user4->id] 3005 ); 3006 3007 // The person asking for the messages for another user. 3008 $this->setUser($user1); 3009 3010 // Ensure an exception is thrown. 3011 $this->expectException('moodle_exception'); 3012 core_message_external::get_conversation_messages($user2->id, $conversation->id); 3013 } 3014 3015 /** 3016 * Tests get_conversation_messages for retrieving messages as another user not in the conversation. 3017 */ 3018 public function test_get_conversation_messages_as_user_not_in_conversation() { 3019 $this->resetAfterTest(true); 3020 3021 // Create some users. 3022 $user1 = self::getDataGenerator()->create_user(); 3023 $user2 = self::getDataGenerator()->create_user(); 3024 $user3 = self::getDataGenerator()->create_user(); // Not in group. 3025 3026 // Create group conversation. 3027 $conversation = \core_message\api::create_conversation( 3028 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3029 [$user1->id, $user2->id] 3030 ); 3031 3032 // The person asking for the messages for a conversation he does not belong to. 3033 $this->setUser($user3); 3034 3035 // Ensure an exception is thrown. 3036 $this->expectExceptionMessage('User is not part of conversation.'); 3037 core_message_external::get_conversation_messages($user3->id, $conversation->id); 3038 } 3039 3040 /** 3041 * Tests get_conversation_messages for retrieving messages with messaging disabled. 3042 */ 3043 public function test_get_conversation_messages_messaging_disabled() { 3044 $this->resetAfterTest(true); 3045 3046 // Create some skeleton data just so we can call the WS. 3047 $user1 = self::getDataGenerator()->create_user(); 3048 $user2 = self::getDataGenerator()->create_user(); 3049 $user3 = self::getDataGenerator()->create_user(); 3050 $user4 = self::getDataGenerator()->create_user(); 3051 3052 // Create group conversation. 3053 $conversation = \core_message\api::create_conversation( 3054 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3055 [$user1->id, $user2->id, $user3->id, $user4->id] 3056 ); 3057 3058 // The person asking for the messages for another user. 3059 $this->setUser($user1); 3060 3061 // Disable messaging. 3062 set_config('messaging', 0); 3063 3064 // Ensure an exception is thrown. 3065 $this->expectException('moodle_exception'); 3066 core_message_external::get_conversation_messages($user1->id, $conversation->id); 3067 } 3068 3069 /** 3070 * Test marking all conversation messages as read with an invalid user. 3071 */ 3072 public function test_mark_all_conversation_messages_as_read_invalid_user_exception() { 3073 $this->resetAfterTest(true); 3074 3075 $user1 = self::getDataGenerator()->create_user(); 3076 $user2 = self::getDataGenerator()->create_user(); 3077 3078 // Send some messages back and forth. 3079 $time = time(); 3080 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3081 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3082 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3083 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3084 3085 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3086 3087 $this->expectException('moodle_exception'); 3088 core_message_external::mark_all_conversation_messages_as_read(-2132131, $conversationid); 3089 } 3090 3091 /** 3092 * Test marking all conversation messages as read without proper access. 3093 */ 3094 public function test_mark_all_conversation_messages_as_read_access_denied_exception() { 3095 $this->resetAfterTest(true); 3096 3097 $user1 = self::getDataGenerator()->create_user(); 3098 $user2 = self::getDataGenerator()->create_user(); 3099 $user3 = self::getDataGenerator()->create_user(); 3100 3101 // Send some messages back and forth. 3102 $time = time(); 3103 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3104 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3105 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3106 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3107 3108 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3109 3110 // User 3 is not in the conversation. 3111 $this->expectException('moodle_exception'); 3112 core_message_external::mark_all_conversation_messages_as_read($user3->id, $conversationid); 3113 } 3114 3115 /** 3116 * Test marking all conversation messages as read for another user. 3117 */ 3118 public function test_mark_all_conversation_messages_as_read_wrong_user() { 3119 $this->resetAfterTest(true); 3120 3121 $user1 = self::getDataGenerator()->create_user(); 3122 $user2 = self::getDataGenerator()->create_user(); 3123 3124 // Send some messages back and forth. 3125 $time = time(); 3126 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3127 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3128 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3129 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3130 3131 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3132 3133 // Can't mark the messages as read for user 2. 3134 $this->setUser($user1); 3135 $this->expectException('moodle_exception'); 3136 core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid); 3137 } 3138 3139 /** 3140 * Test marking all conversation messages as admin. 3141 */ 3142 public function test_mark_all_conversation_messages_as_admin() { 3143 global $DB; 3144 3145 $this->resetAfterTest(true); 3146 3147 $user1 = self::getDataGenerator()->create_user(); 3148 $user2 = self::getDataGenerator()->create_user(); 3149 3150 // Send some messages back and forth. 3151 $time = time(); 3152 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3153 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3154 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3155 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3156 3157 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3158 3159 // Admin can do anything. 3160 $this->setAdminUser(); 3161 core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid); 3162 $this->assertEquals(2, $DB->count_records('message_user_actions')); 3163 } 3164 3165 /** 3166 * Test marking all conversation messages. 3167 */ 3168 public function test_mark_all_conversation_messages_as_read() { 3169 global $DB; 3170 3171 $this->resetAfterTest(true); 3172 3173 $user1 = self::getDataGenerator()->create_user(); 3174 $user2 = self::getDataGenerator()->create_user(); 3175 3176 // Send some messages back and forth. 3177 $time = time(); 3178 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3179 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3180 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3181 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3182 3183 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3184 3185 // We are the user we want to mark the messages for and we are in the conversation, all good. 3186 $this->setUser($user1); 3187 core_message_external::mark_all_conversation_messages_as_read($user1->id, $conversationid); 3188 $this->assertEquals(2, $DB->count_records('message_user_actions')); 3189 } 3190 3191 /** 3192 * Test getting unread conversation count. 3193 */ 3194 public function test_get_unread_conversations_count() { 3195 $this->resetAfterTest(true); 3196 3197 // Create some users. 3198 $user1 = self::getDataGenerator()->create_user(); 3199 $user2 = self::getDataGenerator()->create_user(); 3200 $user3 = self::getDataGenerator()->create_user(); 3201 $user4 = self::getDataGenerator()->create_user(); 3202 3203 // The person wanting the conversation count. 3204 $this->setUser($user1); 3205 3206 // Send some messages back and forth, have some different conversations with different users. 3207 $this->send_message($user1, $user2, 'Yo!'); 3208 $this->send_message($user2, $user1, 'Sup mang?'); 3209 $this->send_message($user1, $user2, 'Writing PHPUnit tests!'); 3210 $this->send_message($user2, $user1, 'Word.'); 3211 3212 $this->send_message($user1, $user3, 'Booyah'); 3213 $this->send_message($user3, $user1, 'Whaaat?'); 3214 $this->send_message($user1, $user3, 'Nothing.'); 3215 $this->send_message($user3, $user1, 'Cool.'); 3216 3217 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3218 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3219 $this->send_message($user1, $user4, 'Dope.'); 3220 3221 // Get the unread conversation count. 3222 $result = core_message_external::get_unread_conversations_count($user1->id); 3223 3224 // We need to execute the return values cleaning process to simulate the web service server. 3225 $result = \external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(), 3226 $result); 3227 3228 $this->assertEquals(3, $result); 3229 } 3230 3231 /** 3232 * Test getting unread conversation count as other user. 3233 */ 3234 public function test_get_unread_conversations_count_as_other_user() { 3235 $this->resetAfterTest(true); 3236 3237 // The person wanting the conversation count. 3238 $this->setAdminUser(); 3239 3240 // Create some users. 3241 $user1 = self::getDataGenerator()->create_user(); 3242 $user2 = self::getDataGenerator()->create_user(); 3243 $user3 = self::getDataGenerator()->create_user(); 3244 $user4 = self::getDataGenerator()->create_user(); 3245 3246 // Send some messages back and forth, have some different conversations with different users. 3247 $this->send_message($user1, $user2, 'Yo!'); 3248 $this->send_message($user2, $user1, 'Sup mang?'); 3249 $this->send_message($user1, $user2, 'Writing PHPUnit tests!'); 3250 $this->send_message($user2, $user1, 'Word.'); 3251 3252 $this->send_message($user1, $user3, 'Booyah'); 3253 $this->send_message($user3, $user1, 'Whaaat?'); 3254 $this->send_message($user1, $user3, 'Nothing.'); 3255 $this->send_message($user3, $user1, 'Cool.'); 3256 3257 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3258 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3259 $this->send_message($user1, $user4, 'Dope.'); 3260 3261 // Get the unread conversation count. 3262 $result = core_message_external::get_unread_conversations_count($user1->id); 3263 3264 // We need to execute the return values cleaning process to simulate the web service server. 3265 $result = \external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(), 3266 $result); 3267 3268 $this->assertEquals(3, $result); 3269 } 3270 3271 /** 3272 * Test getting unread conversation count as other user without proper capability. 3273 */ 3274 public function test_get_unread_conversations_count_as_other_user_without_cap() { 3275 $this->resetAfterTest(true); 3276 3277 // Create some users. 3278 $user1 = self::getDataGenerator()->create_user(); 3279 $user2 = self::getDataGenerator()->create_user(); 3280 3281 // The person wanting the conversation count. 3282 $this->setUser($user1); 3283 3284 // Ensure an exception is thrown. 3285 $this->expectException('moodle_exception'); 3286 core_message_external::get_unread_conversations_count($user2->id); 3287 } 3288 3289 /** 3290 * Test deleting conversations. 3291 */ 3292 public function test_delete_conversations_by_id() { 3293 global $DB; 3294 3295 $this->resetAfterTest(true); 3296 3297 // Create some users. 3298 $user1 = self::getDataGenerator()->create_user(); 3299 $user2 = self::getDataGenerator()->create_user(); 3300 3301 // The person wanting to delete the conversation. 3302 $this->setUser($user1); 3303 3304 // Send some messages back and forth. 3305 $time = time(); 3306 $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time); 3307 $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3308 $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3309 $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3310 3311 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3312 3313 // Delete the conversation. 3314 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3315 3316 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC'); 3317 $this->assertCount(4, $muas); 3318 // Sort by id. 3319 ksort($muas); 3320 3321 $mua1 = array_shift($muas); 3322 $mua2 = array_shift($muas); 3323 $mua3 = array_shift($muas); 3324 $mua4 = array_shift($muas); 3325 3326 $this->assertEquals($user1->id, $mua1->userid); 3327 $this->assertEquals($m1id, $mua1->messageid); 3328 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action); 3329 3330 $this->assertEquals($user1->id, $mua2->userid); 3331 $this->assertEquals($m2id, $mua2->messageid); 3332 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action); 3333 3334 $this->assertEquals($user1->id, $mua3->userid); 3335 $this->assertEquals($m3id, $mua3->messageid); 3336 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action); 3337 3338 $this->assertEquals($user1->id, $mua4->userid); 3339 $this->assertEquals($m4id, $mua4->messageid); 3340 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action); 3341 } 3342 3343 /** 3344 * Test deleting conversations as other user. 3345 */ 3346 public function test_delete_conversations_by_id_as_other_user() { 3347 global $DB; 3348 3349 $this->resetAfterTest(true); 3350 3351 $this->setAdminUser(); 3352 3353 // Create some users. 3354 $user1 = self::getDataGenerator()->create_user(); 3355 $user2 = self::getDataGenerator()->create_user(); 3356 3357 // Send some messages back and forth. 3358 $time = time(); 3359 $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time); 3360 $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3361 $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3362 $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3363 3364 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3365 3366 // Delete the conversation. 3367 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3368 3369 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC'); 3370 $this->assertCount(4, $muas); 3371 // Sort by id. 3372 ksort($muas); 3373 3374 $mua1 = array_shift($muas); 3375 $mua2 = array_shift($muas); 3376 $mua3 = array_shift($muas); 3377 $mua4 = array_shift($muas); 3378 3379 $this->assertEquals($user1->id, $mua1->userid); 3380 $this->assertEquals($m1id, $mua1->messageid); 3381 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action); 3382 3383 $this->assertEquals($user1->id, $mua2->userid); 3384 $this->assertEquals($m2id, $mua2->messageid); 3385 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action); 3386 3387 $this->assertEquals($user1->id, $mua3->userid); 3388 $this->assertEquals($m3id, $mua3->messageid); 3389 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action); 3390 3391 $this->assertEquals($user1->id, $mua4->userid); 3392 $this->assertEquals($m4id, $mua4->messageid); 3393 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action); 3394 } 3395 3396 /** 3397 * Test deleting conversations as other user without proper capability. 3398 */ 3399 public function test_delete_conversations_by_id_as_other_user_without_cap() { 3400 $this->resetAfterTest(true); 3401 3402 // Create some users. 3403 $user1 = self::getDataGenerator()->create_user(); 3404 $user2 = self::getDataGenerator()->create_user(); 3405 $user3 = self::getDataGenerator()->create_user(); 3406 3407 // Send some messages back and forth. 3408 $time = time(); 3409 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3410 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3411 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3412 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3413 3414 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3415 3416 // The person wanting to delete the conversation. 3417 $this->setUser($user3); 3418 3419 // Ensure an exception is thrown. 3420 $this->expectException('moodle_exception'); 3421 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3422 } 3423 3424 /** 3425 * Test deleting conversations with messaging disabled. 3426 */ 3427 public function test_delete_conversations_by_id_messaging_disabled() { 3428 global $CFG; 3429 3430 $this->resetAfterTest(true); 3431 3432 // Create some users. 3433 $user1 = self::getDataGenerator()->create_user(); 3434 $user2 = self::getDataGenerator()->create_user(); 3435 3436 // Send some messages back and forth. 3437 $time = time(); 3438 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3439 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3440 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3441 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3442 3443 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3444 3445 // The person wanting to delete the conversation. 3446 $this->setUser($user1); 3447 3448 // Disable messaging. 3449 $CFG->messaging = 0; 3450 3451 // Ensure an exception is thrown. 3452 $this->expectException('moodle_exception'); 3453 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3454 } 3455 3456 /** 3457 * Test get message processor. 3458 */ 3459 public function test_get_message_processor() { 3460 $this->resetAfterTest(true); 3461 3462 // Create a user. 3463 $user1 = self::getDataGenerator()->create_user(); 3464 3465 // Set you as the user. 3466 $this->setUser($user1); 3467 3468 // Get the message processors. 3469 $result = core_message_external::get_message_processor($user1->id, 'popup'); 3470 3471 // We need to execute the return values cleaning process to simulate the web service server. 3472 $result = \external_api::clean_returnvalue(core_message_external::get_message_processor_returns(), $result); 3473 3474 $this->assertNotEmpty($result['systemconfigured']); 3475 $this->assertNotEmpty($result['userconfigured']); 3476 } 3477 3478 /** 3479 * Test get_user_notification_preferences 3480 */ 3481 public function test_get_user_message_preferences() { 3482 $this->resetAfterTest(true); 3483 3484 $user = self::getDataGenerator()->create_user(); 3485 $this->setUser($user); 3486 3487 // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody. 3488 set_config('messagingallusers', true); 3489 3490 // Set a couple of preferences to test. 3491 set_user_preference('message_provider_moodle_instantmessage_loggedin', 'email', $user); 3492 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user); 3493 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user); 3494 3495 $prefs = core_message_external::get_user_message_preferences(); 3496 $prefs = \external_api::clean_returnvalue(core_message_external::get_user_message_preferences_returns(), $prefs); 3497 $this->assertEquals($user->id, $prefs['preferences']['userid']); 3498 3499 // Check components. 3500 $this->assertCount(1, $prefs['preferences']['components']); 3501 $this->assertEquals(\core_message\api::MESSAGE_PRIVACY_SITE, $prefs['blocknoncontacts']); 3502 3503 // Check some preferences that we previously set. 3504 $found = false; 3505 foreach ($prefs['preferences']['components'] as $component) { 3506 foreach ($component['notifications'] as $prefdata) { 3507 if ($prefdata['preferencekey'] != 'message_provider_moodle_instantmessage') { 3508 continue; 3509 } 3510 foreach ($prefdata['processors'] as $processor) { 3511 if ($processor['name'] == 'email') { 3512 $this->assertTrue($processor['loggedin']['checked']); 3513 $this->assertTrue($processor['loggedoff']['checked']); 3514 $found = true; 3515 } 3516 } 3517 } 3518 } 3519 $this->assertTrue($found); 3520 } 3521 3522 /** 3523 * Test get_user_message_preferences permissions 3524 */ 3525 public function test_get_user_message_preferences_permissions() { 3526 $this->resetAfterTest(true); 3527 3528 $user = self::getDataGenerator()->create_user(); 3529 $otheruser = self::getDataGenerator()->create_user(); 3530 $this->setUser($user); 3531 3532 $this->expectException('moodle_exception'); 3533 $prefs = core_message_external::get_user_message_preferences($otheruser->id); 3534 } 3535 3536 /** 3537 * Comparison function for sorting contacts. 3538 * 3539 * @param array $a 3540 * @param array $b 3541 * @return bool 3542 */ 3543 protected static function sort_contacts($a, $b) { 3544 return $a['userid'] <=> $b['userid']; 3545 } 3546 3547 /** 3548 * Comparison function for sorting contacts. 3549 * 3550 * @param array $a 3551 * @param array $b 3552 * @return bool 3553 */ 3554 protected static function sort_contacts_id($a, $b) { 3555 return $a['id'] <=> $b['id']; 3556 } 3557 3558 /** 3559 * Test verifying that conversations can be marked as favourite conversations. 3560 */ 3561 public function test_set_favourite_conversations_basic() { 3562 $this->resetAfterTest(); 3563 3564 $user1 = self::getDataGenerator()->create_user(); 3565 $user2 = self::getDataGenerator()->create_user(); 3566 $user3 = self::getDataGenerator()->create_user(); 3567 $user4 = self::getDataGenerator()->create_user(); 3568 3569 $this->setUser($user1); 3570 3571 // Now, create some conversations. 3572 $time = time(); 3573 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3574 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3575 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3576 3577 $this->send_message($user1, $user3, 'Booyah'); 3578 $this->send_message($user3, $user1, 'Whaaat?'); 3579 $this->send_message($user1, $user3, 'Nothing.'); 3580 3581 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3582 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3583 3584 // Favourite 2 conversations as user 1. 3585 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3586 $conversation2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]); 3587 $result = core_message_external::set_favourite_conversations($user1->id, [$conversation1, $conversation2]); 3588 3589 // We need to execute the return values cleaning process to simulate the web service server. 3590 $result = \external_api::clean_returnvalue(core_message_external::set_favourite_conversations_returns(), $result); 3591 $this->assertCount(0, $result); 3592 } 3593 3594 /** 3595 * Test confirming that a user can't favourite a conversation on behalf of another user. 3596 */ 3597 public function test_set_favourite_conversations_another_users_conversation() { 3598 $this->resetAfterTest(); 3599 3600 $user1 = self::getDataGenerator()->create_user(); 3601 $user2 = self::getDataGenerator()->create_user(); 3602 $user3 = self::getDataGenerator()->create_user(); 3603 3604 $this->setUser($user3); 3605 3606 // Now, create some conversations. 3607 $time = time(); 3608 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3609 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3610 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3611 3612 $this->send_message($user1, $user3, 'Booyah'); 3613 $this->send_message($user3, $user1, 'Whaaat?'); 3614 $this->send_message($user1, $user3, 'Nothing.'); 3615 3616 // Try to favourite conversation 1 for user 2, as user3. 3617 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3618 $this->expectException(\moodle_exception::class); 3619 $result = core_message_external::set_favourite_conversations($user2->id, [$conversation1]); 3620 } 3621 3622 /** 3623 * Test confirming that a user can't mark a conversation as their own favourite if it's a conversation they're not a member of. 3624 */ 3625 public function test_set_favourite_conversations_non_member() { 3626 $this->resetAfterTest(); 3627 3628 $user1 = self::getDataGenerator()->create_user(); 3629 $user2 = self::getDataGenerator()->create_user(); 3630 $user3 = self::getDataGenerator()->create_user(); 3631 3632 $this->setUser($user3); 3633 3634 // Now, create some conversations. 3635 $time = time(); 3636 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3637 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3638 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3639 3640 $this->send_message($user1, $user3, 'Booyah'); 3641 $this->send_message($user3, $user1, 'Whaaat?'); 3642 $this->send_message($user1, $user3, 'Nothing.'); 3643 3644 // Try to favourite conversation 1 as user 3. 3645 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3646 $conversation2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]); 3647 $this->expectException(\moodle_exception::class); 3648 $result = core_message_external::set_favourite_conversations($user3->id, [$conversation1]); 3649 } 3650 3651 /** 3652 * Test confirming that a user can't favourite a non-existent conversation. 3653 */ 3654 public function test_set_favourite_conversations_non_existent_conversation() { 3655 $this->resetAfterTest(); 3656 3657 $user1 = self::getDataGenerator()->create_user(); 3658 $this->setUser($user1); 3659 3660 // Try to favourite a non-existent conversation. 3661 $this->expectException(\moodle_exception::class); 3662 $result = core_message_external::set_favourite_conversations($user1->id, [0]); 3663 } 3664 3665 /** 3666 * Test confirming that a user can unset a favourite conversation, or list of favourite conversations. 3667 */ 3668 public function test_unset_favourite_conversations_basic() { 3669 $this->resetAfterTest(); 3670 3671 $user1 = self::getDataGenerator()->create_user(); 3672 $user2 = self::getDataGenerator()->create_user(); 3673 $user3 = self::getDataGenerator()->create_user(); 3674 $user4 = self::getDataGenerator()->create_user(); 3675 3676 $this->setUser($user1); 3677 3678 // Now, create some conversations. 3679 $time = time(); 3680 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3681 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3682 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3683 3684 $this->send_message($user1, $user3, 'Booyah'); 3685 $this->send_message($user3, $user1, 'Whaaat?'); 3686 $this->send_message($user1, $user3, 'Nothing.'); 3687 3688 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3689 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3690 3691 // Favourite 2 conversations as user 1. 3692 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3693 $conversation2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]); 3694 \core_message\api::set_favourite_conversation($conversation1, $user1->id); 3695 \core_message\api::set_favourite_conversation($conversation2, $user1->id); 3696 // Consider first conversations is self-conversation. 3697 $this->assertCount(3, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); 3698 3699 // Unset favourite self-conversation. 3700 $selfconversation = \core_message\api::get_self_conversation($user1->id); 3701 $result = core_message_external::unset_favourite_conversations($user1->id, [$selfconversation->id]); 3702 $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); 3703 3704 // Now, using the web service, unset the favourite conversations. 3705 $result = core_message_external::unset_favourite_conversations($user1->id, [$conversation1, $conversation2]); 3706 3707 // We need to execute the return values cleaning process to simulate the web service server. 3708 $result = \external_api::clean_returnvalue(core_message_external::unset_favourite_conversations_returns(), $result); 3709 $this->assertCount(0, $result); 3710 } 3711 3712 /** 3713 * Test confirming that a user can't unfavourite a conversation for another user. 3714 */ 3715 public function test_unset_favourite_conversations_another_users_conversation() { 3716 $this->resetAfterTest(); 3717 3718 $user1 = self::getDataGenerator()->create_user(); 3719 $user2 = self::getDataGenerator()->create_user(); 3720 $user3 = self::getDataGenerator()->create_user(); 3721 3722 $this->setUser($user3); 3723 3724 // Now, create some conversations. 3725 $time = time(); 3726 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3727 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3728 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3729 3730 $this->send_message($user1, $user3, 'Booyah'); 3731 $this->send_message($user3, $user1, 'Whaaat?'); 3732 $this->send_message($user1, $user3, 'Nothing.'); 3733 3734 // Favourite conversation 1 for user1. The current user ($USER) isn't checked for this action. 3735 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3736 \core_message\api::set_favourite_conversation($conversation1, $user1->id); 3737 // Consider first conversations is self-conversation. 3738 $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); 3739 3740 // Try to unfavourite conversation 1 for user 2, as user3. 3741 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3742 $this->expectException(\moodle_exception::class); 3743 $result = core_message_external::unset_favourite_conversations($user2->id, [$conversation1]); 3744 } 3745 3746 /** 3747 * Test confirming that a user can't unfavourite a non-existent conversation. 3748 */ 3749 public function test_unset_favourite_conversations_non_existent_conversation() { 3750 $this->resetAfterTest(); 3751 3752 $user1 = self::getDataGenerator()->create_user(); 3753 $this->setUser($user1); 3754 3755 // Try to unfavourite a non-existent conversation. 3756 $this->expectException(\moodle_exception::class); 3757 $result = core_message_external::unset_favourite_conversations($user1->id, [0]); 3758 } 3759 3760 /** 3761 * Helper to seed the database with initial state. 3762 */ 3763 protected function create_conversation_test_data() { 3764 // Create some users. 3765 $user1 = self::getDataGenerator()->create_user(); 3766 $user2 = self::getDataGenerator()->create_user(); 3767 $user3 = self::getDataGenerator()->create_user(); 3768 $user4 = self::getDataGenerator()->create_user(); 3769 3770 $time = 1; 3771 3772 // Create some conversations. We want: 3773 // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message. 3774 // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message. 3775 // 3) At least one of each type (group, individual) of which user1 IS NOT a member. 3776 // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering). 3777 // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member. 3778 3779 // Individual conversation, user1 is a member, last message from other user. 3780 $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3781 [$user1->id, $user2->id]); 3782 testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time); 3783 testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1); 3784 3785 // Individual conversation, user1 is a member, last message from user1. 3786 $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3787 [$user1->id, $user3->id]); 3788 testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2); 3789 testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3); 3790 3791 // Individual conversation, user1 is not a member. 3792 $ic3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3793 [$user2->id, $user3->id]); 3794 testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4); 3795 testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5); 3796 3797 // Group conversation, user1 is not a member. 3798 $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3799 [$user2->id, $user3->id, $user4->id], 'Project discussions'); 3800 testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6); 3801 testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7); 3802 3803 // Group conversation, user1 is a member, last message from another user. 3804 $gc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3805 [$user1->id, $user3->id, $user4->id], 'Group chat'); 3806 testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8); 3807 testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9); 3808 testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10); 3809 3810 // Group conversation, user1 is a member, last message from user1. 3811 $gc3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3812 [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!'); 3813 testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11); 3814 testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12); 3815 testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13); 3816 3817 // Empty group conversations (x2), user1 is a member. 3818 $gc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3819 [$user1->id, $user2->id, $user3->id], 'Empty group'); 3820 $gc5 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3821 [$user1->id, $user2->id, $user4->id], 'Another empty group'); 3822 3823 // Empty group conversation, user1 is NOT a member. 3824 $gc6 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3825 [$user2->id, $user3->id, $user4->id], 'Empty group 3'); 3826 3827 return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6]; 3828 } 3829 3830 /** 3831 * Test confirming the basic use of get_conversations, with no limits, nor type or favourite restrictions. 3832 */ 3833 public function test_get_conversations_no_restrictions() { 3834 $this->resetAfterTest(true); 3835 3836 // Get a bunch of conversations, some group, some individual and in different states. 3837 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 3838 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 3839 3840 // The user making the request. 3841 $this->setUser($user1); 3842 3843 // Get all conversations for user1. 3844 $result = core_message_external::get_conversations($user1->id); 3845 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3846 $conversations = $result['conversations']; 3847 3848 $selfconversation = \core_message\api::get_self_conversation($user1->id); 3849 3850 // Verify there are 7 conversations: 2 individual, 2 group with message, 2 group without messages 3851 // and a self-conversation. 3852 // The conversations with the most recent messages should be listed first, followed by the most newly created 3853 // conversations without messages. 3854 $this->assertCount(7, $conversations); 3855 $this->assertEquals($gc3->id, $conversations[0]['id']); 3856 $this->assertEquals($gc2->id, $conversations[1]['id']); 3857 $this->assertEquals($ic2->id, $conversations[2]['id']); 3858 $this->assertEquals($ic1->id, $conversations[3]['id']); 3859 $this->assertEquals($gc5->id, $conversations[4]['id']); 3860 $this->assertEquals($gc4->id, $conversations[5]['id']); 3861 $this->assertEquals($selfconversation->id, $conversations[6]['id']); 3862 3863 foreach ($conversations as $conv) { 3864 $this->assertArrayHasKey('id', $conv); 3865 $this->assertArrayHasKey('name', $conv); 3866 $this->assertArrayHasKey('subname', $conv); 3867 $this->assertArrayHasKey('imageurl', $conv); 3868 $this->assertArrayHasKey('type', $conv); 3869 $this->assertArrayHasKey('membercount', $conv); 3870 $this->assertArrayHasKey('isfavourite', $conv); 3871 $this->assertArrayHasKey('isread', $conv); 3872 $this->assertArrayHasKey('unreadcount', $conv); 3873 $this->assertArrayHasKey('members', $conv); 3874 foreach ($conv['members'] as $member) { 3875 $this->assertArrayHasKey('id', $member); 3876 $this->assertArrayHasKey('fullname', $member); 3877 $this->assertArrayHasKey('profileimageurl', $member); 3878 $this->assertArrayHasKey('profileimageurlsmall', $member); 3879 $this->assertArrayHasKey('isonline', $member); 3880 $this->assertArrayHasKey('showonlinestatus', $member); 3881 $this->assertArrayHasKey('isblocked', $member); 3882 $this->assertArrayHasKey('iscontact', $member); 3883 $this->assertArrayHasKey('isdeleted', $member); 3884 $this->assertArrayHasKey('canmessage', $member); 3885 $this->assertArrayHasKey('requirescontact', $member); 3886 $this->assertArrayHasKey('contactrequests', $member); 3887 } 3888 $this->assertArrayHasKey('messages', $conv); 3889 foreach ($conv['messages'] as $message) { 3890 $this->assertArrayHasKey('id', $message); 3891 $this->assertArrayHasKey('useridfrom', $message); 3892 $this->assertArrayHasKey('text', $message); 3893 $this->assertArrayHasKey('timecreated', $message); 3894 } 3895 } 3896 } 3897 3898 /** 3899 * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately. 3900 */ 3901 public function test_get_conversations_message_format() { 3902 $this->resetAfterTest(); 3903 3904 global $DB; 3905 // Create some users. 3906 $user1 = self::getDataGenerator()->create_user(); 3907 $user2 = self::getDataGenerator()->create_user(); 3908 3909 // Create conversation. 3910 $conversation = \core_message\api::create_conversation( 3911 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3912 [$user1->id, $user2->id] 3913 ); 3914 3915 // Send some messages back and forth. 3916 $time = 1; 3917 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1); 3918 $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2); 3919 $message = $DB->get_record('messages', ['id' => $mid]); 3920 3921 // The user in scope. 3922 $this->setUser($user1); 3923 3924 // Verify the format of the html message. 3925 $expectedmessagetext = message_format_message_text($message); 3926 $result = core_message_external::get_conversations($user1->id); 3927 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3928 $conversations = $result['conversations']; 3929 $messages = $conversations[0]['messages']; 3930 $this->assertEquals($expectedmessagetext, $messages[0]['text']); 3931 } 3932 3933 /** 3934 * Tests retrieving conversations with a limit and offset to ensure pagination works correctly. 3935 */ 3936 public function test_get_conversations_limit_offset() { 3937 $this->resetAfterTest(true); 3938 3939 // Get a bunch of conversations, some group, some individual and in different states. 3940 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 3941 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 3942 3943 // The user making the request. 3944 $this->setUser($user1); 3945 3946 // Get all conversations for user1. 3947 $result = core_message_external::get_conversations($user1->id, 0, 1); 3948 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3949 $conversations = $result['conversations']; 3950 3951 // Verify the first conversation. 3952 $this->assertCount(1, $conversations); 3953 $conversation = array_shift($conversations); 3954 $this->assertEquals($gc3->id, $conversation['id']); 3955 3956 // Verify the next conversation. 3957 $result = core_message_external::get_conversations($user1->id, 1, 1); 3958 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3959 $conversations = $result['conversations']; 3960 $this->assertCount(1, $conversations); 3961 $this->assertEquals($gc2->id, $conversations[0]['id']); 3962 3963 // Verify the next conversation. 3964 $result = core_message_external::get_conversations($user1->id, 2, 1); 3965 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3966 $conversations = $result['conversations']; 3967 $this->assertCount(1, $conversations); 3968 $this->assertEquals($ic2->id, $conversations[0]['id']); 3969 3970 // Skip one and get both empty conversations. 3971 $result = core_message_external::get_conversations($user1->id, 4, 2); 3972 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3973 $conversations = $result['conversations']; 3974 $this->assertCount(2, $conversations); 3975 $this->assertEquals($gc5->id, $conversations[0]['id']); 3976 $this->assertEmpty($conversations[0]['messages']); 3977 $this->assertEquals($gc4->id, $conversations[1]['id']); 3978 $this->assertEmpty($conversations[1]['messages']); 3979 3980 // Ask for an offset that doesn't exist and verify no conversations are returned. 3981 $conversations = \core_message\api::get_conversations($user1->id, 10, 1); 3982 $this->assertCount(0, $conversations); 3983 } 3984 3985 /** 3986 * Test verifying the type filtering behaviour of the get_conversations external method. 3987 */ 3988 public function test_get_conversations_type_filter() { 3989 $this->resetAfterTest(true); 3990 3991 // Get a bunch of conversations, some group, some individual and in different states. 3992 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 3993 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 3994 3995 // The user making the request. 3996 $this->setUser($user1); 3997 3998 // Verify we can ask for only individual conversations. 3999 $result = core_message_external::get_conversations($user1->id, 0, 20, 4000 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL); 4001 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4002 $conversations = $result['conversations']; 4003 $this->assertCount(2, $conversations); 4004 4005 // Verify we can ask for only group conversations. 4006 $result = core_message_external::get_conversations($user1->id, 0, 20, 4007 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP); 4008 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4009 $conversations = $result['conversations']; 4010 $this->assertCount(4, $conversations); 4011 4012 // Verify an exception is thrown if an unrecognized type is specified. 4013 $this->expectException(\moodle_exception::class); 4014 core_message_external::get_conversations($user1->id, 0, 20, 0); 4015 } 4016 4017 /** 4018 * Tests retrieving conversations when a 'self' conversation exists. 4019 */ 4020 public function test_get_conversations_self_conversations() { 4021 global $DB; 4022 $this->resetAfterTest(); 4023 4024 // Create a conversation between one user and themself. 4025 $user1 = self::getDataGenerator()->create_user(); 4026 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, 4027 [$user1->id]); 4028 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Test message to self!'); 4029 4030 // Verify we are in a 'self' conversation state. 4031 $members = $DB->get_records('message_conversation_members', ['conversationid' => $conversation->id]); 4032 $this->assertCount(1, $members); 4033 $member = array_pop($members); 4034 $this->assertEquals($user1->id, $member->userid); 4035 4036 // Verify this conversation is returned by the method. 4037 $this->setUser($user1); 4038 $result = core_message_external::get_conversations($user1->id, 0, 20); 4039 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4040 $conversations = $result['conversations']; 4041 $this->assertCount(1, $conversations); 4042 } 4043 4044 /** 4045 * Tests retrieving conversations when a conversation contains a deleted user. 4046 */ 4047 public function test_get_conversations_deleted_user() { 4048 $this->resetAfterTest(true); 4049 4050 // Get a bunch of conversations, some group, some individual and in different states. 4051 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4052 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4053 4054 // The user making the request. 4055 $this->setUser($user1); 4056 4057 $selfconversation = \core_message\api::get_self_conversation($user1->id); 4058 4059 // Delete the second user and retrieve the conversations. 4060 // We should have 6 still, as conversations with soft-deleted users are still returned. 4061 // Group conversations are also present, albeit with less members. 4062 delete_user($user2); 4063 $result = core_message_external::get_conversations($user1->id); 4064 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4065 $conversations = $result['conversations']; 4066 $this->assertCount(7, $conversations); 4067 $this->assertEquals($gc3->id, $conversations[0]['id']); 4068 $this->assertcount(1, $conversations[0]['members']); 4069 $this->assertEquals($gc2->id, $conversations[1]['id']); 4070 $this->assertcount(1, $conversations[1]['members']); 4071 $this->assertEquals($ic2->id, $conversations[2]['id']); 4072 $this->assertEquals($ic1->id, $conversations[3]['id']); 4073 $this->assertEquals($gc5->id, $conversations[4]['id']); 4074 $this->assertEquals($gc4->id, $conversations[5]['id']); 4075 $this->assertEquals($selfconversation->id, $conversations[6]['id']); 4076 4077 // Delete a user from a group conversation where that user had sent the most recent message. 4078 // This user will still be present in the members array, as will the message in the messages array. 4079 delete_user($user4); 4080 $result = core_message_external::get_conversations($user1->id); 4081 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4082 $conversations = $result['conversations']; 4083 $this->assertCount(7, $conversations); 4084 $this->assertEquals($gc2->id, $conversations[1]['id']); 4085 $this->assertcount(1, $conversations[1]['members']); 4086 $this->assertEquals($user4->id, $conversations[1]['members'][0]['id']); 4087 $this->assertcount(1, $conversations[1]['messages']); 4088 $this->assertEquals($user4->id, $conversations[1]['messages'][0]['useridfrom']); 4089 4090 // Delete the third user and retrieve the conversations. 4091 // We should have 7 still (including self-conversation), as conversations with soft-deleted users are still returned. 4092 // Group conversations are also present, albeit with less members. 4093 delete_user($user3); 4094 $result = core_message_external::get_conversations($user1->id); 4095 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4096 $conversations = $result['conversations']; 4097 $this->assertCount(7, $conversations); 4098 $this->assertEquals($gc3->id, $conversations[0]['id']); 4099 $this->assertcount(1, $conversations[0]['members']); 4100 $this->assertEquals($gc2->id, $conversations[1]['id']); 4101 $this->assertcount(1, $conversations[1]['members']); 4102 $this->assertEquals($ic2->id, $conversations[2]['id']); 4103 $this->assertEquals($ic1->id, $conversations[3]['id']); 4104 $this->assertEquals($gc5->id, $conversations[4]['id']); 4105 $this->assertEquals($gc4->id, $conversations[5]['id']); 4106 $this->assertEquals($selfconversation->id, $conversations[6]['id']); 4107 } 4108 4109 /** 4110 * Tests retrieving conversations when a conversation contains a deleted from the database user. 4111 */ 4112 public function test_get_conversations_deleted_user_from_database() { 4113 global $DB; 4114 4115 $this->resetAfterTest(); 4116 4117 $user1 = self::getDataGenerator()->create_user(); 4118 $user2 = self::getDataGenerator()->create_user(); 4119 $user3 = self::getDataGenerator()->create_user(); 4120 4121 $conversation1 = \core_message\api::create_conversation( 4122 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4123 [ 4124 $user1->id, 4125 $user2->id 4126 ], 4127 'Individual conversation 1' 4128 ); 4129 4130 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'A'); 4131 testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'B'); 4132 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'C'); 4133 4134 $conversation2 = \core_message\api::create_conversation( 4135 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4136 [ 4137 $user1->id, 4138 $user3->id 4139 ], 4140 'Individual conversation 2' 4141 ); 4142 4143 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'A'); 4144 testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'B'); 4145 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'C'); 4146 4147 $this->setUser($user1); 4148 4149 // Delete the second user (from DB as well as this could happen in the past). 4150 delete_user($user2); 4151 $DB->delete_records('user', ['id' => $user2->id]); 4152 $result = core_message_external::get_conversations($user1->id, 0, 20, 1, false); 4153 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4154 4155 $conversation = $result['conversations']; 4156 4157 $this->assertCount(1, $conversation); 4158 4159 $conversation = reset($conversation); 4160 4161 $this->assertEquals($conversation2->id, $conversation['id']); 4162 } 4163 4164 /** 4165 * Test verifying the behaviour of get_conversations() when fetching favourite conversations. 4166 */ 4167 public function test_get_conversations_favourite_conversations() { 4168 $this->resetAfterTest(true); 4169 4170 // Get a bunch of conversations, some group, some individual and in different states. 4171 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4172 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4173 4174 // The user making the request. 4175 $this->setUser($user1); 4176 4177 // Unset favourite self-conversation. 4178 $selfconversation = \core_message\api::get_self_conversation($user1->id); 4179 \core_message\api::unset_favourite_conversation($selfconversation->id, $user1->id); 4180 4181 // Try to get ONLY favourite conversations, when no favourites exist. 4182 $result = core_message_external::get_conversations($user1->id, 0, 20, null, true); 4183 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4184 $conversations = $result['conversations']; 4185 $this->assertEquals([], $conversations); 4186 4187 // Try to get NO favourite conversations, when no favourites exist. 4188 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4189 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4190 $conversations = $result['conversations']; 4191 // Consider first conversations is self-conversation. 4192 $this->assertCount(7, $conversations); 4193 4194 // Mark a few conversations as favourites. 4195 \core_message\api::set_favourite_conversation($ic1->id, $user1->id); 4196 \core_message\api::set_favourite_conversation($gc2->id, $user1->id); 4197 \core_message\api::set_favourite_conversation($gc5->id, $user1->id); 4198 4199 // Get the conversations, first with no restrictions, confirming the favourite status of the conversations. 4200 $result = core_message_external::get_conversations($user1->id); 4201 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4202 $conversations = $result['conversations']; 4203 $this->assertCount(7, $conversations); 4204 foreach ($conversations as $conv) { 4205 if (in_array($conv['id'], [$ic1->id, $gc2->id, $gc5->id])) { 4206 $this->assertTrue($conv['isfavourite']); 4207 } 4208 } 4209 4210 // Now, get ONLY favourite conversations. 4211 $result = core_message_external::get_conversations($user1->id, 0, 20, null, true); 4212 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4213 $conversations = $result['conversations']; 4214 $this->assertCount(3, $conversations); 4215 foreach ($conversations as $conv) { 4216 $this->assertTrue($conv['isfavourite']); 4217 } 4218 4219 // Now, try ONLY favourites of type 'group'. 4220 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 4221 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true); 4222 $this->assertCount(2, $conversations); 4223 foreach ($conversations as $conv) { 4224 $this->assertTrue($conv->isfavourite); 4225 } 4226 4227 // And NO favourite conversations. 4228 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4229 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4230 $conversations = $result['conversations']; 4231 $this->assertCount(4, $conversations); 4232 foreach ($conversations as $conv) { 4233 $this->assertFalse($conv['isfavourite']); 4234 } 4235 } 4236 4237 /** 4238 * Test verifying that group linked conversations are returned and contain a subname matching the course name. 4239 */ 4240 public function test_get_conversations_group_linked() { 4241 $this->resetAfterTest(); 4242 global $CFG, $DB; 4243 4244 // Create some users. 4245 $user1 = self::getDataGenerator()->create_user(); 4246 $user2 = self::getDataGenerator()->create_user(); 4247 $user3 = self::getDataGenerator()->create_user(); 4248 4249 $course1 = $this->getDataGenerator()->create_course(); 4250 4251 // Create a group with a linked conversation. 4252 $this->setAdminUser(); 4253 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4254 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4255 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4256 $group1 = $this->getDataGenerator()->create_group([ 4257 'courseid' => $course1->id, 4258 'enablemessaging' => 1, 4259 'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png' 4260 ]); 4261 4262 // Add users to group1. 4263 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); 4264 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); 4265 4266 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4267 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4268 $conversations = $result['conversations']; 4269 4270 $this->assertEquals(2, $conversations[0]['membercount']); 4271 $this->assertEquals($course1->shortname, $conversations[0]['subname']); 4272 $groupimageurl = get_group_picture_url($group1, $group1->courseid, true); 4273 $this->assertEquals($groupimageurl, $conversations[0]['imageurl']); 4274 4275 // Now, disable the conversation linked to the group and verify it's no longer returned. 4276 $DB->set_field('message_conversations', 'enabled', 0, ['id' => $conversations[0]['id']]); 4277 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4278 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4279 $conversations = $result['conversations']; 4280 $this->assertCount(0, $conversations); 4281 } 4282 4283 /** 4284 * Test that group conversations containing MathJax don't break the WebService. 4285 */ 4286 public function test_get_conversations_group_with_mathjax() { 4287 $this->resetAfterTest(true); 4288 $this->setAdminUser(); 4289 4290 // Enable MathJax filter in content and headings. 4291 $this->configure_filters([ 4292 ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true], 4293 ]); 4294 4295 // Create some users, a course and a group with a linked conversation. 4296 $user1 = self::getDataGenerator()->create_user(); 4297 $user2 = self::getDataGenerator()->create_user(); 4298 4299 $coursename = 'Course $$(a+b)=2$$'; 4300 $groupname = 'Group $$(a+b)=2$$'; 4301 $course1 = $this->getDataGenerator()->create_course(['shortname' => $coursename]); 4302 4303 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4304 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4305 $group1 = $this->getDataGenerator()->create_group([ 4306 'name' => $groupname, 4307 'courseid' => $course1->id, 4308 'enablemessaging' => 1, 4309 ]); 4310 4311 // Add users to group1. 4312 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); 4313 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); 4314 4315 // Call the WebService. 4316 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4317 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4318 $conversations = $result['conversations']; 4319 4320 // Format original data. 4321 $coursecontext = \context_course::instance($course1->id); 4322 $coursename = external_format_string($coursename, $coursecontext->id); 4323 $groupname = external_format_string($groupname, $coursecontext->id); 4324 4325 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $conversations[0]['name']); 4326 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $conversations[0]['subname']); 4327 $this->assertEquals($groupname, $conversations[0]['name']); 4328 $this->assertEquals($coursename, $conversations[0]['subname']); 4329 } 4330 4331 /** 4332 * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this 4333 * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want 4334 * to confirm this happens. 4335 */ 4336 public function test_get_conversations_user_in_group_and_individual_chat() { 4337 $this->resetAfterTest(); 4338 4339 $user1 = self::getDataGenerator()->create_user(); 4340 $user2 = self::getDataGenerator()->create_user(); 4341 $user3 = self::getDataGenerator()->create_user(); 4342 4343 $conversation = \core_message\api::create_conversation( 4344 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4345 [ 4346 $user1->id, 4347 $user2->id 4348 ], 4349 'Individual conversation' 4350 ); 4351 4352 testhelper::send_fake_message_to_conversation($user1, $conversation->id); 4353 4354 $conversation = \core_message\api::create_conversation( 4355 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4356 [ 4357 $user1->id, 4358 $user2->id, 4359 ], 4360 'Group conversation' 4361 ); 4362 4363 testhelper::send_fake_message_to_conversation($user1, $conversation->id); 4364 4365 \core_message\api::create_contact_request($user1->id, $user2->id); 4366 \core_message\api::create_contact_request($user1->id, $user3->id); 4367 4368 $this->setUser($user2); 4369 $result = core_message_external::get_conversations($user2->id); 4370 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4371 $conversations = $result['conversations']; 4372 4373 $groupconversation = array_shift($conversations); 4374 $individualconversation = array_shift($conversations); 4375 4376 $this->assertEquals('Group conversation', $groupconversation['name']); 4377 $this->assertEquals('Individual conversation', $individualconversation['name']); 4378 4379 $this->assertCount(1, $groupconversation['members']); 4380 $this->assertCount(1, $individualconversation['members']); 4381 4382 $groupmember = reset($groupconversation['members']); 4383 $this->assertNull($groupmember['requirescontact']); 4384 $this->assertNull($groupmember['canmessage']); 4385 $this->assertEmpty($groupmember['contactrequests']); 4386 4387 $individualmember = reset($individualconversation['members']); 4388 $this->assertNotNull($individualmember['requirescontact']); 4389 $this->assertNotNull($individualmember['canmessage']); 4390 $this->assertNotEmpty($individualmember['contactrequests']); 4391 } 4392 4393 /** 4394 * Test verifying get_conversations identifies if a conversation is muted or not. 4395 */ 4396 public function test_get_conversations_some_muted() { 4397 $this->resetAfterTest(); 4398 4399 // Create some users. 4400 $user1 = self::getDataGenerator()->create_user(); 4401 $user2 = self::getDataGenerator()->create_user(); 4402 $user3 = self::getDataGenerator()->create_user(); 4403 4404 $conversation1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4405 [$user1->id, $user2->id]); 4406 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'Message 1'); 4407 testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'Message 2'); 4408 \core_message\api::mute_conversation($user1->id, $conversation1->id); 4409 4410 $conversation2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4411 [$user1->id, $user3->id]); 4412 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Message 1'); 4413 testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Message 2'); 4414 4415 $conversation3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4416 [$user1->id, $user2->id]); 4417 \core_message\api::mute_conversation($user1->id, $conversation3->id); 4418 4419 $conversation4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4420 [$user1->id, $user3->id]); 4421 4422 $this->setUser($user1); 4423 $result = core_message_external::get_conversations($user1->id); 4424 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4425 $conversations = $result['conversations']; 4426 4427 usort($conversations, function($first, $second){ 4428 return $first['id'] <=> $second['id']; 4429 }); 4430 4431 $selfconversation = array_shift($conversations); 4432 $conv1 = array_shift($conversations); 4433 $conv2 = array_shift($conversations); 4434 $conv3 = array_shift($conversations); 4435 $conv4 = array_shift($conversations); 4436 4437 $this->assertTrue($conv1['ismuted']); 4438 $this->assertFalse($conv2['ismuted']); 4439 $this->assertTrue($conv3['ismuted']); 4440 $this->assertFalse($conv4['ismuted']); 4441 } 4442 4443 /** 4444 * Test returning members in a conversation with no contact requests. 4445 */ 4446 public function test_get_conversation_members_messaging_disabled() { 4447 global $CFG; 4448 4449 $this->resetAfterTest(); 4450 4451 $CFG->messaging = 0; 4452 4453 $this->expectException('moodle_exception'); 4454 core_message_external::get_conversation_members(1, 2); 4455 } 4456 4457 /** 4458 * Test returning members in a conversation with no contact requests. 4459 */ 4460 public function test_get_conversation_members_wrong_user() { 4461 $this->resetAfterTest(); 4462 4463 $user1 = self::getDataGenerator()->create_user(); 4464 $user2 = self::getDataGenerator()->create_user(); 4465 4466 $this->setUser($user2); 4467 4468 $this->expectException('moodle_exception'); 4469 core_message_external::get_conversation_members($user1->id, 2); 4470 } 4471 4472 /** 4473 * Test returning members in a conversation with no contact requests. 4474 */ 4475 public function test_get_conversation_members() { 4476 $this->resetAfterTest(); 4477 4478 $lastaccess = new \stdClass(); 4479 $lastaccess->lastaccess = time(); 4480 4481 $user1 = self::getDataGenerator()->create_user($lastaccess); 4482 $user2 = self::getDataGenerator()->create_user(); 4483 $user3 = self::getDataGenerator()->create_user(); 4484 4485 // This user will not be in the conversation, but a contact request will exist for them. 4486 $user4 = self::getDataGenerator()->create_user(); 4487 4488 // Add some contact requests. 4489 \core_message\api::create_contact_request($user1->id, $user3->id); 4490 \core_message\api::create_contact_request($user1->id, $user4->id); 4491 \core_message\api::create_contact_request($user2->id, $user3->id); 4492 4493 // User 1 and 2 are already contacts. 4494 \core_message\api::add_contact($user1->id, $user2->id); 4495 4496 // User 1 has blocked user 3. 4497 \core_message\api::block_user($user1->id, $user3->id); 4498 4499 $conversation = \core_message\api::create_conversation( 4500 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4501 [ 4502 $user1->id, 4503 $user2->id, 4504 $user3->id 4505 ] 4506 ); 4507 $conversationid = $conversation->id; 4508 4509 $this->setAdminUser(); 4510 4511 $members = core_message_external::get_conversation_members($user1->id, $conversationid, false); 4512 \external_api::clean_returnvalue(core_message_external::get_conversation_members_returns(), $members); 4513 4514 // Sort them by id. 4515 ksort($members); 4516 $this->assertCount(3, $members); 4517 $member1 = array_shift($members); 4518 $member2 = array_shift($members); 4519 $member3 = array_shift($members); 4520 4521 // Confirm the standard fields are OK. 4522 $this->assertEquals($user1->id, $member1->id); 4523 $this->assertEquals(fullname($user1), $member1->fullname); 4524 $this->assertEquals(true, $member1->isonline); 4525 $this->assertEquals(true, $member1->showonlinestatus); 4526 $this->assertEquals(false, $member1->iscontact); 4527 $this->assertEquals(false, $member1->isblocked); 4528 $this->assertObjectHasAttribute('contactrequests', $member1); 4529 $this->assertEmpty($member1->contactrequests); 4530 4531 $this->assertEquals($user2->id, $member2->id); 4532 $this->assertEquals(fullname($user2), $member2->fullname); 4533 $this->assertEquals(false, $member2->isonline); 4534 $this->assertEquals(true, $member2->showonlinestatus); 4535 $this->assertEquals(true, $member2->iscontact); 4536 $this->assertEquals(false, $member2->isblocked); 4537 $this->assertObjectHasAttribute('contactrequests', $member2); 4538 $this->assertEmpty($member2->contactrequests); 4539 4540 $this->assertEquals($user3->id, $member3->id); 4541 $this->assertEquals(fullname($user3), $member3->fullname); 4542 $this->assertEquals(false, $member3->isonline); 4543 $this->assertEquals(true, $member3->showonlinestatus); 4544 $this->assertEquals(false, $member3->iscontact); 4545 $this->assertEquals(true, $member3->isblocked); 4546 $this->assertObjectHasAttribute('contactrequests', $member3); 4547 $this->assertEmpty($member3->contactrequests); 4548 } 4549 4550 /** 4551 * Test returning members in a conversation with contact requests. 4552 */ 4553 public function test_get_conversation_members_with_contact_requests() { 4554 $this->resetAfterTest(); 4555 4556 $lastaccess = new \stdClass(); 4557 $lastaccess->lastaccess = time(); 4558 4559 $user1 = self::getDataGenerator()->create_user($lastaccess); 4560 $user2 = self::getDataGenerator()->create_user(); 4561 $user3 = self::getDataGenerator()->create_user(); 4562 4563 // This user will not be in the conversation, but a contact request will exist for them. 4564 $user4 = self::getDataGenerator()->create_user(); 4565 4566 // Add some contact requests. 4567 \core_message\api::create_contact_request($user1->id, $user2->id); 4568 \core_message\api::create_contact_request($user1->id, $user3->id); 4569 \core_message\api::create_contact_request($user1->id, $user4->id); 4570 \core_message\api::create_contact_request($user2->id, $user3->id); 4571 4572 // User 1 and 2 are already contacts. 4573 \core_message\api::add_contact($user1->id, $user2->id); 4574 // User 1 has blocked user 3. 4575 \core_message\api::block_user($user1->id, $user3->id); 4576 4577 $conversation = \core_message\api::create_conversation( 4578 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4579 [ 4580 $user1->id, 4581 $user2->id, 4582 $user3->id 4583 ] 4584 ); 4585 $conversationid = $conversation->id; 4586 4587 $this->setAdminUser(); 4588 4589 $members = core_message_external::get_conversation_members($user1->id, $conversationid, true); 4590 \external_api::clean_returnvalue(core_message_external::get_conversation_members_returns(), $members); 4591 4592 // Sort them by id. 4593 ksort($members); 4594 $this->assertCount(3, $members); 4595 $member1 = array_shift($members); 4596 $member2 = array_shift($members); 4597 $member3 = array_shift($members); 4598 4599 // Confirm the standard fields are OK. 4600 $this->assertEquals($user1->id, $member1->id); 4601 $this->assertEquals(fullname($user1), $member1->fullname); 4602 $this->assertEquals(true, $member1->isonline); 4603 $this->assertEquals(true, $member1->showonlinestatus); 4604 $this->assertEquals(false, $member1->iscontact); 4605 $this->assertEquals(false, $member1->isblocked); 4606 $this->assertCount(2, $member1->contactrequests); 4607 4608 $this->assertEquals($user2->id, $member2->id); 4609 $this->assertEquals(fullname($user2), $member2->fullname); 4610 $this->assertEquals(false, $member2->isonline); 4611 $this->assertEquals(true, $member2->showonlinestatus); 4612 $this->assertEquals(true, $member2->iscontact); 4613 $this->assertEquals(false, $member2->isblocked); 4614 $this->assertCount(1, $member2->contactrequests); 4615 4616 $this->assertEquals($user3->id, $member3->id); 4617 $this->assertEquals(fullname($user3), $member3->fullname); 4618 $this->assertEquals(false, $member3->isonline); 4619 $this->assertEquals(true, $member3->showonlinestatus); 4620 $this->assertEquals(false, $member3->iscontact); 4621 $this->assertEquals(true, $member3->isblocked); 4622 $this->assertCount(1, $member3->contactrequests); 4623 4624 // Confirm the contact requests are OK. 4625 $request1 = array_shift($member1->contactrequests); 4626 $request2 = array_shift($member1->contactrequests); 4627 4628 $this->assertEquals($user1->id, $request1->userid); 4629 $this->assertEquals($user2->id, $request1->requesteduserid); 4630 4631 $this->assertEquals($user1->id, $request2->userid); 4632 $this->assertEquals($user3->id, $request2->requesteduserid); 4633 4634 $request1 = array_shift($member2->contactrequests); 4635 4636 $this->assertEquals($user1->id, $request1->userid); 4637 $this->assertEquals($user2->id, $request1->requesteduserid); 4638 4639 $request1 = array_shift($member3->contactrequests); 4640 4641 $this->assertEquals($user1->id, $request1->userid); 4642 $this->assertEquals($user3->id, $request1->requesteduserid); 4643 } 4644 4645 /** 4646 * Test returning members in a conversation when you are not a member. 4647 */ 4648 public function test_get_conversation_members_not_a_member() { 4649 $this->resetAfterTest(); 4650 4651 $user1 = self::getDataGenerator()->create_user(); 4652 $user2 = self::getDataGenerator()->create_user(); 4653 4654 // This user will not be in the conversation. 4655 $user3 = self::getDataGenerator()->create_user(); 4656 4657 $conversation = \core_message\api::create_conversation( 4658 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4659 [ 4660 $user1->id, 4661 $user2->id, 4662 ] 4663 ); 4664 $conversationid = $conversation->id; 4665 4666 $this->setUser($user3); 4667 4668 $this->expectException('moodle_exception'); 4669 core_message_external::get_conversation_members($user3->id, $conversationid); 4670 } 4671 4672 /** 4673 * Test verifying multiple messages can be sent to an individual conversation. 4674 */ 4675 public function test_send_messages_to_conversation_individual() { 4676 $this->resetAfterTest(true); 4677 4678 // Get a bunch of conversations, some group, some individual and in different states. 4679 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4680 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4681 4682 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4683 $course1 = $this->getDataGenerator()->create_course(); 4684 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4685 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4686 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4687 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4688 4689 // The user making the request. 4690 $this->setUser($user1); 4691 4692 // Try to send a message as user1 to a conversation user1 is a a part of. 4693 $messages = [ 4694 [ 4695 'text' => 'a message from user 1', 4696 'textformat' => FORMAT_MOODLE 4697 ], 4698 [ 4699 'text' => 'another message from user 1', 4700 'textformat' => FORMAT_MOODLE 4701 ], 4702 ]; 4703 // Redirect messages. 4704 // This marks messages as read, but we can still observe and verify the number of conversation recipients, 4705 // based on the message_viewed events generated as part of marking the message as read for each user. 4706 $this->preventResetByRollback(); 4707 $sink = $this->redirectMessages(); 4708 $writtenmessages = core_message_external::send_messages_to_conversation($ic1->id, $messages); 4709 4710 \external_api::clean_returnvalue(core_message_external::send_messages_to_conversation_returns(), $writtenmessages); 4711 4712 $this->assertCount(2, $writtenmessages); 4713 $this->assertObjectHasAttribute('id', $writtenmessages[0]); 4714 $this->assertEquals($user1->id, $writtenmessages[0]->useridfrom); 4715 $this->assertEquals('<p>a message from user 1</p>', $writtenmessages[0]->text); 4716 $this->assertNotEmpty($writtenmessages[0]->timecreated); 4717 4718 $this->assertObjectHasAttribute('id', $writtenmessages[1]); 4719 $this->assertEquals($user1->id, $writtenmessages[1]->useridfrom); 4720 $this->assertEquals('<p>another message from user 1</p>', $writtenmessages[1]->text); 4721 $this->assertNotEmpty($writtenmessages[1]->timecreated); 4722 } 4723 4724 /** 4725 * Test verifying multiple messages can be sent to an group conversation. 4726 */ 4727 public function test_send_messages_to_conversation_group() { 4728 $this->resetAfterTest(true); 4729 4730 // Get a bunch of conversations, some group, some individual and in different states. 4731 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4732 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4733 4734 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4735 $course1 = $this->getDataGenerator()->create_course(); 4736 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4737 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4738 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4739 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4740 4741 // The user making the request. 4742 $this->setUser($user1); 4743 4744 // Try to send a message as user1 to a conversation user1 is a a part of. 4745 $messages = [ 4746 [ 4747 'text' => 'a message from user 1 to group conv', 4748 'textformat' => FORMAT_MOODLE 4749 ], 4750 [ 4751 'text' => 'another message from user 1 to group conv', 4752 'textformat' => FORMAT_MOODLE 4753 ], 4754 ]; 4755 // Redirect messages. 4756 // This marks messages as read, but we can still observe and verify the number of conversation recipients, 4757 // based on the message_viewed events generated as part of marking the message as read for each user. 4758 $this->preventResetByRollback(); 4759 $sink = $this->redirectMessages(); 4760 $writtenmessages = core_message_external::send_messages_to_conversation($gc2->id, $messages); 4761 4762 \external_api::clean_returnvalue(core_message_external::send_messages_to_conversation_returns(), $writtenmessages); 4763 4764 $this->assertCount(2, $writtenmessages); 4765 $this->assertObjectHasAttribute('id', $writtenmessages[0]); 4766 $this->assertEquals($user1->id, $writtenmessages[0]->useridfrom); 4767 $this->assertEquals('<p>a message from user 1 to group conv</p>', $writtenmessages[0]->text); 4768 $this->assertNotEmpty($writtenmessages[0]->timecreated); 4769 4770 $this->assertObjectHasAttribute('id', $writtenmessages[1]); 4771 $this->assertEquals($user1->id, $writtenmessages[1]->useridfrom); 4772 $this->assertEquals('<p>another message from user 1 to group conv</p>', $writtenmessages[1]->text); 4773 $this->assertNotEmpty($writtenmessages[1]->timecreated); 4774 } 4775 4776 /** 4777 * Test verifying multiple messages can not be sent to a non existent conversation. 4778 */ 4779 public function test_send_messages_to_conversation_non_existent_conversation() { 4780 $this->resetAfterTest(true); 4781 4782 // Get a bunch of conversations, some group, some individual and in different states. 4783 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4784 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4785 4786 // The user making the request. 4787 $this->setUser($user1); 4788 4789 // Try to send a message as user1 to a conversation user1 is a a part of. 4790 $messages = [ 4791 [ 4792 'text' => 'a message from user 1', 4793 'textformat' => FORMAT_MOODLE 4794 ], 4795 [ 4796 'text' => 'another message from user 1', 4797 'textformat' => FORMAT_MOODLE 4798 ], 4799 ]; 4800 $this->expectException(\moodle_exception::class); 4801 $writtenmessages = core_message_external::send_messages_to_conversation(0, $messages); 4802 } 4803 4804 /** 4805 * Test verifying multiple messages can not be sent to a conversation by a non-member. 4806 */ 4807 public function test_send_messages_to_conversation_non_member() { 4808 $this->resetAfterTest(true); 4809 4810 // Get a bunch of conversations, some group, some individual and in different states. 4811 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4812 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4813 4814 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4815 $course1 = $this->getDataGenerator()->create_course(); 4816 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4817 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4818 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4819 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4820 4821 // The user making the request. This user is not a member of group conversation 1 (gc1). 4822 $this->setUser($user1); 4823 4824 // Try to send a message as user1 to a conversation user1 is a a part of. 4825 $messages = [ 4826 [ 4827 'text' => 'a message from user 1 to group conv', 4828 'textformat' => FORMAT_MOODLE 4829 ], 4830 [ 4831 'text' => 'another message from user 1 to group conv', 4832 'textformat' => FORMAT_MOODLE 4833 ], 4834 ]; 4835 $this->expectException(\moodle_exception::class); 4836 $writtenmessages = core_message_external::send_messages_to_conversation($gc1->id, $messages); 4837 } 4838 4839 /** 4840 * Test verifying a to long message can not be sent to a conversation. 4841 */ 4842 public function test_send_messages_to_conversation_long_text() { 4843 $this->resetAfterTest(true); 4844 4845 // Get a bunch of conversations, some group, some individual and in different states. 4846 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4847 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4848 4849 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4850 $course1 = $this->getDataGenerator()->create_course(); 4851 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4852 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4853 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4854 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4855 4856 // The user making the request. 4857 $this->setUser($user1); 4858 4859 // Try to send a message as user1 to a conversation user1 is a a part of. 4860 $messages = [ 4861 [ 4862 'text' => str_repeat("M", \core_message\api::MESSAGE_MAX_LENGTH + 100), 4863 'textformat' => FORMAT_MOODLE 4864 ], 4865 ]; 4866 4867 $this->expectException(\moodle_exception::class); 4868 $writtenmessages = core_message_external::send_messages_to_conversation($gc2->id, $messages); 4869 } 4870 4871 /** 4872 * Test getting a conversation that doesn't exist. 4873 */ 4874 public function test_get_conversation_no_conversation() { 4875 $this->resetAfterTest(); 4876 4877 $user1 = self::getDataGenerator()->create_user(); 4878 $user2 = self::getDataGenerator()->create_user(); 4879 4880 $name = 'lol conversation'; 4881 $conversation = \core_message\api::create_conversation( 4882 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4883 [ 4884 $user1->id, 4885 $user2->id, 4886 ], 4887 $name 4888 ); 4889 $conversationid = $conversation->id; 4890 4891 $this->setUser($user1); 4892 4893 $this->expectException('moodle_exception'); 4894 $conv = core_message_external::get_conversation($user1->id, $conversationid + 1); 4895 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4896 } 4897 4898 /** 4899 * Test verifying that the correct favourite information is returned for a non-linked converastion at user context. 4900 */ 4901 public function test_get_conversation_favourited() { 4902 $this->resetAfterTest(); 4903 4904 $user1 = self::getDataGenerator()->create_user(); 4905 $user2 = self::getDataGenerator()->create_user(); 4906 4907 // Create a conversation between the 2 users. 4908 $conversation = \core_message\api::create_conversation( 4909 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4910 [ 4911 $user1->id, 4912 $user2->id, 4913 ], 4914 'An individual conversation' 4915 ); 4916 4917 // Favourite the conversation as user 1 only. 4918 \core_message\api::set_favourite_conversation($conversation->id, $user1->id); 4919 4920 // Get the conversation for user1 and confirm it's favourited. 4921 $this->setUser($user1); 4922 $conv = core_message_external::get_conversation($user1->id, $conversation->id); 4923 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4924 $this->assertTrue($conv['isfavourite']); 4925 4926 // Get the conversation for user2 and confirm it's NOT favourited. 4927 $this->setUser($user2); 4928 $conv = core_message_external::get_conversation($user2->id, $conversation->id); 4929 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4930 $this->assertFalse($conv['isfavourite']); 4931 } 4932 4933 /** 4934 * Test verifying that the correct favourite information is returned for a group-linked conversation at course context. 4935 */ 4936 public function test_get_conversation_favourited_group_linked() { 4937 $this->resetAfterTest(); 4938 global $DB; 4939 4940 $user1 = self::getDataGenerator()->create_user(); 4941 $user2 = self::getDataGenerator()->create_user(); 4942 $user3 = self::getDataGenerator()->create_user(); 4943 4944 $course1 = $this->getDataGenerator()->create_course(); 4945 $course1context = \context_course::instance($course1->id); 4946 4947 // Create a group with a linked conversation and a valid image. 4948 $this->setAdminUser(); 4949 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4950 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4951 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4952 $group1 = $this->getDataGenerator()->create_group([ 4953 'courseid' => $course1->id, 4954 'enablemessaging' => 1 4955 ]); 4956 4957 // Add users to group1. 4958 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); 4959 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); 4960 4961 // Verify that the conversation is a group linked conversation in the course context. 4962 $conversationrecord = $DB->get_record('message_conversations', ['component' => 'core_group', 'itemtype' => 'groups']); 4963 $this->assertEquals($course1context->id, $conversationrecord->contextid); 4964 4965 // Favourite the conversation as user 1 only. 4966 \core_message\api::set_favourite_conversation($conversationrecord->id, $user1->id); 4967 4968 // Get the conversation for user1 and confirm it's favourited. 4969 $this->setUser($user1); 4970 $conv = core_message_external::get_conversation($user1->id, $conversationrecord->id); 4971 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4972 $this->assertTrue($conv['isfavourite']); 4973 4974 // Get the conversation for user2 and confirm it's NOT favourited. 4975 $this->setUser($user2); 4976 $conv = core_message_external::get_conversation($user2->id, $conversationrecord->id); 4977 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4978 $this->assertFalse($conv['isfavourite']); 4979 } 4980 4981 /** 4982 * Test getting a conversation with no messages. 4983 */ 4984 public function test_get_conversation_no_messages() { 4985 $this->resetAfterTest(); 4986 4987 $user1 = self::getDataGenerator()->create_user(); 4988 $user2 = self::getDataGenerator()->create_user(); 4989 4990 $name = 'lol conversation'; 4991 $conversation = \core_message\api::create_conversation( 4992 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4993 [ 4994 $user1->id, 4995 $user2->id, 4996 ], 4997 $name 4998 ); 4999 $conversationid = $conversation->id; 5000 5001 $this->setUser($user1); 5002 5003 $conv = core_message_external::get_conversation($user1->id, $conversationid); 5004 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5005 5006 $conv = (array) $conv; 5007 $this->assertEquals($conversationid, $conv['id']); 5008 $this->assertEquals($name, $conv['name']); 5009 $this->assertArrayHasKey('subname', $conv); 5010 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conv['type']); 5011 $this->assertEquals(2, $conv['membercount']); 5012 $this->assertEquals(false, $conv['isfavourite']); 5013 $this->assertEquals(true, $conv['isread']); 5014 $this->assertEquals(0, $conv['unreadcount']); 5015 $this->assertCount(1, $conv['members']); 5016 foreach ($conv['members'] as $member) { 5017 $member = (array) $member; 5018 $this->assertArrayHasKey('id', $member); 5019 $this->assertArrayHasKey('fullname', $member); 5020 $this->assertArrayHasKey('profileimageurl', $member); 5021 $this->assertArrayHasKey('profileimageurlsmall', $member); 5022 $this->assertArrayHasKey('isonline', $member); 5023 $this->assertArrayHasKey('showonlinestatus', $member); 5024 $this->assertArrayHasKey('isblocked', $member); 5025 $this->assertArrayHasKey('iscontact', $member); 5026 } 5027 $this->assertEmpty($conv['messages']); 5028 } 5029 5030 /** 5031 * Test getting a conversation with messages. 5032 */ 5033 public function test_get_conversation_with_messages() { 5034 $this->resetAfterTest(); 5035 5036 $user1 = self::getDataGenerator()->create_user(); 5037 $user2 = self::getDataGenerator()->create_user(); 5038 $user3 = self::getDataGenerator()->create_user(); 5039 5040 // Some random conversation. 5041 $otherconversation = \core_message\api::create_conversation( 5042 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 5043 [ 5044 $user1->id, 5045 $user3->id, 5046 ] 5047 ); 5048 5049 $conversation = \core_message\api::create_conversation( 5050 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 5051 [ 5052 $user1->id, 5053 $user2->id, 5054 ] 5055 ); 5056 $conversationid = $conversation->id; 5057 5058 $time = time(); 5059 $message1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'A', $time - 10); 5060 $message2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'B', $time - 5); 5061 $message3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'C', $time); 5062 5063 // Add some messages to the other convo to make sure they aren't included. 5064 testhelper::send_fake_message_to_conversation($user1, $otherconversation->id, 'foo'); 5065 5066 $this->setUser($user1); 5067 5068 // Test newest first. 5069 $conv = core_message_external::get_conversation( 5070 $user1->id, 5071 $conversationid, 5072 false, 5073 false, 5074 0, 5075 0, 5076 0, 5077 0, 5078 true 5079 ); 5080 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5081 5082 $conv = (array) $conv; 5083 $this->assertEquals(false, $conv['isread']); 5084 $this->assertEquals(1, $conv['unreadcount']); 5085 $this->assertCount(3, $conv['messages']); 5086 $this->assertEquals($message3id, $conv['messages'][0]->id); 5087 $this->assertEquals($user1->id, $conv['messages'][0]->useridfrom); 5088 $this->assertEquals($message2id, $conv['messages'][1]->id); 5089 $this->assertEquals($user2->id, $conv['messages'][1]->useridfrom); 5090 $this->assertEquals($message1id, $conv['messages'][2]->id); 5091 $this->assertEquals($user1->id, $conv['messages'][2]->useridfrom); 5092 5093 // Test newest last. 5094 $conv = core_message_external::get_conversation( 5095 $user1->id, 5096 $conversationid, 5097 false, 5098 false, 5099 0, 5100 0, 5101 0, 5102 0, 5103 false 5104 ); 5105 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5106 5107 $conv = (array) $conv; 5108 $this->assertCount(3, $conv['messages']); 5109 $this->assertEquals($message3id, $conv['messages'][2]->id); 5110 $this->assertEquals($user1->id, $conv['messages'][2]->useridfrom); 5111 $this->assertEquals($message2id, $conv['messages'][1]->id); 5112 $this->assertEquals($user2->id, $conv['messages'][1]->useridfrom); 5113 $this->assertEquals($message1id, $conv['messages'][0]->id); 5114 $this->assertEquals($user1->id, $conv['messages'][0]->useridfrom); 5115 5116 // Test message offest and limit. 5117 $conv = core_message_external::get_conversation( 5118 $user1->id, 5119 $conversationid, 5120 false, 5121 false, 5122 0, 5123 0, 5124 1, 5125 1, 5126 true 5127 ); 5128 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5129 5130 $conv = (array) $conv; 5131 $this->assertCount(1, $conv['messages']); 5132 $this->assertEquals($message2id, $conv['messages'][0]->id); 5133 $this->assertEquals($user2->id, $conv['messages'][0]->useridfrom); 5134 } 5135 5136 /** 5137 * Data provider for test_get_conversation_counts(). 5138 */ 5139 public function get_conversation_counts_test_cases() { 5140 $typeindividual = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL; 5141 $typegroup = \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP; 5142 $typeself = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF; 5143 list($user1, $user2, $user3, $user4, $user5, $user6, $user7, $user8) = [0, 1, 2, 3, 4, 5, 6, 7]; 5144 $conversations = [ 5145 [ 5146 'type' => $typeindividual, 5147 'users' => [$user1, $user2], 5148 'messages' => [$user1, $user2, $user2], 5149 'favourites' => [$user1], 5150 'enabled' => null // Individual conversations cannot be disabled. 5151 ], 5152 [ 5153 'type' => $typeindividual, 5154 'users' => [$user1, $user3], 5155 'messages' => [$user1, $user3, $user1], 5156 'favourites' => [], 5157 'enabled' => null // Individual conversations cannot be disabled. 5158 ], 5159 [ 5160 'type' => $typegroup, 5161 'users' => [$user1, $user2, $user3, $user4], 5162 'messages' => [$user1, $user2, $user3, $user4], 5163 'favourites' => [], 5164 'enabled' => true 5165 ], 5166 [ 5167 'type' => $typegroup, 5168 'users' => [$user2, $user3, $user4], 5169 'messages' => [$user2, $user3, $user4], 5170 'favourites' => [], 5171 'enabled' => true 5172 ], 5173 [ 5174 'type' => $typegroup, 5175 'users' => [$user6, $user7], 5176 'messages' => [$user6, $user7, $user7], 5177 'favourites' => [$user6], 5178 'enabled' => false 5179 ], 5180 [ 5181 'type' => $typeself, 5182 'users' => [$user8], 5183 'messages' => [$user8], 5184 'favourites' => [], 5185 'enabled' => null // Individual conversations cannot be disabled. 5186 ], 5187 ]; 5188 5189 return [ 5190 'No conversations' => [ 5191 'conversationConfigs' => $conversations, 5192 'deletemessagesuser' => null, 5193 'deletemessages' => [], 5194 'arguments' => [$user5], 5195 'expectedcounts' => ['favourites' => 1, 'types' => [ 5196 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5197 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5198 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5199 ]], 5200 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5201 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5202 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5203 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5204 ]], 5205 'deletedusers' => [] 5206 ], 5207 'No individual conversations, 2 group conversations' => [ 5208 'conversationConfigs' => $conversations, 5209 'deletemessagesuser' => null, 5210 'deletemessages' => [], 5211 'arguments' => [$user4], 5212 'expectedcounts' => ['favourites' => 1, 'types' => [ 5213 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5214 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5215 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5216 ]], 5217 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5218 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5219 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5220 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5221 ]], 5222 'deletedusers' => [] 5223 ], 5224 '2 individual conversations (one favourited), 1 group conversation' => [ 5225 'conversationConfigs' => $conversations, 5226 'deletemessagesuser' => null, 5227 'deletemessages' => [], 5228 'arguments' => [$user1], 5229 'expectedcounts' => ['favourites' => 2, 'types' => [ 5230 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5231 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5232 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5233 ]], 5234 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5235 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5236 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5237 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5238 ]], 5239 'deletedusers' => [] 5240 ], 5241 '1 individual conversation, 2 group conversations' => [ 5242 'conversationConfigs' => $conversations, 5243 'deletemessagesuser' => null, 5244 'deletemessages' => [], 5245 'arguments' => [$user2], 5246 'expectedcounts' => ['favourites' => 1, 'types' => [ 5247 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5248 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5249 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5250 ]], 5251 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5252 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5253 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5254 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5255 ]], 5256 'deletedusers' => [] 5257 ], 5258 '2 group conversations only' => [ 5259 'conversationConfigs' => $conversations, 5260 'deletemessagesuser' => null, 5261 'deletemessages' => [], 5262 'arguments' => [$user4], 5263 'expectedcounts' => ['favourites' => 1, 'types' => [ 5264 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5265 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5266 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5267 ]], 5268 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5269 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5270 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5271 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5272 ]], 5273 'deletedusers' => [] 5274 ], 5275 'All conversation types, delete a message from individual favourited, messages remaining' => [ 5276 'conversationConfigs' => $conversations, 5277 'deletemessagesuser' => $user1, 5278 'deletemessages' => [0], 5279 'arguments' => [$user1], 5280 'expectedcounts' => ['favourites' => 2, 'types' => [ 5281 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5282 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5283 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5284 ]], 5285 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5286 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5287 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5288 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5289 ]], 5290 'deletedusers' => [] 5291 ], 5292 'All conversation types, delete a message from individual non-favourited, messages remaining' => [ 5293 'conversationConfigs' => $conversations, 5294 'deletemessagesuser' => $user1, 5295 'deletemessages' => [3], 5296 'arguments' => [$user1], 5297 'expectedcounts' => ['favourites' => 2, 'types' => [ 5298 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5299 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5300 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5301 ]], 5302 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5303 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5304 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5305 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5306 ]], 5307 'deletedusers' => [] 5308 ], 5309 'All conversation types, delete all messages from individual favourited, no messages remaining' => [ 5310 'conversationConfigs' => $conversations, 5311 'deletemessagesuser' => $user1, 5312 'deletemessages' => [0, 1, 2], 5313 'arguments' => [$user1], 5314 'expectedcounts' => ['favourites' => 1, 'types' => [ 5315 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5316 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5317 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5318 ]], 5319 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5320 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5321 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5322 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5323 ]], 5324 'deletedusers' => [] 5325 ], 5326 'All conversation types, delete all messages from individual non-favourited, no messages remaining' => [ 5327 'conversationConfigs' => $conversations, 5328 'deletemessagesuser' => $user1, 5329 'deletemessages' => [3, 4, 5], 5330 'arguments' => [$user1], 5331 'expectedcounts' => ['favourites' => 2, 'types' => [ 5332 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5333 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5334 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5335 ]], 5336 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5337 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5338 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5339 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5340 ]], 5341 'deletedusers' => [] 5342 ], 5343 'All conversation types, delete all messages from individual favourited, no messages remaining, different user' => [ 5344 'conversationConfigs' => $conversations, 5345 'deletemessagesuser' => $user1, 5346 'deletemessages' => [0, 1, 2], 5347 'arguments' => [$user2], 5348 'expectedcounts' => ['favourites' => 1, 'types' => [ 5349 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5350 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5351 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5352 ]], 5353 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5354 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5355 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5356 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5357 ]], 5358 'deletedusers' => [] 5359 ], 5360 'All conversation types, delete all messages from individual non-favourited, no messages remaining, different user' => [ 5361 'conversationConfigs' => $conversations, 5362 'deletemessagesuser' => $user1, 5363 'deletemessages' => [3, 4, 5], 5364 'arguments' => [$user3], 5365 'expectedcounts' => ['favourites' => 1, 'types' => [ 5366 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5367 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5368 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5369 ]], 5370 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5371 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5372 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5373 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5374 ]], 5375 'deletedusers' => [] 5376 ], 5377 'All conversation types, delete some messages from group non-favourited, messages remaining,' => [ 5378 'conversationConfigs' => $conversations, 5379 'deletemessagesuser' => $user1, 5380 'deletemessages' => [6, 7], 5381 'arguments' => [$user1], 5382 'expectedcounts' => ['favourites' => 2, 'types' => [ 5383 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5384 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5385 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5386 ]], 5387 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5388 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5389 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5390 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5391 ]], 5392 'deletedusers' => [] 5393 ], 5394 'All conversation types, delete all messages from group non-favourited, no messages remaining,' => [ 5395 'conversationConfigs' => $conversations, 5396 'deletemessagesuser' => $user1, 5397 'deletemessages' => [6, 7, 8, 9], 5398 'arguments' => [$user1], 5399 'expectedcounts' => ['favourites' => 2, 'types' => [ 5400 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5401 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5402 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5403 ]], 5404 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5405 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5406 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5407 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5408 ]], 5409 'deletedusers' => [] 5410 ], 5411 'All conversation types, another user soft deleted' => [ 5412 'conversationConfigs' => $conversations, 5413 'deletemessagesuser' => null, 5414 'deletemessages' => [], 5415 'arguments' => [$user1], 5416 'expectedcounts' => ['favourites' => 2, 'types' => [ 5417 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5418 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5419 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5420 ]], 5421 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5422 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5423 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5424 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5425 ]], 5426 'deletedusers' => [$user2] 5427 ], 5428 'All conversation types, all group users soft deleted' => [ 5429 'conversationConfigs' => $conversations, 5430 'deletemessagesuser' => null, 5431 'deletemessages' => [], 5432 'arguments' => [$user1], 5433 'expectedcounts' => ['favourites' => 2, 'types' => [ 5434 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5435 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5436 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5437 ]], 5438 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5439 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5440 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5441 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5442 ]], 5443 'deletedusers' => [$user2, $user3, $user4] 5444 ], 5445 'Group conversation which is disabled, favourited' => [ 5446 'conversationConfigs' => $conversations, 5447 'deletemessagesuser' => null, 5448 'deletemessages' => [], 5449 'arguments' => [$user6], 5450 'expectedcounts' => ['favourites' => 1, 'types' => [ 5451 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5452 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5453 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5454 ]], 5455 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5456 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5457 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5458 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5459 ]], 5460 'deletedusers' => [] 5461 ], 5462 'Group conversation which is disabled, non-favourited' => [ 5463 'conversationConfigs' => $conversations, 5464 'deletemessagesuser' => null, 5465 'deletemessages' => [], 5466 'arguments' => [$user7], 5467 'expectedcounts' => ['favourites' => 1, 'types' => [ 5468 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5469 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5470 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5471 ]], 5472 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5473 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5474 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5475 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5476 ]], 5477 'deletedusers' => [] 5478 ], 5479 'Conversation with self' => [ 5480 'conversationConfigs' => $conversations, 5481 'deletemessagesuser' => null, 5482 'deletemessages' => [], 5483 'arguments' => [$user8], 5484 'expectedcounts' => ['favourites' => 0, 'types' => [ 5485 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5486 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5487 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 1 5488 ]], 5489 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5490 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5491 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5492 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5493 ]], 5494 'deletedusers' => [] 5495 ], 5496 ]; 5497 } 5498 5499 /** 5500 * Test the get_conversation_counts() function. 5501 * 5502 * @dataProvider get_conversation_counts_test_cases() 5503 * @param array $conversationconfigs Conversations to create 5504 * @param int $deletemessagesuser The user who is deleting the messages 5505 * @param array $deletemessages The list of messages to delete (by index) 5506 * @param array $arguments Arguments for the count conversations function 5507 * @param array $expectedcounts the expected conversation counts 5508 * @param array $expectedunreadcounts the expected unread conversation counts 5509 * @param array $deletedusers the array of users to soft delete. 5510 */ 5511 public function test_get_conversation_counts( 5512 $conversationconfigs, 5513 $deletemessagesuser, 5514 $deletemessages, 5515 $arguments, 5516 $expectedcounts, 5517 $expectedunreadcounts, 5518 $deletedusers 5519 ) { 5520 $this->resetAfterTest(); 5521 $generator = $this->getDataGenerator(); 5522 $users = [ 5523 $generator->create_user(), 5524 $generator->create_user(), 5525 $generator->create_user(), 5526 $generator->create_user(), 5527 $generator->create_user(), 5528 $generator->create_user(), 5529 $generator->create_user(), 5530 $generator->create_user() 5531 ]; 5532 5533 $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null; 5534 $this->setUser($users[$arguments[0]]); 5535 $arguments[0] = $users[$arguments[0]]->id; 5536 $systemcontext = \context_system::instance(); 5537 $conversations = []; 5538 $messageids = []; 5539 5540 foreach ($conversationconfigs as $config) { 5541 $conversation = \core_message\api::create_conversation( 5542 $config['type'], 5543 array_map(function($userindex) use ($users) { 5544 return $users[$userindex]->id; 5545 }, $config['users']), 5546 null, 5547 ($config['enabled'] ?? true) 5548 ); 5549 5550 foreach ($config['messages'] as $userfromindex) { 5551 $userfrom = $users[$userfromindex]; 5552 $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id); 5553 } 5554 5555 // Remove the self conversations created by the generator, 5556 // so we can choose to set that ourself and honour the original intention of the test. 5557 $userids = array_map(function($userindex) use ($users) { 5558 return $users[$userindex]->id; 5559 }, $config['users']); 5560 foreach ($userids as $userid) { 5561 if ($conversation->type == \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) { 5562 \core_message\api::unset_favourite_conversation($conversation->id, $userid); 5563 } 5564 } 5565 5566 foreach ($config['favourites'] as $userfromindex) { 5567 $userfrom = $users[$userfromindex]; 5568 $usercontext = \context_user::instance($userfrom->id); 5569 $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); 5570 $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext); 5571 } 5572 5573 $conversations[] = $conversation; 5574 } 5575 5576 foreach ($deletemessages as $messageindex) { 5577 \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]); 5578 } 5579 5580 foreach ($deletedusers as $deleteduser) { 5581 delete_user($users[$deleteduser]); 5582 } 5583 5584 $counts = core_message_external::get_conversation_counts(...$arguments); 5585 $counts = \external_api::clean_returnvalue(core_message_external::get_conversation_counts_returns(), $counts); 5586 5587 $this->assertEquals($expectedcounts['favourites'], $counts['favourites']); 5588 $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL], 5589 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); 5590 $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP], 5591 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); 5592 $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF], 5593 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]); 5594 } 5595 5596 /** 5597 * Test the get_unread_conversation_counts() function. 5598 * 5599 * @dataProvider get_conversation_counts_test_cases 5600 * @param array $conversationconfigs Conversations to create 5601 * @param int $deletemessagesuser The user who is deleting the messages 5602 * @param array $deletemessages The list of messages to delete (by index) 5603 * @param array $arguments Arguments for the count conversations function 5604 * @param array $expectedcounts the expected conversation counts 5605 * @param array $expectedunreadcounts the expected unread conversation counts 5606 * @param array $deletedusers the list of users to soft-delete. 5607 */ 5608 public function test_get_unread_conversation_counts( 5609 $conversationconfigs, 5610 $deletemessagesuser, 5611 $deletemessages, 5612 $arguments, 5613 $expectedcounts, 5614 $expectedunreadcounts, 5615 $deletedusers 5616 ) { 5617 $this->resetAfterTest(); 5618 $generator = $this->getDataGenerator(); 5619 $users = [ 5620 $generator->create_user(), 5621 $generator->create_user(), 5622 $generator->create_user(), 5623 $generator->create_user(), 5624 $generator->create_user(), 5625 $generator->create_user(), 5626 $generator->create_user(), 5627 $generator->create_user() 5628 ]; 5629 5630 $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null; 5631 $this->setUser($users[$arguments[0]]); 5632 $arguments[0] = $users[$arguments[0]]->id; 5633 $systemcontext = \context_system::instance(); 5634 $conversations = []; 5635 $messageids = []; 5636 5637 foreach ($conversationconfigs as $config) { 5638 $conversation = \core_message\api::create_conversation( 5639 $config['type'], 5640 array_map(function($userindex) use ($users) { 5641 return $users[$userindex]->id; 5642 }, $config['users']), 5643 null, 5644 ($config['enabled'] ?? true) 5645 ); 5646 5647 foreach ($config['messages'] as $userfromindex) { 5648 $userfrom = $users[$userfromindex]; 5649 $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id); 5650 } 5651 5652 foreach ($config['favourites'] as $userfromindex) { 5653 $userfrom = $users[$userfromindex]; 5654 $usercontext = \context_user::instance($userfrom->id); 5655 $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); 5656 $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext); 5657 } 5658 5659 $conversations[] = $conversation; 5660 } 5661 5662 foreach ($deletemessages as $messageindex) { 5663 \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]); 5664 } 5665 5666 foreach ($deletedusers as $deleteduser) { 5667 delete_user($users[$deleteduser]); 5668 } 5669 5670 $counts = core_message_external::get_unread_conversation_counts(...$arguments); 5671 $counts = \external_api::clean_returnvalue(core_message_external::get_unread_conversation_counts_returns(), $counts); 5672 5673 $this->assertEquals($expectedunreadcounts['favourites'], $counts['favourites']); 5674 $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL], 5675 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); 5676 $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP], 5677 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); 5678 $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF], 5679 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]); 5680 } 5681 5682 /** 5683 * Test delete_message for all users. 5684 */ 5685 public function test_delete_message_for_all_users() { 5686 global $DB; 5687 5688 $this->resetAfterTest(true); 5689 5690 // Create fake data to test it. 5691 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5692 5693 // Send message as user1 to group conversation. 5694 $messageid1 = testhelper::send_fake_message_to_conversation($user1, $convgroup->id); 5695 $messageid2 = testhelper::send_fake_message_to_conversation($user2, $convgroup->id); 5696 5697 // User1 deletes the first message for all users of group conversation. 5698 // First, we have to allow user1 (Teacher) can delete messages for all users. 5699 $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']); 5700 assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, \context_system::instance()); 5701 5702 $this->setUser($user1); 5703 5704 // Now, user1 deletes message for all users. 5705 $return = core_message_external::delete_message_for_all_users($messageid1, $user1->id); 5706 $return = \external_api::clean_returnvalue(core_message_external::delete_message_for_all_users_returns(), $return); 5707 // Check if everything is ok. 5708 $this->assertEquals(array(), $return); 5709 5710 // Check we have 3 records on message_user_actions with the mark MESSAGE_ACTION_DELETED. 5711 $muas = $DB->get_records('message_user_actions', array('messageid' => $messageid1), 'userid ASC'); 5712 $this->assertCount(3, $muas); 5713 $mua1 = array_shift($muas); 5714 $mua2 = array_shift($muas); 5715 $mua3 = array_shift($muas); 5716 5717 $this->assertEquals($user1->id, $mua1->userid); 5718 $this->assertEquals($messageid1, $mua1->messageid); 5719 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action); 5720 $this->assertEquals($user2->id, $mua2->userid); 5721 $this->assertEquals($messageid1, $mua2->messageid); 5722 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action); 5723 $this->assertEquals($user3->id, $mua3->userid); 5724 $this->assertEquals($messageid1, $mua3->messageid); 5725 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action); 5726 } 5727 5728 /** 5729 * Test delete_message for all users with messaging disabled. 5730 */ 5731 public function test_delete_message_for_all_users_messaging_disabled() { 5732 global $CFG; 5733 5734 $this->resetAfterTest(); 5735 5736 // Create fake data to test it. 5737 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5738 5739 // Send message as user1 to group conversation. 5740 $messageid = testhelper::send_fake_message_to_conversation($user1, $convgroup->id); 5741 5742 $this->setUser($user1); 5743 5744 // Disable messaging. 5745 $CFG->messaging = 0; 5746 5747 // Ensure an exception is thrown. 5748 $this->expectException('moodle_exception'); 5749 core_message_external::delete_message_for_all_users($messageid, $user1->id); 5750 } 5751 5752 /** 5753 * Test delete_message for all users with no permission. 5754 */ 5755 public function test_delete_message_for_all_users_no_permission() { 5756 $this->resetAfterTest(); 5757 5758 // Create fake data to test it. 5759 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5760 5761 // Send message as user1 to group conversation. 5762 $messageid = testhelper::send_fake_message_to_conversation($user1, $convgroup->id); 5763 5764 $this->setUser($user2); 5765 5766 // Try as user2 to delete a message for all users without permission to do it. 5767 $this->expectException('moodle_exception'); 5768 $this->expectExceptionMessage('You do not have permission to delete this message for everyone.'); 5769 core_message_external::delete_message_for_all_users($messageid, $user2->id); 5770 } 5771 5772 /** 5773 * Test delete_message for all users in a private conversation. 5774 */ 5775 public function test_delete_message_for_all_users_private_conversation() { 5776 global $DB; 5777 5778 $this->resetAfterTest(); 5779 5780 // Create fake data to test it. 5781 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5782 5783 // Send message as user1 to private conversation. 5784 $messageid = testhelper::send_fake_message_to_conversation($user1, $convindividual->id); 5785 5786 // First, we have to allow user1 (Teacher) can delete messages for all users. 5787 $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']); 5788 assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, \context_system::instance()); 5789 5790 $this->setUser($user1); 5791 5792 // Try as user1 to delete a private message for all users on individual conversation. 5793 // User1 should not delete message for all users in a private conversations despite being a teacher. 5794 // Because is a teacher in a course and not in a system context. 5795 $this->expectException('moodle_exception'); 5796 $this->expectExceptionMessage('You do not have permission to delete this message for everyone.'); 5797 core_message_external::delete_message_for_all_users($messageid, $user1->id); 5798 } 5799 5800 /** 5801 * Test retrieving conversation messages by providing a timefrom higher than last message timecreated. It should return no 5802 * messages but keep the return structure to not break when called from the ws. 5803 */ 5804 public function test_get_conversation_messages_timefrom_higher_than_last_timecreated() { 5805 $this->resetAfterTest(true); 5806 5807 // Create some users. 5808 $user1 = self::getDataGenerator()->create_user(); 5809 $user2 = self::getDataGenerator()->create_user(); 5810 $user3 = self::getDataGenerator()->create_user(); 5811 $user4 = self::getDataGenerator()->create_user(); 5812 5813 // Create group conversation. 5814 $conversation = \core_message\api::create_conversation( 5815 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 5816 [$user1->id, $user2->id, $user3->id, $user4->id] 5817 ); 5818 5819 // The person asking for the messages for another user. 5820 $this->setUser($user1); 5821 5822 // Send some messages back and forth. 5823 $time = 1; 5824 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1); 5825 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2); 5826 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3); 5827 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4); 5828 5829 // Retrieve the messages. 5830 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, '', $time + 5); 5831 5832 // We need to execute the return values cleaning process to simulate the web service server. 5833 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), $result); 5834 5835 // Check the results are correct. 5836 $this->assertEquals($conversation->id, $result['id']); 5837 5838 // Confirm the message data is correct. 5839 $messages = $result['messages']; 5840 $this->assertEquals(0, count($messages)); 5841 5842 // Confirm that members key is present. 5843 $this->assertArrayHasKey('members', $result); 5844 } 5845 5846 /** 5847 * Helper to seed the database with initial state with data. 5848 */ 5849 protected function create_delete_message_test_data() { 5850 // Create some users. 5851 $user1 = self::getDataGenerator()->create_user(); 5852 $user2 = self::getDataGenerator()->create_user(); 5853 $user3 = self::getDataGenerator()->create_user(); 5854 5855 // Create a course and enrol the users. 5856 $course = $this->getDataGenerator()->create_course(); 5857 $coursecontext = \context_course::instance($course->id); 5858 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'editingteacher'); 5859 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 5860 $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student'); 5861 5862 // Create a group and added the users into. 5863 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 5864 groups_add_member($group1->id, $user1->id); 5865 groups_add_member($group1->id, $user2->id); 5866 groups_add_member($group1->id, $user3->id); 5867 5868 // Create a group conversation linked with the course. 5869 $convgroup = \core_message\api::create_conversation( 5870 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 5871 [$user1->id, $user2->id, $user3->id], 5872 'Group test delete for everyone', \core_message\api::MESSAGE_CONVERSATION_ENABLED, 5873 'core_group', 5874 'groups', 5875 $group1->id, 5876 \context_course::instance($course->id)->id 5877 ); 5878 5879 // Create and individual conversation. 5880 $convindividual = \core_message\api::create_conversation( 5881 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 5882 [$user1->id, $user2->id] 5883 ); 5884 5885 return [$user1, $user2, $user3, $convgroup, $convindividual]; 5886 } 5887 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body