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