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