See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_message; 18 19 use core_message\tests\helper as testhelper; 20 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 // This event contains HTML in the subject field that will be removed by the WS (otherwise it will generate an exception). 1441 $eventdata = new \core\message\message(); 1442 $eventdata->courseid = $course->id; 1443 $eventdata->name = 'submission'; 1444 $eventdata->component = 'mod_feedback'; 1445 $eventdata->userfrom = $user1; 1446 $eventdata->userto = $user2; 1447 $eventdata->subject = 'Feedback submitted <span>with html</span>'; 1448 $eventdata->fullmessage = 'Feedback submitted from an user'; 1449 $eventdata->fullmessageformat = FORMAT_PLAIN; 1450 $eventdata->fullmessagehtml = '<strong>Feedback submitted</strong>'; 1451 $eventdata->smallmessage = ''; 1452 $eventdata->customdata = ['datakey' => 'data']; 1453 message_send($eventdata); 1454 1455 $this->setUser($user1); 1456 // Get unread notifications from any user to user1. 1457 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0); 1458 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1459 $this->assertCount(3, $messages['messages']); 1460 1461 // Get one unread notifications from any user to user1. 1462 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', MESSAGE_GET_UNREAD, true, 0, 1); 1463 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1464 $this->assertCount(1, $messages['messages']); 1465 1466 // Get read notifications from any user to user1. 1467 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', MESSAGE_GET_READ, true, 0, 0); 1468 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1469 $this->assertCount(0, $messages['messages']); 1470 1471 // Get unread both type of messages from any user to user1. 1472 $messages = core_message_external::get_messages($user1->id, 0, 'both', MESSAGE_GET_UNREAD, true, 0, 0); 1473 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1474 $this->assertCount(4, $messages['messages']); 1475 1476 // Get unread notifications from no-reply-user to user1. 1477 $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0); 1478 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1479 $this->assertCount(1, $messages['messages']); 1480 1481 // Get notifications send by user1 to any user. 1482 $messages = core_message_external::get_messages(0, $user1->id, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0); 1483 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1484 $this->assertCount(1, $messages['messages']); 1485 // Check we receive custom data as a unserialisable json. 1486 $this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata'])); 1487 $this->assertEquals('mod_feedback', $messages['messages'][0]['component']); 1488 $this->assertEquals('submission', $messages['messages'][0]['eventtype']); 1489 $feedbackicon = clean_param($PAGE->get_renderer('core')->image_url('monologo', 'mod_feedback')->out(), PARAM_URL); 1490 $this->assertEquals($feedbackicon, $messages['messages'][0]['iconurl']); 1491 1492 // Test warnings. 1493 $CFG->messaging = 0; 1494 1495 $messages = core_message_external::get_messages(0, $user1->id, 'both', MESSAGE_GET_UNREAD, true, 0, 0); 1496 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1497 $this->assertCount(1, $messages['warnings']); 1498 1499 // Test exceptions. 1500 1501 // Messaging disabled. 1502 try { 1503 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0); 1504 $this->fail('Exception expected due messaging disabled.'); 1505 } catch (\moodle_exception $e) { 1506 $this->assertEquals('disabled', $e->errorcode); 1507 } 1508 1509 $CFG->messaging = 1; 1510 1511 // Invalid users. 1512 try { 1513 $messages = core_message_external::get_messages(0, 0, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0); 1514 $this->fail('Exception expected due invalid users.'); 1515 } catch (\moodle_exception $e) { 1516 $this->assertEquals('accessdenied', $e->errorcode); 1517 } 1518 1519 // Invalid user ids. 1520 try { 1521 $messages = core_message_external::get_messages(2500, 0, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0); 1522 $this->fail('Exception expected due invalid users.'); 1523 } catch (\moodle_exception $e) { 1524 $this->assertEquals('invaliduser', $e->errorcode); 1525 } 1526 1527 // Invalid users (permissions). 1528 $this->setUser($user2); 1529 try { 1530 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0); 1531 $this->fail('Exception expected due invalid user.'); 1532 } catch (\moodle_exception $e) { 1533 $this->assertEquals('accessdenied', $e->errorcode); 1534 } 1535 1536 } 1537 1538 /** 1539 * Test get_messages where we want all messages from a user, sent to any user. 1540 */ 1541 public function test_get_messages_useridto_all() { 1542 $this->resetAfterTest(true); 1543 1544 $user1 = self::getDataGenerator()->create_user(); 1545 $user2 = self::getDataGenerator()->create_user(); 1546 $user3 = self::getDataGenerator()->create_user(); 1547 1548 $this->setUser($user1); 1549 1550 // Send a message from user 1 to two other users. 1551 $this->send_message($user1, $user2, 'some random text 1', 0, 1); 1552 $this->send_message($user1, $user3, 'some random text 2', 0, 2); 1553 1554 // Get messages sent from user 1. 1555 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', MESSAGE_GET_UNREAD, false, 0, 0); 1556 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1557 1558 // Confirm the data is correct. 1559 $messages = $messages['messages']; 1560 $this->assertCount(2, $messages); 1561 1562 $message1 = array_shift($messages); 1563 $message2 = array_shift($messages); 1564 1565 $this->assertEquals($user1->id, $message1['useridfrom']); 1566 $this->assertEquals($user2->id, $message1['useridto']); 1567 1568 $this->assertEquals($user1->id, $message2['useridfrom']); 1569 $this->assertEquals($user3->id, $message2['useridto']); 1570 } 1571 1572 /** 1573 * Test get_messages where we want all messages to a user, sent by any user. 1574 */ 1575 public function test_get_messages_useridfrom_all() { 1576 $this->resetAfterTest(); 1577 1578 $user1 = self::getDataGenerator()->create_user(); 1579 $user2 = self::getDataGenerator()->create_user(); 1580 $user3 = self::getDataGenerator()->create_user(); 1581 1582 $this->setUser($user1); 1583 1584 // Send a message to user 1 from two other users. 1585 $this->send_message($user2, $user1, 'some random text 1', 0, 1); 1586 $this->send_message($user3, $user1, 'some random text 2', 0, 2); 1587 1588 // Get messages sent to user 1. 1589 $messages = core_message_external::get_messages($user1->id, 0, 'conversations', MESSAGE_GET_UNREAD, false, 0, 0); 1590 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1591 1592 // Confirm the data is correct. 1593 $messages = $messages['messages']; 1594 $this->assertCount(2, $messages); 1595 1596 $message1 = array_shift($messages); 1597 $message2 = array_shift($messages); 1598 1599 $this->assertEquals($user2->id, $message1['useridfrom']); 1600 $this->assertEquals($user1->id, $message1['useridto']); 1601 1602 $this->assertEquals($user3->id, $message2['useridfrom']); 1603 $this->assertEquals($user1->id, $message2['useridto']); 1604 } 1605 1606 /** 1607 * Test get_blocked_users. 1608 */ 1609 public function test_get_blocked_users() { 1610 $this->resetAfterTest(true); 1611 1612 $user1 = self::getDataGenerator()->create_user(); 1613 $userstranger = self::getDataGenerator()->create_user(); 1614 $useroffline1 = self::getDataGenerator()->create_user(); 1615 $useroffline2 = self::getDataGenerator()->create_user(); 1616 $userblocked = self::getDataGenerator()->create_user(); 1617 1618 // Login as user1. 1619 $this->setUser($user1); 1620 1621 \core_message\api::add_contact($user1->id, $useroffline1->id); 1622 \core_message\api::add_contact($user1->id, $useroffline2->id); 1623 1624 // The userstranger sends a couple of messages to user1. 1625 $this->send_message($userstranger, $user1, 'Hello there!'); 1626 $this->send_message($userstranger, $user1, 'How you goin?'); 1627 1628 // The userblocked sends a message to user1. 1629 // Note that this user is not blocked at this point. 1630 $this->send_message($userblocked, $user1, 'Here, have some spam.'); 1631 1632 // Retrieve the list of blocked users. 1633 $this->setUser($user1); 1634 $blockedusers = core_message_external::get_blocked_users($user1->id); 1635 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1636 $this->assertCount(0, $blockedusers['users']); 1637 1638 // Block the $userblocked and retrieve again the list. 1639 \core_message\api::block_user($user1->id, $userblocked->id); 1640 $blockedusers = core_message_external::get_blocked_users($user1->id); 1641 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1642 $this->assertCount(1, $blockedusers['users']); 1643 1644 // Remove the $userblocked and check that the list now is empty. 1645 delete_user($userblocked); 1646 $blockedusers = core_message_external::get_blocked_users($user1->id); 1647 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1648 $this->assertCount(0, $blockedusers['users']); 1649 } 1650 1651 /** 1652 * Test mark_message_read. 1653 */ 1654 public function test_mark_message_read() { 1655 $this->resetAfterTest(true); 1656 1657 $user1 = self::getDataGenerator()->create_user(); 1658 $user2 = self::getDataGenerator()->create_user(); 1659 $user3 = self::getDataGenerator()->create_user(); 1660 1661 // Login as user1. 1662 $this->setUser($user1); 1663 \core_message\api::add_contact($user1->id, $user2->id); 1664 \core_message\api::add_contact($user1->id, $user3->id); 1665 1666 // The user2 sends a couple of messages to user1. 1667 $this->send_message($user2, $user1, 'Hello there!'); 1668 $this->send_message($user2, $user1, 'How you goin?'); 1669 $this->send_message($user3, $user1, 'How you goin?'); 1670 $this->send_message($user3, $user2, 'How you goin?'); 1671 1672 // Retrieve all messages sent by user2 (they are currently unread). 1673 $lastmessages = message_get_messages($user1->id, $user2->id, 0, MESSAGE_GET_UNREAD); 1674 1675 $messageids = array(); 1676 foreach ($lastmessages as $m) { 1677 $messageid = core_message_external::mark_message_read($m->id, time()); 1678 $messageids[] = \external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid); 1679 } 1680 1681 // Retrieve all messages sent (they are currently read). 1682 $lastmessages = message_get_messages($user1->id, $user2->id, 0, MESSAGE_GET_READ); 1683 $this->assertCount(2, $lastmessages); 1684 $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages); 1685 $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages); 1686 1687 // Retrieve all messages sent by any user (that are currently unread). 1688 $lastmessages = message_get_messages($user1->id, 0, 0, MESSAGE_GET_UNREAD); 1689 $this->assertCount(1, $lastmessages); 1690 1691 // Invalid message ids. 1692 try { 1693 $messageid = core_message_external::mark_message_read(1337, time()); 1694 $this->fail('Exception expected due invalid messageid.'); 1695 } catch (\dml_missing_record_exception $e) { 1696 $this->assertEquals('invalidrecordunknown', $e->errorcode); 1697 } 1698 1699 // A message to a different user. 1700 $lastmessages = message_get_messages($user2->id, $user3->id, 0, MESSAGE_GET_UNREAD); 1701 $messageid = array_pop($lastmessages)->id; 1702 try { 1703 $messageid = core_message_external::mark_message_read($messageid, time()); 1704 $this->fail('Exception expected due invalid messageid.'); 1705 } catch (\invalid_parameter_exception $e) { 1706 $this->assertEquals('invalidparameter', $e->errorcode); 1707 } 1708 } 1709 1710 /** 1711 * Test mark_notification_read. 1712 */ 1713 public function test_mark_notification_read() { 1714 $this->resetAfterTest(true); 1715 1716 $user1 = self::getDataGenerator()->create_user(); 1717 $user2 = self::getDataGenerator()->create_user(); 1718 $user3 = self::getDataGenerator()->create_user(); 1719 1720 // Login as user1. 1721 $this->setUser($user1); 1722 \core_message\api::add_contact($user1->id, $user2->id); 1723 \core_message\api::add_contact($user1->id, $user3->id); 1724 1725 // The user2 sends a couple of notifications to user1. 1726 $this->send_message($user2, $user1, 'Hello there!', 1); 1727 $this->send_message($user2, $user1, 'How you goin?', 1); 1728 $this->send_message($user3, $user1, 'How you goin?', 1); 1729 $this->send_message($user3, $user2, 'How you goin?', 1); 1730 1731 // Retrieve all notifications sent by user2 (they are currently unread). 1732 $lastnotifications = message_get_messages($user1->id, $user2->id, 1, MESSAGE_GET_UNREAD); 1733 1734 $notificationids = array(); 1735 foreach ($lastnotifications as $n) { 1736 $notificationid = core_message_external::mark_notification_read($n->id, time()); 1737 $notificationids[] = \external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(), 1738 $notificationid); 1739 } 1740 1741 // Retrieve all notifications sent (they are currently read). 1742 $lastnotifications = message_get_messages($user1->id, $user2->id, 1, MESSAGE_GET_READ); 1743 $this->assertCount(2, $lastnotifications); 1744 $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications); 1745 $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications); 1746 1747 // Retrieve all notifications sent by any user (that are currently unread). 1748 $lastnotifications = message_get_messages($user1->id, 0, 1, MESSAGE_GET_UNREAD); 1749 $this->assertCount(1, $lastnotifications); 1750 1751 // Invalid notification ids. 1752 try { 1753 $notificationid = core_message_external::mark_notification_read(1337, time()); 1754 $this->fail('Exception expected due invalid notificationid.'); 1755 } catch (\dml_missing_record_exception $e) { 1756 $this->assertEquals('invalidrecord', $e->errorcode); 1757 } 1758 1759 // A notification to a different user. 1760 $lastnotifications = message_get_messages($user2->id, $user3->id, 1, MESSAGE_GET_UNREAD); 1761 $notificationid = array_pop($lastnotifications)->id; 1762 try { 1763 $notificationid = core_message_external::mark_notification_read($notificationid, time()); 1764 $this->fail('Exception expected due invalid notificationid.'); 1765 } catch (\invalid_parameter_exception $e) { 1766 $this->assertEquals('invalidparameter', $e->errorcode); 1767 } 1768 } 1769 1770 /** 1771 * Test delete_message. 1772 */ 1773 public function test_delete_message() { 1774 global $DB; 1775 $this->resetAfterTest(true); 1776 1777 $user1 = self::getDataGenerator()->create_user(); 1778 $user2 = self::getDataGenerator()->create_user(); 1779 $user3 = self::getDataGenerator()->create_user(); 1780 $user4 = self::getDataGenerator()->create_user(); 1781 1782 // Login as user1. 1783 $this->setUser($user1); 1784 \core_message\api::add_contact($user1->id, $user2->id); 1785 \core_message\api::add_contact($user1->id, $user3->id); 1786 1787 // User user1 does not interchange messages with user3. 1788 $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); 1789 $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); 1790 $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); 1791 $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE); 1792 1793 // Retrieve all messages sent by user2 (they are currently unread). 1794 $lastmessages = message_get_messages($user1->id, $user2->id, 0, MESSAGE_GET_UNREAD); 1795 1796 // Delete a message not read, as a user from. 1797 $result = core_message_external::delete_message($m1to2, $user1->id, false); 1798 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1799 $this->assertTrue($result['status']); 1800 $this->assertCount(0, $result['warnings']); 1801 $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id)); 1802 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action); 1803 1804 // Try to delete the same message again. 1805 $result = core_message_external::delete_message($m1to2, $user1->id, false); 1806 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1807 $this->assertFalse($result['status']); 1808 1809 // Try to delete a message that does not belong to me. 1810 try { 1811 $messageid = core_message_external::delete_message($m2to3, $user3->id, false); 1812 $this->fail('Exception expected due invalid messageid.'); 1813 } catch (\moodle_exception $e) { 1814 $this->assertEquals('You do not have permission to delete this message', $e->errorcode); 1815 } 1816 1817 $this->setUser($user3); 1818 // Delete a message not read, as a user to. 1819 $result = core_message_external::delete_message($m2to3, $user3->id, false); 1820 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1821 $this->assertTrue($result['status']); 1822 $this->assertCount(0, $result['warnings']); 1823 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id, 1824 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1825 1826 // Delete a message read. 1827 $message = $DB->get_record('messages', ['id' => $m3to2]); 1828 \core_message\api::mark_message_as_read($user3->id, $message, time()); 1829 $result = core_message_external::delete_message($m3to2, $user3->id); 1830 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1831 $this->assertTrue($result['status']); 1832 $this->assertCount(0, $result['warnings']); 1833 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id, 1834 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1835 1836 // Invalid message ids. 1837 try { 1838 $result = core_message_external::delete_message(-1, $user1->id); 1839 $this->fail('Exception expected due invalid messageid.'); 1840 } catch (\dml_missing_record_exception $e) { 1841 $this->assertEquals('invalidrecord', $e->errorcode); 1842 } 1843 1844 // Invalid user. 1845 try { 1846 $result = core_message_external::delete_message($m1to2, -1, false); 1847 $this->fail('Exception expected due invalid user.'); 1848 } catch (\moodle_exception $e) { 1849 $this->assertEquals('invaliduser', $e->errorcode); 1850 } 1851 1852 // Not active user. 1853 delete_user($user2); 1854 try { 1855 $result = core_message_external::delete_message($m1to2, $user2->id, false); 1856 $this->fail('Exception expected due invalid user.'); 1857 } catch (\moodle_exception $e) { 1858 $this->assertEquals('userdeleted', $e->errorcode); 1859 } 1860 1861 // Now, as an admin, try to delete any message. 1862 $this->setAdminUser(); 1863 $result = core_message_external::delete_message($m3to4, $user4->id, false); 1864 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1865 $this->assertTrue($result['status']); 1866 $this->assertCount(0, $result['warnings']); 1867 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id, 1868 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1869 1870 } 1871 1872 public function test_mark_all_notifications_as_read_invalid_user_exception() { 1873 $this->resetAfterTest(true); 1874 1875 $this->expectException('moodle_exception'); 1876 core_message_external::mark_all_notifications_as_read(-2132131, 0); 1877 } 1878 1879 public function test_mark_all_notifications_as_read_access_denied_exception() { 1880 $this->resetAfterTest(true); 1881 1882 $sender = $this->getDataGenerator()->create_user(); 1883 $user = $this->getDataGenerator()->create_user(); 1884 1885 $this->setUser($user); 1886 $this->expectException('moodle_exception'); 1887 core_message_external::mark_all_notifications_as_read($sender->id, 0); 1888 } 1889 1890 public function test_mark_all_notifications_as_read_missing_from_user_exception() { 1891 $this->resetAfterTest(true); 1892 1893 $sender = $this->getDataGenerator()->create_user(); 1894 1895 $this->setUser($sender); 1896 $this->expectException('moodle_exception'); 1897 core_message_external::mark_all_notifications_as_read($sender->id, 99999); 1898 } 1899 1900 public function test_mark_all_notifications_as_read() { 1901 global $DB; 1902 1903 $this->resetAfterTest(true); 1904 1905 $sender1 = $this->getDataGenerator()->create_user(); 1906 $sender2 = $this->getDataGenerator()->create_user(); 1907 $sender3 = $this->getDataGenerator()->create_user(); 1908 $recipient = $this->getDataGenerator()->create_user(); 1909 1910 $this->setUser($recipient); 1911 1912 $this->send_message($sender1, $recipient, 'Notification', 1); 1913 $this->send_message($sender1, $recipient, 'Notification', 1); 1914 $this->send_message($sender2, $recipient, 'Notification', 1); 1915 $this->send_message($sender2, $recipient, 'Notification', 1); 1916 $this->send_message($sender3, $recipient, 'Notification', 1); 1917 $this->send_message($sender3, $recipient, 'Notification', 1); 1918 1919 core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id); 1920 $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]); 1921 $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]); 1922 1923 $this->assertCount(2, $readnotifications); 1924 $this->assertCount(4, $unreadnotifications); 1925 1926 core_message_external::mark_all_notifications_as_read($recipient->id, 0); 1927 $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]); 1928 $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]); 1929 1930 $this->assertCount(6, $readnotifications); 1931 $this->assertCount(0, $unreadnotifications); 1932 } 1933 1934 public function test_mark_all_notifications_as_read_time_created_to() { 1935 global $DB; 1936 1937 $this->resetAfterTest(true); 1938 1939 $sender1 = $this->getDataGenerator()->create_user(); 1940 $sender2 = $this->getDataGenerator()->create_user(); 1941 1942 $recipient = $this->getDataGenerator()->create_user(); 1943 $this->setUser($recipient); 1944 1945 // Record messages as sent on one second intervals. 1946 $time = time(); 1947 1948 $this->send_message($sender1, $recipient, 'Message 1', 1, $time); 1949 $this->send_message($sender2, $recipient, 'Message 2', 1, $time + 1); 1950 $this->send_message($sender1, $recipient, 'Message 3', 1, $time + 2); 1951 $this->send_message($sender2, $recipient, 'Message 4', 1, $time + 3); 1952 1953 // Mark notifications sent from sender1 up until the second message; should only mark the first notification as read. 1954 core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id, $time + 1); 1955 1956 $params = [$recipient->id]; 1957 1958 $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1959 $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1960 1961 // Mark all notifications as read from any sender up to the time the third message was sent. 1962 core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 2); 1963 1964 $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1965 $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1966 1967 // Mark all notifications as read from any sender with a time after all messages were sent. 1968 core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 10); 1969 1970 $this->assertEquals(4, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1971 $this->assertEquals(0, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1972 } 1973 1974 /** 1975 * Test get_user_notification_preferences 1976 */ 1977 public function test_get_user_notification_preferences() { 1978 $this->resetAfterTest(true); 1979 1980 $user = self::getDataGenerator()->create_user(); 1981 $this->setUser($user); 1982 1983 // Set a couple of preferences to test. 1984 set_user_preference('message_provider_mod_assign_assign_notification_enabled', 'popup', $user); 1985 1986 $prefs = core_message_external::get_user_notification_preferences(); 1987 $prefs = \external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs); 1988 // Check processors. 1989 $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors'])); 1990 $this->assertEquals($user->id, $prefs['preferences']['userid']); 1991 1992 // Check components. 1993 $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components'])); 1994 1995 // Check some preferences that we previously set. 1996 $found = 0; 1997 foreach ($prefs['preferences']['components'] as $component) { 1998 foreach ($component['notifications'] as $prefdata) { 1999 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') { 2000 continue; 2001 } 2002 foreach ($prefdata['processors'] as $processor) { 2003 if ($processor['name'] == 'popup') { 2004 $this->assertTrue($processor['enabled']); 2005 $found = 1; 2006 } 2007 } 2008 } 2009 } 2010 $this->assertEquals(1, $found); 2011 } 2012 2013 /** 2014 * Test get_user_notification_preferences permissions 2015 */ 2016 public function test_get_user_notification_preferences_permissions() { 2017 $this->resetAfterTest(true); 2018 2019 $user = self::getDataGenerator()->create_user(); 2020 $otheruser = self::getDataGenerator()->create_user(); 2021 $this->setUser($user); 2022 2023 $this->expectException('moodle_exception'); 2024 $prefs = core_message_external::get_user_notification_preferences($otheruser->id); 2025 } 2026 2027 /** 2028 * Tests searching for users when site-wide messaging is disabled. 2029 * 2030 * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view. 2031 * If checks this by placing some users in the same course, where default caps would permit a user to view another user's 2032 * profile. 2033 */ 2034 public function test_message_search_users_messagingallusers_disabled() { 2035 global $DB; 2036 $this->resetAfterTest(); 2037 2038 // Create some users. 2039 $users = []; 2040 foreach (range(1, 8) as $i) { 2041 $user = new \stdClass(); 2042 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2043 $user->lastname = $i; 2044 $user = $this->getDataGenerator()->create_user($user); 2045 $users[$i] = $user; 2046 } 2047 2048 // Enrol a few users in the same course, but leave them as non-contacts. 2049 $course1 = $this->getDataGenerator()->create_course(); 2050 $course2 = $this->getDataGenerator()->create_course(); 2051 2052 $this->setAdminUser(); 2053 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2054 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2055 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2056 2057 // Add some other users as contacts. 2058 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2059 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2060 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2061 2062 // Enrol a user as a teacher in the course, and make the teacher role a course contact role. 2063 $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher'); 2064 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 2065 set_config('coursecontact', $teacherrole->id); 2066 2067 // Create individual conversations between some users, one contact and one non-contact. 2068 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2069 [$users[1]->id, $users[2]->id]); 2070 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2071 [$users[6]->id, $users[1]->id]); 2072 2073 // Create a group conversation between 4 users, including a contact and a non-contact. 2074 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2075 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat'); 2076 2077 // Set as the user performing the search. 2078 $this->setUser($users[1]); 2079 2080 // Perform a search with $CFG->messagingallusers disabled. 2081 set_config('messagingallusers', 0); 2082 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2083 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2084 2085 // Confirm that we returns contacts and non-contacts. 2086 $this->assertArrayHasKey('contacts', $result); 2087 $this->assertArrayHasKey('noncontacts', $result); 2088 $contacts = $result['contacts']; 2089 $noncontacts = $result['noncontacts']; 2090 2091 // Check that we retrieved the correct contacts. 2092 $this->assertCount(2, $contacts); 2093 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2094 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2095 2096 // Verify the correct conversations were returned for the contacts. 2097 $this->assertCount(2, $contacts[0]['conversations']); 2098 // We can't rely on the ordering of conversations within the results, so sort by id first. 2099 usort($contacts[0]['conversations'], function($a, $b) { 2100 return $b['id'] <=> $a['id']; 2101 }); 2102 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']); 2103 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']); 2104 2105 $this->assertCount(0, $contacts[1]['conversations']); 2106 2107 // Check that we retrieved the correct non-contacts. 2108 // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles 2109 // are visible in that course. This excludes users like course contacts. 2110 $this->assertCount(3, $noncontacts); 2111 // Self-conversation first. 2112 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2113 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2114 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2115 2116 // Verify the correct conversations were returned for the non-contacts. 2117 $this->assertCount(1, $noncontacts[1]['conversations']); 2118 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']); 2119 2120 $this->assertCount(1, $noncontacts[2]['conversations']); 2121 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']); 2122 } 2123 2124 /** 2125 * Tests searching for users when site-wide messaging is enabled. 2126 * 2127 * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user 2128 * can view their respective profile. 2129 */ 2130 public function test_message_search_users_messagingallusers_enabled() { 2131 global $DB; 2132 $this->resetAfterTest(); 2133 2134 // Create some users. 2135 $users = []; 2136 foreach (range(1, 9) as $i) { 2137 $user = new \stdClass(); 2138 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2139 $user->lastname = $i; 2140 $user = $this->getDataGenerator()->create_user($user); 2141 $users[$i] = $user; 2142 } 2143 2144 // Enrol a few users in the same course, but leave them as non-contacts. 2145 $course1 = $this->getDataGenerator()->create_course(); 2146 $course2 = $this->getDataGenerator()->create_course(); 2147 2148 $this->setAdminUser(); 2149 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2150 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2151 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2152 2153 // Add some other users as contacts. 2154 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2155 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2156 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2157 2158 // Enrol a user as a teacher in the course, and make the teacher role a course contact role. 2159 $this->getDataGenerator()->enrol_user($users[9]->id, $course2->id, 'editingteacher'); 2160 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 2161 set_config('coursecontact', $teacherrole->id); 2162 2163 // Create individual conversations between some users, one contact and one non-contact. 2164 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2165 [$users[1]->id, $users[2]->id]); 2166 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2167 [$users[6]->id, $users[1]->id]); 2168 2169 // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course. 2170 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2171 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat'); 2172 2173 // Set as the user performing the search. 2174 $this->setUser($users[1]); 2175 2176 // Perform a search with $CFG->messagingallusers enabled. 2177 set_config('messagingallusers', 1); 2178 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2179 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2180 2181 // Confirm that we returns contacts and non-contacts. 2182 $this->assertArrayHasKey('contacts', $result); 2183 $this->assertArrayHasKey('noncontacts', $result); 2184 $contacts = $result['contacts']; 2185 $noncontacts = $result['noncontacts']; 2186 2187 // Check that we retrieved the correct contacts. 2188 $this->assertCount(2, $contacts); 2189 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2190 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2191 2192 // Verify the correct conversations were returned for the contacts. 2193 $this->assertCount(2, $contacts[0]['conversations']); 2194 // We can't rely on the ordering of conversations within the results, so sort by id first. 2195 usort($contacts[0]['conversations'], function($a, $b) { 2196 return $b['id'] <=> $a['id']; 2197 }); 2198 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']); 2199 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']); 2200 2201 $this->assertCount(0, $contacts[1]['conversations']); 2202 2203 // Check that we retrieved the correct non-contacts. 2204 // If site wide messaging is enabled, we expect to be able to search for any users whose profiles we can view. 2205 // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1. 2206 $this->assertCount(4, $noncontacts); 2207 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2208 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2209 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2210 $this->assertEquals($users[9]->id, $noncontacts[3]['id']); 2211 2212 // Verify the correct conversations were returned for the non-contacts. 2213 $this->assertCount(1, $noncontacts[1]['conversations']); 2214 $this->assertCount(1, $noncontacts[2]['conversations']); 2215 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']); 2216 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']); 2217 $this->assertCount(0, $noncontacts[3]['conversations']); 2218 } 2219 2220 /** 2221 * Verify searching for users find themselves when they have self-conversations. 2222 */ 2223 public function test_message_search_users_self_conversations() { 2224 $this->resetAfterTest(); 2225 2226 // Create some users. 2227 $user1 = new \stdClass(); 2228 $user1->firstname = 'User'; 2229 $user1->lastname = 'One'; 2230 $user1 = $this->getDataGenerator()->create_user($user1); 2231 $user2 = new \stdClass(); 2232 $user2->firstname = 'User'; 2233 $user2->lastname = 'Two'; 2234 $user2 = $this->getDataGenerator()->create_user($user2); 2235 2236 // Get self-conversation for user1. 2237 $sc1 = \core_message\api::get_self_conversation($user1->id); 2238 testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!'); 2239 2240 // Perform a search as user1. 2241 $this->setUser($user1); 2242 $result = core_message_external::message_search_users($user1->id, 'One'); 2243 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2244 2245 // Check results are empty. 2246 $this->assertCount(0, $result['contacts']); 2247 $this->assertCount(1, $result['noncontacts']); 2248 } 2249 2250 /** 2251 * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found. 2252 */ 2253 public function test_message_search_users_with_empty_result() { 2254 $this->resetAfterTest(); 2255 2256 // Create some users, but make sure neither will match the search term. 2257 $user1 = new \stdClass(); 2258 $user1->firstname = 'User'; 2259 $user1->lastname = 'One'; 2260 $user1 = $this->getDataGenerator()->create_user($user1); 2261 $user2 = new \stdClass(); 2262 $user2->firstname = 'User'; 2263 $user2->lastname = 'Two'; 2264 $user2 = $this->getDataGenerator()->create_user($user2); 2265 2266 // Perform a search as user1. 2267 $this->setUser($user1); 2268 $result = core_message_external::message_search_users($user1->id, 'search'); 2269 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2270 2271 // Check results are empty. 2272 $this->assertCount(0, $result['contacts']); 2273 $this->assertCount(0, $result['noncontacts']); 2274 } 2275 2276 /** 2277 * Test verifying that limits and offsets work for both the contacts and non-contacts return data. 2278 */ 2279 public function test_message_search_users_limit_offset() { 2280 $this->resetAfterTest(); 2281 2282 // Create 20 users. 2283 $users = []; 2284 foreach (range(1, 20) as $i) { 2285 $user = new \stdClass(); 2286 $user->firstname = "User search"; 2287 $user->lastname = $i; 2288 $user = $this->getDataGenerator()->create_user($user); 2289 $users[$i] = $user; 2290 } 2291 2292 // Enrol the first 8 users in the same course, but leave them as non-contacts. 2293 $this->setAdminUser(); 2294 $course1 = $this->getDataGenerator()->create_course(); 2295 foreach (range(1, 8) as $i) { 2296 $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id); 2297 } 2298 2299 // Add 5 users, starting at the 11th user, as contacts for user1. 2300 foreach (range(11, 15) as $i) { 2301 \core_message\api::add_contact($users[1]->id, $users[$i]->id); 2302 } 2303 2304 // Set as the user performing the search. 2305 $this->setUser($users[1]); 2306 2307 // Search using a limit of 3. 2308 // This tests the case where we have more results than the limit for both contacts and non-contacts. 2309 $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3); 2310 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2311 $contacts = $result['contacts']; 2312 $noncontacts = $result['noncontacts']; 2313 2314 // Check that we retrieved the correct contacts. 2315 $this->assertCount(3, $contacts); 2316 $this->assertEquals($users[11]->id, $contacts[0]['id']); 2317 $this->assertEquals($users[12]->id, $contacts[1]['id']); 2318 $this->assertEquals($users[13]->id, $contacts[2]['id']); 2319 2320 // Check that we retrieved the correct non-contacts. 2321 // Consider first conversation is self-conversation. 2322 $this->assertCount(3, $noncontacts); 2323 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2324 $this->assertEquals($users[2]->id, $noncontacts[1]['id']); 2325 $this->assertEquals($users[3]->id, $noncontacts[2]['id']); 2326 2327 // Now, offset to get the next batch of results. 2328 // We expect to see 2 contacts, and 3 non-contacts. 2329 $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3); 2330 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2331 $contacts = $result['contacts']; 2332 $noncontacts = $result['noncontacts']; 2333 $this->assertCount(2, $contacts); 2334 $this->assertEquals($users[14]->id, $contacts[0]['id']); 2335 $this->assertEquals($users[15]->id, $contacts[1]['id']); 2336 2337 $this->assertCount(3, $noncontacts); 2338 $this->assertEquals($users[4]->id, $noncontacts[0]['id']); 2339 $this->assertEquals($users[5]->id, $noncontacts[1]['id']); 2340 $this->assertEquals($users[6]->id, $noncontacts[2]['id']); 2341 2342 // Now, offset to get the next batch of results. 2343 // We expect to see 0 contacts, and 2 non-contacts. 2344 $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3); 2345 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2346 $contacts = $result['contacts']; 2347 $noncontacts = $result['noncontacts']; 2348 $this->assertCount(0, $contacts); 2349 2350 $this->assertCount(2, $noncontacts); 2351 $this->assertEquals($users[7]->id, $noncontacts[0]['id']); 2352 $this->assertEquals($users[8]->id, $noncontacts[1]['id']); 2353 } 2354 2355 /** 2356 * Tests searching users as another user having the 'moodle/user:viewdetails' capability. 2357 */ 2358 public function test_message_search_users_with_cap() { 2359 $this->resetAfterTest(); 2360 global $DB; 2361 2362 // Create some users. 2363 $users = []; 2364 foreach (range(1, 8) as $i) { 2365 $user = new \stdClass(); 2366 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2367 $user->lastname = $i; 2368 $user = $this->getDataGenerator()->create_user($user); 2369 $users[$i] = $user; 2370 } 2371 2372 // Enrol a few users in the same course, but leave them as non-contacts. 2373 $course1 = $this->getDataGenerator()->create_course(); 2374 $this->setAdminUser(); 2375 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2376 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2377 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2378 2379 // Add some other users as contacts. 2380 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2381 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2382 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2383 2384 // Set as the user performing the search. 2385 $this->setUser($users[1]); 2386 2387 // Grant the authenticated user role the capability 'user:viewdetails' at site context. 2388 $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST); 2389 assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, \context_system::instance()); 2390 2391 // Perform a search with $CFG->messagingallusers disabled. 2392 set_config('messagingallusers', 0); 2393 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2394 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2395 $contacts = $result['contacts']; 2396 $noncontacts = $result['noncontacts']; 2397 2398 // Check that we retrieved the correct contacts. 2399 $this->assertCount(2, $contacts); 2400 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2401 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2402 2403 // Check that we retrieved the correct non-contacts. 2404 // Site-wide messaging is disabled, so we expect to be able to search for any users whose profile we can view. 2405 // Consider first conversations is self-conversation. 2406 $this->assertCount(3, $noncontacts); 2407 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2408 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2409 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2410 } 2411 2412 /** 2413 * Tests searching users as another user without the 'moodle/user:viewdetails' capability. 2414 */ 2415 public function test_message_search_users_without_cap() { 2416 $this->resetAfterTest(); 2417 2418 // Create some users. 2419 $user1 = $this->getDataGenerator()->create_user(); 2420 $user2 = $this->getDataGenerator()->create_user(); 2421 2422 // The person doing the search for another user. 2423 $this->setUser($user1); 2424 2425 // Ensure an exception is thrown. 2426 $this->expectException('moodle_exception'); 2427 core_message_external::message_search_users($user2->id, 'User'); 2428 $this->assertDebuggingCalled(); 2429 } 2430 2431 /** 2432 * Tests searching users with messaging disabled. 2433 */ 2434 public function test_message_search_users_messaging_disabled() { 2435 $this->resetAfterTest(); 2436 2437 // Create some skeleton data just so we can call the WS. 2438 $user = $this->getDataGenerator()->create_user(); 2439 2440 // The person doing the search. 2441 $this->setUser($user); 2442 2443 // Disable messaging. 2444 set_config('messaging', 0); 2445 2446 // Ensure an exception is thrown. 2447 $this->expectException('moodle_exception'); 2448 core_message_external::message_search_users($user->id, 'User'); 2449 } 2450 2451 /** 2452 * Tests searching messages. 2453 */ 2454 public function test_messagearea_search_messages() { 2455 $this->resetAfterTest(true); 2456 2457 // Create some users. 2458 $user1 = self::getDataGenerator()->create_user(); 2459 $user2 = self::getDataGenerator()->create_user(); 2460 2461 // The person doing the search. 2462 $this->setUser($user1); 2463 2464 // Send some messages back and forth. 2465 $time = time(); 2466 $this->send_message($user1, $user2, 'Yo!', 0, $time); 2467 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 2468 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 2469 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 2470 $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 2471 2472 // Perform a search. 2473 $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o'); 2474 2475 // We need to execute the return values cleaning process to simulate the web service server. 2476 $result = \external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result); 2477 2478 // Confirm the data is correct. 2479 $messages = $result['contacts']; 2480 $this->assertCount(2, $messages); 2481 2482 $message1 = $messages[0]; 2483 $message2 = $messages[1]; 2484 2485 $this->assertEquals($user2->id, $message1['userid']); 2486 $this->assertEquals(fullname($user2), $message1['fullname']); 2487 $this->assertTrue($message1['ismessaging']); 2488 $this->assertFalse($message1['sentfromcurrentuser']); 2489 $this->assertEquals('Word.', $message1['lastmessage']); 2490 $this->assertNotEmpty($message1['messageid']); 2491 $this->assertNull($message1['isonline']); 2492 $this->assertFalse($message1['isread']); 2493 $this->assertFalse($message1['isblocked']); 2494 $this->assertNull($message1['unreadcount']); 2495 $this->assertEquals($convid, $message1['conversationid']); 2496 2497 $this->assertEquals($user2->id, $message2['userid']); 2498 $this->assertEquals(fullname($user2), $message2['fullname']); 2499 $this->assertTrue($message2['ismessaging']); 2500 $this->assertTrue($message2['sentfromcurrentuser']); 2501 $this->assertEquals('Yo!', $message2['lastmessage']); 2502 $this->assertNotEmpty($message2['messageid']); 2503 $this->assertNull($message2['isonline']); 2504 $this->assertTrue($message2['isread']); 2505 $this->assertFalse($message2['isblocked']); 2506 $this->assertNull($message2['unreadcount']); 2507 $this->assertEquals($convid, $message2['conversationid']); 2508 } 2509 2510 /** 2511 * Tests searching messages as another user. 2512 */ 2513 public function test_messagearea_search_messages_as_other_user() { 2514 $this->resetAfterTest(true); 2515 2516 // The person doing the search. 2517 $this->setAdminUser(); 2518 2519 // Create some users. 2520 $user1 = self::getDataGenerator()->create_user(); 2521 $user2 = self::getDataGenerator()->create_user(); 2522 2523 // Send some messages back and forth. 2524 $time = time(); 2525 $this->send_message($user1, $user2, 'Yo!', 0, $time); 2526 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 2527 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 2528 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 2529 2530 // Perform a search. 2531 $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o'); 2532 2533 // We need to execute the return values cleaning process to simulate the web service server. 2534 $result = \external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), 2535 $result); 2536 2537 // Confirm the data is correct. 2538 $messages = $result['contacts']; 2539 $this->assertCount(2, $messages); 2540 2541 $message1 = $messages[0]; 2542 $message2 = $messages[1]; 2543 2544 $this->assertEquals($user2->id, $message1['userid']); 2545 $this->assertEquals(fullname($user2), $message1['fullname']); 2546 $this->assertTrue($message1['ismessaging']); 2547 $this->assertFalse($message1['sentfromcurrentuser']); 2548 $this->assertEquals('Word.', $message1['lastmessage']); 2549 $this->assertNotEmpty($message1['messageid']); 2550 $this->assertFalse($message1['isonline']); 2551 $this->assertFalse($message1['isread']); 2552 $this->assertFalse($message1['isblocked']); 2553 $this->assertNull($message1['unreadcount']); 2554 2555 $this->assertEquals($user2->id, $message2['userid']); 2556 $this->assertEquals(fullname($user2), $message2['fullname']); 2557 $this->assertTrue($message2['ismessaging']); 2558 $this->assertTrue($message2['sentfromcurrentuser']); 2559 $this->assertEquals('Yo!', $message2['lastmessage']); 2560 $this->assertNotEmpty($message2['messageid']); 2561 $this->assertFalse($message2['isonline']); 2562 $this->assertTrue($message2['isread']); 2563 $this->assertFalse($message2['isblocked']); 2564 $this->assertNull($message2['unreadcount']); 2565 } 2566 2567 /** 2568 * Tests searching messages as another user without the proper capabilities. 2569 */ 2570 public function test_messagearea_search_messages_as_other_user_without_cap() { 2571 $this->resetAfterTest(true); 2572 2573 // Create some users. 2574 $user1 = self::getDataGenerator()->create_user(); 2575 $user2 = self::getDataGenerator()->create_user(); 2576 2577 // The person doing the search for another user. 2578 $this->setUser($user1); 2579 2580 // Ensure an exception is thrown. 2581 $this->expectException('moodle_exception'); 2582 core_message_external::data_for_messagearea_search_messages($user2->id, 'Search'); 2583 } 2584 2585 /** 2586 * Tests searching messages with messaging disabled 2587 */ 2588 public function test_messagearea_search_messages_messaging_disabled() { 2589 global $CFG; 2590 2591 $this->resetAfterTest(true); 2592 2593 // Create some skeleton data just so we can call the WS. 2594 $user = self::getDataGenerator()->create_user(); 2595 2596 // The person doing the search . 2597 $this->setUser($user); 2598 2599 // Disable messaging. 2600 $CFG->messaging = 0; 2601 2602 // Ensure an exception is thrown. 2603 $this->expectException('moodle_exception'); 2604 core_message_external::data_for_messagearea_search_messages($user->id, 'Search'); 2605 } 2606 2607 /** 2608 * Tests retrieving contacts. 2609 */ 2610 public function test_get_user_contacts() { 2611 $this->resetAfterTest(true); 2612 2613 // Create some users. 2614 $user1 = self::getDataGenerator()->create_user(); 2615 2616 // Set as the user. 2617 $this->setUser($user1); 2618 2619 $user2 = new \stdClass(); 2620 $user2->firstname = 'User'; 2621 $user2->lastname = 'A'; 2622 $user2 = self::getDataGenerator()->create_user($user2); 2623 2624 $user3 = new \stdClass(); 2625 $user3->firstname = 'User'; 2626 $user3->lastname = 'B'; 2627 $user3 = self::getDataGenerator()->create_user($user3); 2628 2629 $user4 = new \stdClass(); 2630 $user4->firstname = 'User'; 2631 $user4->lastname = 'C'; 2632 $user4 = self::getDataGenerator()->create_user($user4); 2633 2634 $user5 = new \stdClass(); 2635 $user5->firstname = 'User'; 2636 $user5->lastname = 'D'; 2637 $user5 = self::getDataGenerator()->create_user($user5); 2638 2639 // Add some users as contacts. 2640 \core_message\api::add_contact($user1->id, $user2->id); 2641 \core_message\api::add_contact($user1->id, $user3->id); 2642 \core_message\api::add_contact($user1->id, $user4->id); 2643 2644 // Retrieve the contacts. 2645 $result = core_message_external::get_user_contacts($user1->id); 2646 2647 // We need to execute the return values cleaning process to simulate the web service server. 2648 $result = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), 2649 $result); 2650 2651 // Confirm the data is correct. 2652 $contacts = $result; 2653 usort($contacts, ['static', 'sort_contacts_id']); 2654 $this->assertCount(3, $contacts); 2655 2656 $contact1 = array_shift($contacts); 2657 $contact2 = array_shift($contacts); 2658 $contact3 = array_shift($contacts); 2659 2660 $this->assertEquals($user2->id, $contact1['id']); 2661 $this->assertEquals(fullname($user2), $contact1['fullname']); 2662 $this->assertTrue($contact1['iscontact']); 2663 2664 $this->assertEquals($user3->id, $contact2['id']); 2665 $this->assertEquals(fullname($user3), $contact2['fullname']); 2666 $this->assertTrue($contact2['iscontact']); 2667 2668 $this->assertEquals($user4->id, $contact3['id']); 2669 $this->assertEquals(fullname($user4), $contact3['fullname']); 2670 $this->assertTrue($contact3['iscontact']); 2671 } 2672 2673 /** 2674 * Tests retrieving contacts as another user. 2675 */ 2676 public function test_get_user_contacts_as_other_user() { 2677 $this->resetAfterTest(true); 2678 2679 $this->setAdminUser(); 2680 2681 // Create some users. 2682 $user1 = self::getDataGenerator()->create_user(); 2683 2684 $user2 = new \stdClass(); 2685 $user2->firstname = 'User'; 2686 $user2->lastname = 'A'; 2687 $user2 = self::getDataGenerator()->create_user($user2); 2688 2689 $user3 = new \stdClass(); 2690 $user3->firstname = 'User'; 2691 $user3->lastname = 'B'; 2692 $user3 = self::getDataGenerator()->create_user($user3); 2693 2694 $user4 = new \stdClass(); 2695 $user4->firstname = 'User'; 2696 $user4->lastname = 'C'; 2697 $user4 = self::getDataGenerator()->create_user($user4); 2698 2699 $user5 = new \stdClass(); 2700 $user5->firstname = 'User'; 2701 $user5->lastname = 'D'; 2702 $user5 = self::getDataGenerator()->create_user($user5); 2703 2704 // Add some users as contacts. 2705 \core_message\api::add_contact($user1->id, $user2->id); 2706 \core_message\api::add_contact($user1->id, $user3->id); 2707 \core_message\api::add_contact($user1->id, $user4->id); 2708 2709 // Retrieve the contacts. 2710 $result = core_message_external::get_user_contacts($user1->id); 2711 2712 // We need to execute the return values cleaning process to simulate the web service server. 2713 $result = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), 2714 $result); 2715 2716 // Confirm the data is correct. 2717 $contacts = $result; 2718 usort($contacts, ['static', 'sort_contacts_id']); 2719 $this->assertCount(3, $contacts); 2720 2721 $contact1 = array_shift($contacts); 2722 $contact2 = array_shift($contacts); 2723 $contact3 = array_shift($contacts); 2724 2725 $this->assertEquals($user2->id, $contact1['id']); 2726 $this->assertEquals(fullname($user2), $contact1['fullname']); 2727 $this->assertTrue($contact1['iscontact']); 2728 2729 $this->assertEquals($user3->id, $contact2['id']); 2730 $this->assertEquals(fullname($user3), $contact2['fullname']); 2731 $this->assertTrue($contact2['iscontact']); 2732 2733 $this->assertEquals($user4->id, $contact3['id']); 2734 $this->assertEquals(fullname($user4), $contact3['fullname']); 2735 $this->assertTrue($contact3['iscontact']); 2736 } 2737 2738 /** 2739 * Tests retrieving contacts as another user without the proper capabilities. 2740 */ 2741 public function test_get_user_contacts_as_other_user_without_cap() { 2742 $this->resetAfterTest(true); 2743 2744 // Create some users. 2745 $user1 = self::getDataGenerator()->create_user(); 2746 $user2 = self::getDataGenerator()->create_user(); 2747 2748 // The person retrieving the contacts for another user. 2749 $this->setUser($user1); 2750 2751 // Perform the WS call and ensure an exception is thrown. 2752 $this->expectException('moodle_exception'); 2753 core_message_external::get_user_contacts($user2->id); 2754 } 2755 2756 /** 2757 * Tests retrieving contacts with messaging disabled. 2758 */ 2759 public function test_get_user_contacts_messaging_disabled() { 2760 global $CFG; 2761 2762 $this->resetAfterTest(true); 2763 2764 // Create some skeleton data just so we can call the WS. 2765 $user = self::getDataGenerator()->create_user(); 2766 2767 // The person retrieving the contacts. 2768 $this->setUser($user); 2769 2770 // Disable messaging. 2771 $CFG->messaging = 0; 2772 2773 // Perform the WS call and ensure we are shown that it is disabled. 2774 $this->expectException('moodle_exception'); 2775 core_message_external::get_user_contacts($user->id); 2776 } 2777 2778 /** 2779 * Test getting contacts when there are no results. 2780 */ 2781 public function test_get_user_contacts_no_results() { 2782 $this->resetAfterTest(); 2783 2784 $user1 = self::getDataGenerator()->create_user(); 2785 2786 $this->setUser($user1); 2787 2788 $requests = core_message_external::get_user_contacts($user1->id); 2789 $requests = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), $requests); 2790 2791 $this->assertEmpty($requests); 2792 } 2793 2794 /** 2795 * Tests get_conversation_messages for retrieving messages. 2796 */ 2797 public function test_get_conversation_messages() { 2798 $this->resetAfterTest(true); 2799 2800 // Create some users. 2801 $user1 = self::getDataGenerator()->create_user(); 2802 $user2 = self::getDataGenerator()->create_user(); 2803 $user3 = self::getDataGenerator()->create_user(); 2804 $user4 = self::getDataGenerator()->create_user(); 2805 $user5 = self::getDataGenerator()->create_user(); 2806 2807 // Create group conversation. 2808 $conversation = \core_message\api::create_conversation( 2809 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2810 [$user1->id, $user2->id, $user3->id, $user4->id] 2811 ); 2812 2813 // The person asking for the messages. 2814 $this->setUser($user1); 2815 2816 // Send some messages back and forth. 2817 $time = time(); 2818 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time); 2819 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1); 2820 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2); 2821 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3); 2822 2823 // Retrieve the messages. 2824 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id); 2825 2826 // We need to execute the return values cleaning process to simulate the web service server. 2827 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2828 $result); 2829 2830 // Check the results are correct. 2831 $this->assertEquals($conversation->id, $result['id']); 2832 2833 // Confirm the members data is correct. 2834 $members = $result['members']; 2835 $this->assertCount(3, $members); 2836 $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']]; 2837 $this->assertContainsEquals($user1->id, $membersid); 2838 $this->assertContainsEquals($user2->id, $membersid); 2839 $this->assertContainsEquals($user3->id, $membersid); 2840 2841 $membersfullnames = [$members[0]['fullname'], $members[1]['fullname'], $members[2]['fullname']]; 2842 $this->assertContainsEquals(fullname($user1), $membersfullnames); 2843 $this->assertContainsEquals(fullname($user2), $membersfullnames); 2844 $this->assertContainsEquals(fullname($user3), $membersfullnames); 2845 2846 // Confirm the messages data is correct. 2847 $messages = $result['messages']; 2848 $this->assertCount(4, $messages); 2849 2850 $message1 = $messages[0]; 2851 $message2 = $messages[1]; 2852 $message3 = $messages[2]; 2853 $message4 = $messages[3]; 2854 2855 $this->assertEquals($user1->id, $message1['useridfrom']); 2856 $this->assertStringContainsString('Yo!', $message1['text']); 2857 2858 $this->assertEquals($user3->id, $message2['useridfrom']); 2859 $this->assertStringContainsString('Sup mang?', $message2['text']); 2860 2861 $this->assertEquals($user2->id, $message3['useridfrom']); 2862 $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']); 2863 2864 $this->assertEquals($user1->id, $message4['useridfrom']); 2865 $this->assertStringContainsString('Word.', $message4['text']); 2866 } 2867 2868 /** 2869 * Tests get_conversation_messages for retrieving messages using timefrom parameter. 2870 */ 2871 public function test_get_conversation_messages_timefrom() { 2872 $this->resetAfterTest(true); 2873 2874 // Create some users. 2875 $user1 = self::getDataGenerator()->create_user(); 2876 $user2 = self::getDataGenerator()->create_user(); 2877 $user3 = self::getDataGenerator()->create_user(); 2878 $user4 = self::getDataGenerator()->create_user(); 2879 2880 // Create group conversation. 2881 $conversation = \core_message\api::create_conversation( 2882 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2883 [$user1->id, $user2->id, $user3->id] 2884 ); 2885 2886 // The person asking for the messages. 2887 $this->setUser($user1); 2888 2889 // Send some messages back and forth. 2890 $time = time(); 2891 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time - 4); 2892 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time - 3); 2893 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 3', $time - 2); 2894 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 4', $time - 1); 2895 2896 // Retrieve the messages from $time - 3, which should be the 3 most recent messages. 2897 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, false, $time - 3); 2898 2899 // We need to execute the return values cleaning process to simulate the web service server. 2900 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2901 $result); 2902 2903 // Check the results are correct. 2904 $this->assertEquals($conversation->id, $result['id']); 2905 2906 // Confirm the messages data is correct. 2907 $messages = $result['messages']; 2908 $this->assertCount(3, $messages); 2909 2910 $message1 = $messages[0]; 2911 $message2 = $messages[1]; 2912 $message3 = $messages[2]; 2913 2914 $this->assertStringContainsString('Message 2', $message1['text']); 2915 $this->assertStringContainsString('Message 3', $message2['text']); 2916 $this->assertStringContainsString('Message 4', $message3['text']); 2917 2918 // Confirm the members data is correct. 2919 $members = $result['members']; 2920 $this->assertCount(1, $members); 2921 $this->assertEquals($user2->id, $members[0]['id']); 2922 } 2923 2924 /** 2925 * Tests get_conversation_messages for retrieving messages as another user. 2926 */ 2927 public function test_get_conversation_messages_as_other_user() { 2928 $this->resetAfterTest(true); 2929 2930 // Set as admin. 2931 $this->setAdminUser(); 2932 2933 // Create some users. 2934 $user1 = self::getDataGenerator()->create_user(); 2935 $user2 = self::getDataGenerator()->create_user(); 2936 $user3 = self::getDataGenerator()->create_user(); 2937 $user4 = self::getDataGenerator()->create_user(); 2938 2939 // Create group conversation. 2940 $conversation = \core_message\api::create_conversation( 2941 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2942 [$user1->id, $user2->id, $user3->id, $user4->id] 2943 ); 2944 2945 // Send some messages back and forth. 2946 $time = time(); 2947 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time); 2948 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1); 2949 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2); 2950 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3); 2951 2952 // Retrieve the messages. 2953 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id); 2954 2955 // We need to execute the return values cleaning process to simulate the web service server. 2956 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2957 $result); 2958 2959 // Check the results are correct. 2960 $this->assertEquals($conversation->id, $result['id']); 2961 2962 // Confirm the members data is correct. 2963 $members = $result['members']; 2964 $this->assertCount(3, $members); 2965 $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']]; 2966 $this->assertContainsEquals($user1->id, $membersid); 2967 $this->assertContainsEquals($user2->id, $membersid); 2968 $this->assertContainsEquals($user3->id, $membersid); 2969 2970 // Confirm the message data is correct. 2971 $messages = $result['messages']; 2972 $this->assertCount(4, $messages); 2973 2974 $message1 = $messages[0]; 2975 $message2 = $messages[1]; 2976 $message3 = $messages[2]; 2977 $message4 = $messages[3]; 2978 2979 $this->assertEquals($user1->id, $message1['useridfrom']); 2980 $this->assertStringContainsString('Yo!', $message1['text']); 2981 2982 $this->assertEquals($user3->id, $message2['useridfrom']); 2983 $this->assertStringContainsString('Sup mang?', $message2['text']); 2984 2985 $this->assertEquals($user2->id, $message3['useridfrom']); 2986 $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']); 2987 2988 $this->assertEquals($user1->id, $message4['useridfrom']); 2989 $this->assertStringContainsString('Word.', $message4['text']); 2990 } 2991 2992 /** 2993 * Tests get_conversation_messages for retrieving messages as another user without the proper capabilities. 2994 */ 2995 public function test_get_conversation_messages_as_other_user_without_cap() { 2996 $this->resetAfterTest(true); 2997 2998 // Create some users. 2999 $user1 = self::getDataGenerator()->create_user(); 3000 $user2 = self::getDataGenerator()->create_user(); 3001 $user3 = self::getDataGenerator()->create_user(); 3002 $user4 = self::getDataGenerator()->create_user(); 3003 3004 // Create group conversation. 3005 $conversation = \core_message\api::create_conversation( 3006 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3007 [$user1->id, $user2->id, $user3->id, $user4->id] 3008 ); 3009 3010 // The person asking for the messages for another user. 3011 $this->setUser($user1); 3012 3013 // Ensure an exception is thrown. 3014 $this->expectException('moodle_exception'); 3015 core_message_external::get_conversation_messages($user2->id, $conversation->id); 3016 } 3017 3018 /** 3019 * Tests get_conversation_messages for retrieving messages as another user not in the conversation. 3020 */ 3021 public function test_get_conversation_messages_as_user_not_in_conversation() { 3022 $this->resetAfterTest(true); 3023 3024 // Create some users. 3025 $user1 = self::getDataGenerator()->create_user(); 3026 $user2 = self::getDataGenerator()->create_user(); 3027 $user3 = self::getDataGenerator()->create_user(); // Not in group. 3028 3029 // Create group conversation. 3030 $conversation = \core_message\api::create_conversation( 3031 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3032 [$user1->id, $user2->id] 3033 ); 3034 3035 // The person asking for the messages for a conversation he does not belong to. 3036 $this->setUser($user3); 3037 3038 // Ensure an exception is thrown. 3039 $this->expectExceptionMessage('User is not part of conversation.'); 3040 core_message_external::get_conversation_messages($user3->id, $conversation->id); 3041 } 3042 3043 /** 3044 * Tests get_conversation_messages for retrieving messages with messaging disabled. 3045 */ 3046 public function test_get_conversation_messages_messaging_disabled() { 3047 $this->resetAfterTest(true); 3048 3049 // Create some skeleton data just so we can call the WS. 3050 $user1 = self::getDataGenerator()->create_user(); 3051 $user2 = self::getDataGenerator()->create_user(); 3052 $user3 = self::getDataGenerator()->create_user(); 3053 $user4 = self::getDataGenerator()->create_user(); 3054 3055 // Create group conversation. 3056 $conversation = \core_message\api::create_conversation( 3057 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3058 [$user1->id, $user2->id, $user3->id, $user4->id] 3059 ); 3060 3061 // The person asking for the messages for another user. 3062 $this->setUser($user1); 3063 3064 // Disable messaging. 3065 set_config('messaging', 0); 3066 3067 // Ensure an exception is thrown. 3068 $this->expectException('moodle_exception'); 3069 core_message_external::get_conversation_messages($user1->id, $conversation->id); 3070 } 3071 3072 /** 3073 * Test marking all conversation messages as read with an invalid user. 3074 */ 3075 public function test_mark_all_conversation_messages_as_read_invalid_user_exception() { 3076 $this->resetAfterTest(true); 3077 3078 $user1 = self::getDataGenerator()->create_user(); 3079 $user2 = self::getDataGenerator()->create_user(); 3080 3081 // Send some messages back and forth. 3082 $time = time(); 3083 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3084 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3085 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3086 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3087 3088 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3089 3090 $this->expectException('moodle_exception'); 3091 core_message_external::mark_all_conversation_messages_as_read(-2132131, $conversationid); 3092 } 3093 3094 /** 3095 * Test marking all conversation messages as read without proper access. 3096 */ 3097 public function test_mark_all_conversation_messages_as_read_access_denied_exception() { 3098 $this->resetAfterTest(true); 3099 3100 $user1 = self::getDataGenerator()->create_user(); 3101 $user2 = self::getDataGenerator()->create_user(); 3102 $user3 = self::getDataGenerator()->create_user(); 3103 3104 // Send some messages back and forth. 3105 $time = time(); 3106 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3107 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3108 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3109 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3110 3111 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3112 3113 // User 3 is not in the conversation. 3114 $this->expectException('moodle_exception'); 3115 core_message_external::mark_all_conversation_messages_as_read($user3->id, $conversationid); 3116 } 3117 3118 /** 3119 * Test marking all conversation messages as read for another user. 3120 */ 3121 public function test_mark_all_conversation_messages_as_read_wrong_user() { 3122 $this->resetAfterTest(true); 3123 3124 $user1 = self::getDataGenerator()->create_user(); 3125 $user2 = self::getDataGenerator()->create_user(); 3126 3127 // Send some messages back and forth. 3128 $time = time(); 3129 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3130 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3131 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3132 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3133 3134 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3135 3136 // Can't mark the messages as read for user 2. 3137 $this->setUser($user1); 3138 $this->expectException('moodle_exception'); 3139 core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid); 3140 } 3141 3142 /** 3143 * Test marking all conversation messages as admin. 3144 */ 3145 public function test_mark_all_conversation_messages_as_admin() { 3146 global $DB; 3147 3148 $this->resetAfterTest(true); 3149 3150 $user1 = self::getDataGenerator()->create_user(); 3151 $user2 = self::getDataGenerator()->create_user(); 3152 3153 // Send some messages back and forth. 3154 $time = time(); 3155 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3156 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3157 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3158 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3159 3160 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3161 3162 // Admin can do anything. 3163 $this->setAdminUser(); 3164 core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid); 3165 $this->assertEquals(2, $DB->count_records('message_user_actions')); 3166 } 3167 3168 /** 3169 * Test marking all conversation messages. 3170 */ 3171 public function test_mark_all_conversation_messages_as_read() { 3172 global $DB; 3173 3174 $this->resetAfterTest(true); 3175 3176 $user1 = self::getDataGenerator()->create_user(); 3177 $user2 = self::getDataGenerator()->create_user(); 3178 3179 // Send some messages back and forth. 3180 $time = time(); 3181 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3182 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3183 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3184 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3185 3186 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3187 3188 // We are the user we want to mark the messages for and we are in the conversation, all good. 3189 $this->setUser($user1); 3190 core_message_external::mark_all_conversation_messages_as_read($user1->id, $conversationid); 3191 $this->assertEquals(2, $DB->count_records('message_user_actions')); 3192 } 3193 3194 /** 3195 * Test getting unread conversation count. 3196 */ 3197 public function test_get_unread_conversations_count() { 3198 $this->resetAfterTest(true); 3199 3200 // Create some users. 3201 $user1 = self::getDataGenerator()->create_user(); 3202 $user2 = self::getDataGenerator()->create_user(); 3203 $user3 = self::getDataGenerator()->create_user(); 3204 $user4 = self::getDataGenerator()->create_user(); 3205 3206 // The person wanting the conversation count. 3207 $this->setUser($user1); 3208 3209 // Send some messages back and forth, have some different conversations with different users. 3210 $this->send_message($user1, $user2, 'Yo!'); 3211 $this->send_message($user2, $user1, 'Sup mang?'); 3212 $this->send_message($user1, $user2, 'Writing PHPUnit tests!'); 3213 $this->send_message($user2, $user1, 'Word.'); 3214 3215 $this->send_message($user1, $user3, 'Booyah'); 3216 $this->send_message($user3, $user1, 'Whaaat?'); 3217 $this->send_message($user1, $user3, 'Nothing.'); 3218 $this->send_message($user3, $user1, 'Cool.'); 3219 3220 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3221 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3222 $this->send_message($user1, $user4, 'Dope.'); 3223 3224 // Get the unread conversation count. 3225 $result = core_message_external::get_unread_conversations_count($user1->id); 3226 3227 // We need to execute the return values cleaning process to simulate the web service server. 3228 $result = \external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(), 3229 $result); 3230 3231 $this->assertEquals(3, $result); 3232 } 3233 3234 /** 3235 * Test getting unread conversation count as other user. 3236 */ 3237 public function test_get_unread_conversations_count_as_other_user() { 3238 $this->resetAfterTest(true); 3239 3240 // The person wanting the conversation count. 3241 $this->setAdminUser(); 3242 3243 // Create some users. 3244 $user1 = self::getDataGenerator()->create_user(); 3245 $user2 = self::getDataGenerator()->create_user(); 3246 $user3 = self::getDataGenerator()->create_user(); 3247 $user4 = self::getDataGenerator()->create_user(); 3248 3249 // Send some messages back and forth, have some different conversations with different users. 3250 $this->send_message($user1, $user2, 'Yo!'); 3251 $this->send_message($user2, $user1, 'Sup mang?'); 3252 $this->send_message($user1, $user2, 'Writing PHPUnit tests!'); 3253 $this->send_message($user2, $user1, 'Word.'); 3254 3255 $this->send_message($user1, $user3, 'Booyah'); 3256 $this->send_message($user3, $user1, 'Whaaat?'); 3257 $this->send_message($user1, $user3, 'Nothing.'); 3258 $this->send_message($user3, $user1, 'Cool.'); 3259 3260 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3261 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3262 $this->send_message($user1, $user4, 'Dope.'); 3263 3264 // Get the unread conversation count. 3265 $result = core_message_external::get_unread_conversations_count($user1->id); 3266 3267 // We need to execute the return values cleaning process to simulate the web service server. 3268 $result = \external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(), 3269 $result); 3270 3271 $this->assertEquals(3, $result); 3272 } 3273 3274 /** 3275 * Test getting unread conversation count as other user without proper capability. 3276 */ 3277 public function test_get_unread_conversations_count_as_other_user_without_cap() { 3278 $this->resetAfterTest(true); 3279 3280 // Create some users. 3281 $user1 = self::getDataGenerator()->create_user(); 3282 $user2 = self::getDataGenerator()->create_user(); 3283 3284 // The person wanting the conversation count. 3285 $this->setUser($user1); 3286 3287 // Ensure an exception is thrown. 3288 $this->expectException('moodle_exception'); 3289 core_message_external::get_unread_conversations_count($user2->id); 3290 } 3291 3292 /** 3293 * Test deleting conversations. 3294 */ 3295 public function test_delete_conversations_by_id() { 3296 global $DB; 3297 3298 $this->resetAfterTest(true); 3299 3300 // Create some users. 3301 $user1 = self::getDataGenerator()->create_user(); 3302 $user2 = self::getDataGenerator()->create_user(); 3303 3304 // The person wanting to delete the conversation. 3305 $this->setUser($user1); 3306 3307 // Send some messages back and forth. 3308 $time = time(); 3309 $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time); 3310 $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3311 $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3312 $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3313 3314 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3315 3316 // Delete the conversation. 3317 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3318 3319 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC'); 3320 $this->assertCount(4, $muas); 3321 // Sort by id. 3322 ksort($muas); 3323 3324 $mua1 = array_shift($muas); 3325 $mua2 = array_shift($muas); 3326 $mua3 = array_shift($muas); 3327 $mua4 = array_shift($muas); 3328 3329 $this->assertEquals($user1->id, $mua1->userid); 3330 $this->assertEquals($m1id, $mua1->messageid); 3331 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action); 3332 3333 $this->assertEquals($user1->id, $mua2->userid); 3334 $this->assertEquals($m2id, $mua2->messageid); 3335 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action); 3336 3337 $this->assertEquals($user1->id, $mua3->userid); 3338 $this->assertEquals($m3id, $mua3->messageid); 3339 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action); 3340 3341 $this->assertEquals($user1->id, $mua4->userid); 3342 $this->assertEquals($m4id, $mua4->messageid); 3343 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action); 3344 } 3345 3346 /** 3347 * Test deleting conversations as other user. 3348 */ 3349 public function test_delete_conversations_by_id_as_other_user() { 3350 global $DB; 3351 3352 $this->resetAfterTest(true); 3353 3354 $this->setAdminUser(); 3355 3356 // Create some users. 3357 $user1 = self::getDataGenerator()->create_user(); 3358 $user2 = self::getDataGenerator()->create_user(); 3359 3360 // Send some messages back and forth. 3361 $time = time(); 3362 $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time); 3363 $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3364 $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3365 $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3366 3367 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3368 3369 // Delete the conversation. 3370 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3371 3372 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC'); 3373 $this->assertCount(4, $muas); 3374 // Sort by id. 3375 ksort($muas); 3376 3377 $mua1 = array_shift($muas); 3378 $mua2 = array_shift($muas); 3379 $mua3 = array_shift($muas); 3380 $mua4 = array_shift($muas); 3381 3382 $this->assertEquals($user1->id, $mua1->userid); 3383 $this->assertEquals($m1id, $mua1->messageid); 3384 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action); 3385 3386 $this->assertEquals($user1->id, $mua2->userid); 3387 $this->assertEquals($m2id, $mua2->messageid); 3388 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action); 3389 3390 $this->assertEquals($user1->id, $mua3->userid); 3391 $this->assertEquals($m3id, $mua3->messageid); 3392 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action); 3393 3394 $this->assertEquals($user1->id, $mua4->userid); 3395 $this->assertEquals($m4id, $mua4->messageid); 3396 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action); 3397 } 3398 3399 /** 3400 * Test deleting conversations as other user without proper capability. 3401 */ 3402 public function test_delete_conversations_by_id_as_other_user_without_cap() { 3403 $this->resetAfterTest(true); 3404 3405 // Create some users. 3406 $user1 = self::getDataGenerator()->create_user(); 3407 $user2 = self::getDataGenerator()->create_user(); 3408 $user3 = self::getDataGenerator()->create_user(); 3409 3410 // Send some messages back and forth. 3411 $time = time(); 3412 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3413 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3414 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3415 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3416 3417 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3418 3419 // The person wanting to delete the conversation. 3420 $this->setUser($user3); 3421 3422 // Ensure an exception is thrown. 3423 $this->expectException('moodle_exception'); 3424 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3425 } 3426 3427 /** 3428 * Test deleting conversations with messaging disabled. 3429 */ 3430 public function test_delete_conversations_by_id_messaging_disabled() { 3431 global $CFG; 3432 3433 $this->resetAfterTest(true); 3434 3435 // Create some users. 3436 $user1 = self::getDataGenerator()->create_user(); 3437 $user2 = self::getDataGenerator()->create_user(); 3438 3439 // Send some messages back and forth. 3440 $time = time(); 3441 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3442 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3443 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3444 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 3445 3446 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3447 3448 // The person wanting to delete the conversation. 3449 $this->setUser($user1); 3450 3451 // Disable messaging. 3452 $CFG->messaging = 0; 3453 3454 // Ensure an exception is thrown. 3455 $this->expectException('moodle_exception'); 3456 core_message_external::delete_conversations_by_id($user1->id, [$conversationid]); 3457 } 3458 3459 /** 3460 * Test get message processor. 3461 */ 3462 public function test_get_message_processor() { 3463 $this->resetAfterTest(true); 3464 3465 // Create a user. 3466 $user1 = self::getDataGenerator()->create_user(); 3467 3468 // Set you as the user. 3469 $this->setUser($user1); 3470 3471 // Get the message processors. 3472 $result = core_message_external::get_message_processor($user1->id, 'popup'); 3473 3474 // We need to execute the return values cleaning process to simulate the web service server. 3475 $result = \external_api::clean_returnvalue(core_message_external::get_message_processor_returns(), $result); 3476 3477 $this->assertNotEmpty($result['systemconfigured']); 3478 $this->assertNotEmpty($result['userconfigured']); 3479 } 3480 3481 /** 3482 * Test get_user_notification_preferences 3483 */ 3484 public function test_get_user_message_preferences() { 3485 $this->resetAfterTest(true); 3486 3487 $user = self::getDataGenerator()->create_user(); 3488 $this->setUser($user); 3489 3490 // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody. 3491 set_config('messagingallusers', true); 3492 3493 // Set a couple of preferences to test. 3494 set_user_preference('message_provider_moodle_instantmessage_enabled', 'email', $user); 3495 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user); 3496 3497 $prefs = core_message_external::get_user_message_preferences(); 3498 $prefs = \external_api::clean_returnvalue(core_message_external::get_user_message_preferences_returns(), $prefs); 3499 $this->assertEquals($user->id, $prefs['preferences']['userid']); 3500 3501 // Check components. 3502 $this->assertCount(1, $prefs['preferences']['components']); 3503 $this->assertEquals(\core_message\api::MESSAGE_PRIVACY_SITE, $prefs['blocknoncontacts']); 3504 3505 // Check some preferences that we previously set. 3506 $found = false; 3507 foreach ($prefs['preferences']['components'] as $component) { 3508 foreach ($component['notifications'] as $prefdata) { 3509 if ($prefdata['preferencekey'] != 'message_provider_moodle_instantmessage') { 3510 continue; 3511 } 3512 foreach ($prefdata['processors'] as $processor) { 3513 if ($processor['name'] == 'email') { 3514 $this->assertTrue($processor['enabled']); 3515 $found = true; 3516 } 3517 } 3518 } 3519 } 3520 $this->assertTrue($found); 3521 } 3522 3523 /** 3524 * Test get_user_message_preferences permissions 3525 */ 3526 public function test_get_user_message_preferences_permissions() { 3527 $this->resetAfterTest(true); 3528 3529 $user = self::getDataGenerator()->create_user(); 3530 $otheruser = self::getDataGenerator()->create_user(); 3531 $this->setUser($user); 3532 3533 $this->expectException('moodle_exception'); 3534 $prefs = core_message_external::get_user_message_preferences($otheruser->id); 3535 } 3536 3537 /** 3538 * Comparison function for sorting contacts. 3539 * 3540 * @param array $a 3541 * @param array $b 3542 * @return bool 3543 */ 3544 protected static function sort_contacts($a, $b) { 3545 return $a['userid'] <=> $b['userid']; 3546 } 3547 3548 /** 3549 * Comparison function for sorting contacts. 3550 * 3551 * @param array $a 3552 * @param array $b 3553 * @return bool 3554 */ 3555 protected static function sort_contacts_id($a, $b) { 3556 return $a['id'] <=> $b['id']; 3557 } 3558 3559 /** 3560 * Test verifying that conversations can be marked as favourite conversations. 3561 */ 3562 public function test_set_favourite_conversations_basic() { 3563 $this->resetAfterTest(); 3564 3565 $user1 = self::getDataGenerator()->create_user(); 3566 $user2 = self::getDataGenerator()->create_user(); 3567 $user3 = self::getDataGenerator()->create_user(); 3568 $user4 = self::getDataGenerator()->create_user(); 3569 3570 $this->setUser($user1); 3571 3572 // Now, create some conversations. 3573 $time = time(); 3574 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3575 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3576 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3577 3578 $this->send_message($user1, $user3, 'Booyah'); 3579 $this->send_message($user3, $user1, 'Whaaat?'); 3580 $this->send_message($user1, $user3, 'Nothing.'); 3581 3582 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3583 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3584 3585 // Favourite 2 conversations as user 1. 3586 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3587 $conversation2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]); 3588 $result = core_message_external::set_favourite_conversations($user1->id, [$conversation1, $conversation2]); 3589 3590 // We need to execute the return values cleaning process to simulate the web service server. 3591 $result = \external_api::clean_returnvalue(core_message_external::set_favourite_conversations_returns(), $result); 3592 $this->assertCount(0, $result); 3593 } 3594 3595 /** 3596 * Test confirming that a user can't favourite a conversation on behalf of another user. 3597 */ 3598 public function test_set_favourite_conversations_another_users_conversation() { 3599 $this->resetAfterTest(); 3600 3601 $user1 = self::getDataGenerator()->create_user(); 3602 $user2 = self::getDataGenerator()->create_user(); 3603 $user3 = self::getDataGenerator()->create_user(); 3604 3605 $this->setUser($user3); 3606 3607 // Now, create some conversations. 3608 $time = time(); 3609 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3610 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3611 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3612 3613 $this->send_message($user1, $user3, 'Booyah'); 3614 $this->send_message($user3, $user1, 'Whaaat?'); 3615 $this->send_message($user1, $user3, 'Nothing.'); 3616 3617 // Try to favourite conversation 1 for user 2, as user3. 3618 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3619 $this->expectException(\moodle_exception::class); 3620 $result = core_message_external::set_favourite_conversations($user2->id, [$conversation1]); 3621 } 3622 3623 /** 3624 * 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. 3625 */ 3626 public function test_set_favourite_conversations_non_member() { 3627 $this->resetAfterTest(); 3628 3629 $user1 = self::getDataGenerator()->create_user(); 3630 $user2 = self::getDataGenerator()->create_user(); 3631 $user3 = self::getDataGenerator()->create_user(); 3632 3633 $this->setUser($user3); 3634 3635 // Now, create some conversations. 3636 $time = time(); 3637 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3638 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3639 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3640 3641 $this->send_message($user1, $user3, 'Booyah'); 3642 $this->send_message($user3, $user1, 'Whaaat?'); 3643 $this->send_message($user1, $user3, 'Nothing.'); 3644 3645 // Try to favourite conversation 1 as user 3. 3646 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3647 $conversation2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]); 3648 $this->expectException(\moodle_exception::class); 3649 $result = core_message_external::set_favourite_conversations($user3->id, [$conversation1]); 3650 } 3651 3652 /** 3653 * Test confirming that a user can't favourite a non-existent conversation. 3654 */ 3655 public function test_set_favourite_conversations_non_existent_conversation() { 3656 $this->resetAfterTest(); 3657 3658 $user1 = self::getDataGenerator()->create_user(); 3659 $this->setUser($user1); 3660 3661 // Try to favourite a non-existent conversation. 3662 $this->expectException(\moodle_exception::class); 3663 $result = core_message_external::set_favourite_conversations($user1->id, [0]); 3664 } 3665 3666 /** 3667 * Test confirming that a user can unset a favourite conversation, or list of favourite conversations. 3668 */ 3669 public function test_unset_favourite_conversations_basic() { 3670 $this->resetAfterTest(); 3671 3672 $user1 = self::getDataGenerator()->create_user(); 3673 $user2 = self::getDataGenerator()->create_user(); 3674 $user3 = self::getDataGenerator()->create_user(); 3675 $user4 = self::getDataGenerator()->create_user(); 3676 3677 $this->setUser($user1); 3678 3679 // Now, create some conversations. 3680 $time = time(); 3681 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3682 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3683 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3684 3685 $this->send_message($user1, $user3, 'Booyah'); 3686 $this->send_message($user3, $user1, 'Whaaat?'); 3687 $this->send_message($user1, $user3, 'Nothing.'); 3688 3689 $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?'); 3690 $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.'); 3691 3692 // Favourite 2 conversations as user 1. 3693 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3694 $conversation2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]); 3695 \core_message\api::set_favourite_conversation($conversation1, $user1->id); 3696 \core_message\api::set_favourite_conversation($conversation2, $user1->id); 3697 // Consider first conversations is self-conversation. 3698 $this->assertCount(3, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); 3699 3700 // Unset favourite self-conversation. 3701 $selfconversation = \core_message\api::get_self_conversation($user1->id); 3702 $result = core_message_external::unset_favourite_conversations($user1->id, [$selfconversation->id]); 3703 $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); 3704 3705 // Now, using the web service, unset the favourite conversations. 3706 $result = core_message_external::unset_favourite_conversations($user1->id, [$conversation1, $conversation2]); 3707 3708 // We need to execute the return values cleaning process to simulate the web service server. 3709 $result = \external_api::clean_returnvalue(core_message_external::unset_favourite_conversations_returns(), $result); 3710 $this->assertCount(0, $result); 3711 } 3712 3713 /** 3714 * Test confirming that a user can't unfavourite a conversation for another user. 3715 */ 3716 public function test_unset_favourite_conversations_another_users_conversation() { 3717 $this->resetAfterTest(); 3718 3719 $user1 = self::getDataGenerator()->create_user(); 3720 $user2 = self::getDataGenerator()->create_user(); 3721 $user3 = self::getDataGenerator()->create_user(); 3722 3723 $this->setUser($user3); 3724 3725 // Now, create some conversations. 3726 $time = time(); 3727 $this->send_message($user1, $user2, 'Yo!', 0, $time); 3728 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 3729 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 3730 3731 $this->send_message($user1, $user3, 'Booyah'); 3732 $this->send_message($user3, $user1, 'Whaaat?'); 3733 $this->send_message($user1, $user3, 'Nothing.'); 3734 3735 // Favourite conversation 1 for user1. The current user ($USER) isn't checked for this action. 3736 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3737 \core_message\api::set_favourite_conversation($conversation1, $user1->id); 3738 // Consider first conversations is self-conversation. 3739 $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); 3740 3741 // Try to unfavourite conversation 1 for user 2, as user3. 3742 $conversation1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 3743 $this->expectException(\moodle_exception::class); 3744 $result = core_message_external::unset_favourite_conversations($user2->id, [$conversation1]); 3745 } 3746 3747 /** 3748 * Test confirming that a user can't unfavourite a non-existent conversation. 3749 */ 3750 public function test_unset_favourite_conversations_non_existent_conversation() { 3751 $this->resetAfterTest(); 3752 3753 $user1 = self::getDataGenerator()->create_user(); 3754 $this->setUser($user1); 3755 3756 // Try to unfavourite a non-existent conversation. 3757 $this->expectException(\moodle_exception::class); 3758 $result = core_message_external::unset_favourite_conversations($user1->id, [0]); 3759 } 3760 3761 /** 3762 * Helper to seed the database with initial state. 3763 */ 3764 protected function create_conversation_test_data() { 3765 // Create some users. 3766 $user1 = self::getDataGenerator()->create_user(); 3767 $user2 = self::getDataGenerator()->create_user(); 3768 $user3 = self::getDataGenerator()->create_user(); 3769 $user4 = self::getDataGenerator()->create_user(); 3770 3771 $time = 1; 3772 3773 // Create some conversations. We want: 3774 // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message. 3775 // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message. 3776 // 3) At least one of each type (group, individual) of which user1 IS NOT a member. 3777 // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering). 3778 // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member. 3779 3780 // Individual conversation, user1 is a member, last message from other user. 3781 $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3782 [$user1->id, $user2->id]); 3783 testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time); 3784 testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1); 3785 3786 // Individual conversation, user1 is a member, last message from user1. 3787 $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3788 [$user1->id, $user3->id]); 3789 testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2); 3790 testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3); 3791 3792 // Individual conversation, user1 is not a member. 3793 $ic3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3794 [$user2->id, $user3->id]); 3795 testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4); 3796 testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5); 3797 3798 // Group conversation, user1 is not a member. 3799 $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3800 [$user2->id, $user3->id, $user4->id], 'Project discussions'); 3801 testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6); 3802 testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7); 3803 3804 // Group conversation, user1 is a member, last message from another user. 3805 $gc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3806 [$user1->id, $user3->id, $user4->id], 'Group chat'); 3807 testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8); 3808 testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9); 3809 testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10); 3810 3811 // Group conversation, user1 is a member, last message from user1. 3812 $gc3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3813 [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!'); 3814 testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11); 3815 testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12); 3816 testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13); 3817 3818 // Empty group conversations (x2), user1 is a member. 3819 $gc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3820 [$user1->id, $user2->id, $user3->id], 'Empty group'); 3821 $gc5 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3822 [$user1->id, $user2->id, $user4->id], 'Another empty group'); 3823 3824 // Empty group conversation, user1 is NOT a member. 3825 $gc6 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 3826 [$user2->id, $user3->id, $user4->id], 'Empty group 3'); 3827 3828 return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6]; 3829 } 3830 3831 /** 3832 * Test confirming the basic use of get_conversations, with no limits, nor type or favourite restrictions. 3833 */ 3834 public function test_get_conversations_no_restrictions() { 3835 $this->resetAfterTest(true); 3836 3837 // Get a bunch of conversations, some group, some individual and in different states. 3838 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 3839 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 3840 3841 // The user making the request. 3842 $this->setUser($user1); 3843 3844 // Get all conversations for user1. 3845 $result = core_message_external::get_conversations($user1->id); 3846 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3847 $conversations = $result['conversations']; 3848 3849 $selfconversation = \core_message\api::get_self_conversation($user1->id); 3850 3851 // Verify there are 7 conversations: 2 individual, 2 group with message, 2 group without messages 3852 // and a self-conversation. 3853 // The conversations with the most recent messages should be listed first, followed by the most newly created 3854 // conversations without messages. 3855 $this->assertCount(7, $conversations); 3856 $this->assertEquals($gc3->id, $conversations[0]['id']); 3857 $this->assertEquals($gc2->id, $conversations[1]['id']); 3858 $this->assertEquals($ic2->id, $conversations[2]['id']); 3859 $this->assertEquals($ic1->id, $conversations[3]['id']); 3860 $this->assertEquals($gc5->id, $conversations[4]['id']); 3861 $this->assertEquals($gc4->id, $conversations[5]['id']); 3862 $this->assertEquals($selfconversation->id, $conversations[6]['id']); 3863 3864 foreach ($conversations as $conv) { 3865 $this->assertArrayHasKey('id', $conv); 3866 $this->assertArrayHasKey('name', $conv); 3867 $this->assertArrayHasKey('subname', $conv); 3868 $this->assertArrayHasKey('imageurl', $conv); 3869 $this->assertArrayHasKey('type', $conv); 3870 $this->assertArrayHasKey('membercount', $conv); 3871 $this->assertArrayHasKey('isfavourite', $conv); 3872 $this->assertArrayHasKey('isread', $conv); 3873 $this->assertArrayHasKey('unreadcount', $conv); 3874 $this->assertArrayHasKey('members', $conv); 3875 foreach ($conv['members'] as $member) { 3876 $this->assertArrayHasKey('id', $member); 3877 $this->assertArrayHasKey('fullname', $member); 3878 $this->assertArrayHasKey('profileimageurl', $member); 3879 $this->assertArrayHasKey('profileimageurlsmall', $member); 3880 $this->assertArrayHasKey('isonline', $member); 3881 $this->assertArrayHasKey('showonlinestatus', $member); 3882 $this->assertArrayHasKey('isblocked', $member); 3883 $this->assertArrayHasKey('iscontact', $member); 3884 $this->assertArrayHasKey('isdeleted', $member); 3885 $this->assertArrayHasKey('canmessage', $member); 3886 $this->assertArrayHasKey('requirescontact', $member); 3887 $this->assertArrayHasKey('contactrequests', $member); 3888 } 3889 $this->assertArrayHasKey('messages', $conv); 3890 foreach ($conv['messages'] as $message) { 3891 $this->assertArrayHasKey('id', $message); 3892 $this->assertArrayHasKey('useridfrom', $message); 3893 $this->assertArrayHasKey('text', $message); 3894 $this->assertArrayHasKey('timecreated', $message); 3895 } 3896 } 3897 } 3898 3899 /** 3900 * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately. 3901 */ 3902 public function test_get_conversations_message_format() { 3903 $this->resetAfterTest(); 3904 3905 global $DB; 3906 // Create some users. 3907 $user1 = self::getDataGenerator()->create_user(); 3908 $user2 = self::getDataGenerator()->create_user(); 3909 3910 // Create conversation. 3911 $conversation = \core_message\api::create_conversation( 3912 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 3913 [$user1->id, $user2->id] 3914 ); 3915 3916 // Send some messages back and forth. 3917 $time = 1; 3918 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1); 3919 $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2); 3920 $message = $DB->get_record('messages', ['id' => $mid]); 3921 3922 // The user in scope. 3923 $this->setUser($user1); 3924 3925 // Verify the format of the html message. 3926 $expectedmessagetext = message_format_message_text($message); 3927 $result = core_message_external::get_conversations($user1->id); 3928 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3929 $conversations = $result['conversations']; 3930 $messages = $conversations[0]['messages']; 3931 $this->assertEquals($expectedmessagetext, $messages[0]['text']); 3932 } 3933 3934 /** 3935 * Tests retrieving conversations with a limit and offset to ensure pagination works correctly. 3936 */ 3937 public function test_get_conversations_limit_offset() { 3938 $this->resetAfterTest(true); 3939 3940 // Get a bunch of conversations, some group, some individual and in different states. 3941 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 3942 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 3943 3944 // The user making the request. 3945 $this->setUser($user1); 3946 3947 // Get all conversations for user1. 3948 $result = core_message_external::get_conversations($user1->id, 0, 1); 3949 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3950 $conversations = $result['conversations']; 3951 3952 // Verify the first conversation. 3953 $this->assertCount(1, $conversations); 3954 $conversation = array_shift($conversations); 3955 $this->assertEquals($gc3->id, $conversation['id']); 3956 3957 // Verify the next conversation. 3958 $result = core_message_external::get_conversations($user1->id, 1, 1); 3959 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3960 $conversations = $result['conversations']; 3961 $this->assertCount(1, $conversations); 3962 $this->assertEquals($gc2->id, $conversations[0]['id']); 3963 3964 // Verify the next conversation. 3965 $result = core_message_external::get_conversations($user1->id, 2, 1); 3966 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3967 $conversations = $result['conversations']; 3968 $this->assertCount(1, $conversations); 3969 $this->assertEquals($ic2->id, $conversations[0]['id']); 3970 3971 // Skip one and get both empty conversations. 3972 $result = core_message_external::get_conversations($user1->id, 4, 2); 3973 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 3974 $conversations = $result['conversations']; 3975 $this->assertCount(2, $conversations); 3976 $this->assertEquals($gc5->id, $conversations[0]['id']); 3977 $this->assertEmpty($conversations[0]['messages']); 3978 $this->assertEquals($gc4->id, $conversations[1]['id']); 3979 $this->assertEmpty($conversations[1]['messages']); 3980 3981 // Ask for an offset that doesn't exist and verify no conversations are returned. 3982 $conversations = \core_message\api::get_conversations($user1->id, 10, 1); 3983 $this->assertCount(0, $conversations); 3984 } 3985 3986 /** 3987 * Test verifying the type filtering behaviour of the get_conversations external method. 3988 */ 3989 public function test_get_conversations_type_filter() { 3990 $this->resetAfterTest(true); 3991 3992 // Get a bunch of conversations, some group, some individual and in different states. 3993 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 3994 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 3995 3996 // The user making the request. 3997 $this->setUser($user1); 3998 3999 // Verify we can ask for only individual conversations. 4000 $result = core_message_external::get_conversations($user1->id, 0, 20, 4001 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL); 4002 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4003 $conversations = $result['conversations']; 4004 $this->assertCount(2, $conversations); 4005 4006 // Verify we can ask for only group conversations. 4007 $result = core_message_external::get_conversations($user1->id, 0, 20, 4008 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP); 4009 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4010 $conversations = $result['conversations']; 4011 $this->assertCount(4, $conversations); 4012 4013 // Verify an exception is thrown if an unrecognized type is specified. 4014 $this->expectException(\moodle_exception::class); 4015 core_message_external::get_conversations($user1->id, 0, 20, 0); 4016 } 4017 4018 /** 4019 * Tests retrieving conversations when a 'self' conversation exists. 4020 */ 4021 public function test_get_conversations_self_conversations() { 4022 global $DB; 4023 $this->resetAfterTest(); 4024 4025 // Create a conversation between one user and themself. 4026 $user1 = self::getDataGenerator()->create_user(); 4027 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, 4028 [$user1->id]); 4029 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Test message to self!'); 4030 4031 // Verify we are in a 'self' conversation state. 4032 $members = $DB->get_records('message_conversation_members', ['conversationid' => $conversation->id]); 4033 $this->assertCount(1, $members); 4034 $member = array_pop($members); 4035 $this->assertEquals($user1->id, $member->userid); 4036 4037 // Verify this conversation is returned by the method. 4038 $this->setUser($user1); 4039 $result = core_message_external::get_conversations($user1->id, 0, 20); 4040 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4041 $conversations = $result['conversations']; 4042 $this->assertCount(1, $conversations); 4043 } 4044 4045 /** 4046 * Tests retrieving conversations when a conversation contains a deleted user. 4047 */ 4048 public function test_get_conversations_deleted_user() { 4049 $this->resetAfterTest(true); 4050 4051 // Get a bunch of conversations, some group, some individual and in different states. 4052 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4053 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4054 4055 // The user making the request. 4056 $this->setUser($user1); 4057 4058 $selfconversation = \core_message\api::get_self_conversation($user1->id); 4059 4060 // Delete the second user and retrieve the conversations. 4061 // We should have 6 still, as conversations with soft-deleted users are still returned. 4062 // Group conversations are also present, albeit with less members. 4063 delete_user($user2); 4064 $result = core_message_external::get_conversations($user1->id); 4065 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4066 $conversations = $result['conversations']; 4067 $this->assertCount(7, $conversations); 4068 $this->assertEquals($gc3->id, $conversations[0]['id']); 4069 $this->assertcount(1, $conversations[0]['members']); 4070 $this->assertEquals($gc2->id, $conversations[1]['id']); 4071 $this->assertcount(1, $conversations[1]['members']); 4072 $this->assertEquals($ic2->id, $conversations[2]['id']); 4073 $this->assertEquals($ic1->id, $conversations[3]['id']); 4074 $this->assertEquals($gc5->id, $conversations[4]['id']); 4075 $this->assertEquals($gc4->id, $conversations[5]['id']); 4076 $this->assertEquals($selfconversation->id, $conversations[6]['id']); 4077 4078 // Delete a user from a group conversation where that user had sent the most recent message. 4079 // This user will still be present in the members array, as will the message in the messages array. 4080 delete_user($user4); 4081 $result = core_message_external::get_conversations($user1->id); 4082 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4083 $conversations = $result['conversations']; 4084 $this->assertCount(7, $conversations); 4085 $this->assertEquals($gc2->id, $conversations[1]['id']); 4086 $this->assertcount(1, $conversations[1]['members']); 4087 $this->assertEquals($user4->id, $conversations[1]['members'][0]['id']); 4088 $this->assertcount(1, $conversations[1]['messages']); 4089 $this->assertEquals($user4->id, $conversations[1]['messages'][0]['useridfrom']); 4090 4091 // Delete the third user and retrieve the conversations. 4092 // We should have 7 still (including self-conversation), as conversations with soft-deleted users are still returned. 4093 // Group conversations are also present, albeit with less members. 4094 delete_user($user3); 4095 $result = core_message_external::get_conversations($user1->id); 4096 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4097 $conversations = $result['conversations']; 4098 $this->assertCount(7, $conversations); 4099 $this->assertEquals($gc3->id, $conversations[0]['id']); 4100 $this->assertcount(1, $conversations[0]['members']); 4101 $this->assertEquals($gc2->id, $conversations[1]['id']); 4102 $this->assertcount(1, $conversations[1]['members']); 4103 $this->assertEquals($ic2->id, $conversations[2]['id']); 4104 $this->assertEquals($ic1->id, $conversations[3]['id']); 4105 $this->assertEquals($gc5->id, $conversations[4]['id']); 4106 $this->assertEquals($gc4->id, $conversations[5]['id']); 4107 $this->assertEquals($selfconversation->id, $conversations[6]['id']); 4108 } 4109 4110 /** 4111 * Tests retrieving conversations when a conversation contains a deleted from the database user. 4112 */ 4113 public function test_get_conversations_deleted_user_from_database() { 4114 global $DB; 4115 4116 $this->resetAfterTest(); 4117 4118 $user1 = self::getDataGenerator()->create_user(); 4119 $user2 = self::getDataGenerator()->create_user(); 4120 $user3 = self::getDataGenerator()->create_user(); 4121 4122 $conversation1 = \core_message\api::create_conversation( 4123 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4124 [ 4125 $user1->id, 4126 $user2->id 4127 ], 4128 'Individual conversation 1' 4129 ); 4130 4131 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'A'); 4132 testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'B'); 4133 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'C'); 4134 4135 $conversation2 = \core_message\api::create_conversation( 4136 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4137 [ 4138 $user1->id, 4139 $user3->id 4140 ], 4141 'Individual conversation 2' 4142 ); 4143 4144 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'A'); 4145 testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'B'); 4146 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'C'); 4147 4148 $this->setUser($user1); 4149 4150 // Delete the second user (from DB as well as this could happen in the past). 4151 delete_user($user2); 4152 $DB->delete_records('user', ['id' => $user2->id]); 4153 $result = core_message_external::get_conversations($user1->id, 0, 20, 1, false); 4154 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4155 4156 $conversation = $result['conversations']; 4157 4158 $this->assertCount(1, $conversation); 4159 4160 $conversation = reset($conversation); 4161 4162 $this->assertEquals($conversation2->id, $conversation['id']); 4163 } 4164 4165 /** 4166 * Test verifying the behaviour of get_conversations() when fetching favourite conversations. 4167 */ 4168 public function test_get_conversations_favourite_conversations() { 4169 $this->resetAfterTest(true); 4170 4171 // Get a bunch of conversations, some group, some individual and in different states. 4172 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4173 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4174 4175 // The user making the request. 4176 $this->setUser($user1); 4177 4178 // Unset favourite self-conversation. 4179 $selfconversation = \core_message\api::get_self_conversation($user1->id); 4180 \core_message\api::unset_favourite_conversation($selfconversation->id, $user1->id); 4181 4182 // Try to get ONLY favourite conversations, when no favourites exist. 4183 $result = core_message_external::get_conversations($user1->id, 0, 20, null, true); 4184 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4185 $conversations = $result['conversations']; 4186 $this->assertEquals([], $conversations); 4187 4188 // Try to get NO favourite conversations, when no favourites exist. 4189 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4190 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4191 $conversations = $result['conversations']; 4192 // Consider first conversations is self-conversation. 4193 $this->assertCount(7, $conversations); 4194 4195 // Mark a few conversations as favourites. 4196 \core_message\api::set_favourite_conversation($ic1->id, $user1->id); 4197 \core_message\api::set_favourite_conversation($gc2->id, $user1->id); 4198 \core_message\api::set_favourite_conversation($gc5->id, $user1->id); 4199 4200 // Get the conversations, first with no restrictions, confirming the favourite status of the conversations. 4201 $result = core_message_external::get_conversations($user1->id); 4202 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4203 $conversations = $result['conversations']; 4204 $this->assertCount(7, $conversations); 4205 foreach ($conversations as $conv) { 4206 if (in_array($conv['id'], [$ic1->id, $gc2->id, $gc5->id])) { 4207 $this->assertTrue($conv['isfavourite']); 4208 } 4209 } 4210 4211 // Now, get ONLY favourite conversations. 4212 $result = core_message_external::get_conversations($user1->id, 0, 20, null, true); 4213 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4214 $conversations = $result['conversations']; 4215 $this->assertCount(3, $conversations); 4216 foreach ($conversations as $conv) { 4217 $this->assertTrue($conv['isfavourite']); 4218 } 4219 4220 // Now, try ONLY favourites of type 'group'. 4221 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 4222 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true); 4223 $this->assertCount(2, $conversations); 4224 foreach ($conversations as $conv) { 4225 $this->assertTrue($conv->isfavourite); 4226 } 4227 4228 // And NO favourite conversations. 4229 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4230 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4231 $conversations = $result['conversations']; 4232 $this->assertCount(4, $conversations); 4233 foreach ($conversations as $conv) { 4234 $this->assertFalse($conv['isfavourite']); 4235 } 4236 } 4237 4238 /** 4239 * Test verifying that group linked conversations are returned and contain a subname matching the course name. 4240 */ 4241 public function test_get_conversations_group_linked() { 4242 $this->resetAfterTest(); 4243 global $CFG, $DB; 4244 4245 // Create some users. 4246 $user1 = self::getDataGenerator()->create_user(); 4247 $user2 = self::getDataGenerator()->create_user(); 4248 $user3 = self::getDataGenerator()->create_user(); 4249 4250 $course1 = $this->getDataGenerator()->create_course(); 4251 4252 // Create a group with a linked conversation. 4253 $this->setAdminUser(); 4254 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4255 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4256 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4257 $group1 = $this->getDataGenerator()->create_group([ 4258 'courseid' => $course1->id, 4259 'enablemessaging' => 1, 4260 'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png' 4261 ]); 4262 4263 // Add users to group1. 4264 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); 4265 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); 4266 4267 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4268 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4269 $conversations = $result['conversations']; 4270 4271 $this->assertEquals(2, $conversations[0]['membercount']); 4272 $this->assertEquals($course1->shortname, $conversations[0]['subname']); 4273 $groupimageurl = get_group_picture_url($group1, $group1->courseid, true); 4274 $this->assertEquals($groupimageurl, $conversations[0]['imageurl']); 4275 4276 // Now, disable the conversation linked to the group and verify it's no longer returned. 4277 $DB->set_field('message_conversations', 'enabled', 0, ['id' => $conversations[0]['id']]); 4278 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4279 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4280 $conversations = $result['conversations']; 4281 $this->assertCount(0, $conversations); 4282 } 4283 4284 /** 4285 * Test that group conversations containing MathJax don't break the WebService. 4286 */ 4287 public function test_get_conversations_group_with_mathjax() { 4288 $this->resetAfterTest(true); 4289 $this->setAdminUser(); 4290 4291 // Enable MathJax filter in content and headings. 4292 $this->configure_filters([ 4293 ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true], 4294 ]); 4295 4296 // Create some users, a course and a group with a linked conversation. 4297 $user1 = self::getDataGenerator()->create_user(); 4298 $user2 = self::getDataGenerator()->create_user(); 4299 4300 $coursename = 'Course $$(a+b)=2$$'; 4301 $groupname = 'Group $$(a+b)=2$$'; 4302 $course1 = $this->getDataGenerator()->create_course(['shortname' => $coursename]); 4303 4304 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4305 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4306 $group1 = $this->getDataGenerator()->create_group([ 4307 'name' => $groupname, 4308 'courseid' => $course1->id, 4309 'enablemessaging' => 1, 4310 ]); 4311 4312 // Add users to group1. 4313 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); 4314 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); 4315 4316 // Call the WebService. 4317 $result = core_message_external::get_conversations($user1->id, 0, 20, null, false); 4318 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4319 $conversations = $result['conversations']; 4320 4321 // Format original data. 4322 $coursecontext = \context_course::instance($course1->id); 4323 $coursename = external_format_string($coursename, $coursecontext->id); 4324 $groupname = external_format_string($groupname, $coursecontext->id); 4325 4326 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $conversations[0]['name']); 4327 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $conversations[0]['subname']); 4328 $this->assertEquals($groupname, $conversations[0]['name']); 4329 $this->assertEquals($coursename, $conversations[0]['subname']); 4330 } 4331 4332 /** 4333 * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this 4334 * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want 4335 * to confirm this happens. 4336 */ 4337 public function test_get_conversations_user_in_group_and_individual_chat() { 4338 $this->resetAfterTest(); 4339 4340 $user1 = self::getDataGenerator()->create_user(); 4341 $user2 = self::getDataGenerator()->create_user(); 4342 $user3 = self::getDataGenerator()->create_user(); 4343 4344 $conversation = \core_message\api::create_conversation( 4345 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4346 [ 4347 $user1->id, 4348 $user2->id 4349 ], 4350 'Individual conversation' 4351 ); 4352 4353 testhelper::send_fake_message_to_conversation($user1, $conversation->id); 4354 4355 $conversation = \core_message\api::create_conversation( 4356 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4357 [ 4358 $user1->id, 4359 $user2->id, 4360 ], 4361 'Group conversation' 4362 ); 4363 4364 testhelper::send_fake_message_to_conversation($user1, $conversation->id); 4365 4366 \core_message\api::create_contact_request($user1->id, $user2->id); 4367 \core_message\api::create_contact_request($user1->id, $user3->id); 4368 4369 $this->setUser($user2); 4370 $result = core_message_external::get_conversations($user2->id); 4371 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4372 $conversations = $result['conversations']; 4373 4374 $groupconversation = array_shift($conversations); 4375 $individualconversation = array_shift($conversations); 4376 4377 $this->assertEquals('Group conversation', $groupconversation['name']); 4378 $this->assertEquals('Individual conversation', $individualconversation['name']); 4379 4380 $this->assertCount(1, $groupconversation['members']); 4381 $this->assertCount(1, $individualconversation['members']); 4382 4383 $groupmember = reset($groupconversation['members']); 4384 $this->assertNull($groupmember['requirescontact']); 4385 $this->assertNull($groupmember['canmessage']); 4386 $this->assertEmpty($groupmember['contactrequests']); 4387 4388 $individualmember = reset($individualconversation['members']); 4389 $this->assertNotNull($individualmember['requirescontact']); 4390 $this->assertNotNull($individualmember['canmessage']); 4391 $this->assertNotEmpty($individualmember['contactrequests']); 4392 } 4393 4394 /** 4395 * Test verifying get_conversations identifies if a conversation is muted or not. 4396 */ 4397 public function test_get_conversations_some_muted() { 4398 $this->resetAfterTest(); 4399 4400 // Create some users. 4401 $user1 = self::getDataGenerator()->create_user(); 4402 $user2 = self::getDataGenerator()->create_user(); 4403 $user3 = self::getDataGenerator()->create_user(); 4404 4405 $conversation1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4406 [$user1->id, $user2->id]); 4407 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'Message 1'); 4408 testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'Message 2'); 4409 \core_message\api::mute_conversation($user1->id, $conversation1->id); 4410 4411 $conversation2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4412 [$user1->id, $user3->id]); 4413 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Message 1'); 4414 testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Message 2'); 4415 4416 $conversation3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4417 [$user1->id, $user2->id]); 4418 \core_message\api::mute_conversation($user1->id, $conversation3->id); 4419 4420 $conversation4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4421 [$user1->id, $user3->id]); 4422 4423 $this->setUser($user1); 4424 $result = core_message_external::get_conversations($user1->id); 4425 $result = \external_api::clean_returnvalue(core_message_external::get_conversations_returns(), $result); 4426 $conversations = $result['conversations']; 4427 4428 usort($conversations, function($first, $second){ 4429 return $first['id'] <=> $second['id']; 4430 }); 4431 4432 $selfconversation = array_shift($conversations); 4433 $conv1 = array_shift($conversations); 4434 $conv2 = array_shift($conversations); 4435 $conv3 = array_shift($conversations); 4436 $conv4 = array_shift($conversations); 4437 4438 $this->assertTrue($conv1['ismuted']); 4439 $this->assertFalse($conv2['ismuted']); 4440 $this->assertTrue($conv3['ismuted']); 4441 $this->assertFalse($conv4['ismuted']); 4442 } 4443 4444 /** 4445 * Test returning members in a conversation with no contact requests. 4446 */ 4447 public function test_get_conversation_members_messaging_disabled() { 4448 global $CFG; 4449 4450 $this->resetAfterTest(); 4451 4452 $CFG->messaging = 0; 4453 4454 $this->expectException('moodle_exception'); 4455 core_message_external::get_conversation_members(1, 2); 4456 } 4457 4458 /** 4459 * Test returning members in a conversation with no contact requests. 4460 */ 4461 public function test_get_conversation_members_wrong_user() { 4462 $this->resetAfterTest(); 4463 4464 $user1 = self::getDataGenerator()->create_user(); 4465 $user2 = self::getDataGenerator()->create_user(); 4466 4467 $this->setUser($user2); 4468 4469 $this->expectException('moodle_exception'); 4470 core_message_external::get_conversation_members($user1->id, 2); 4471 } 4472 4473 /** 4474 * Test returning members in a conversation with no contact requests. 4475 */ 4476 public function test_get_conversation_members() { 4477 $this->resetAfterTest(); 4478 4479 $lastaccess = new \stdClass(); 4480 $lastaccess->lastaccess = time(); 4481 4482 $user1 = self::getDataGenerator()->create_user($lastaccess); 4483 $user2 = self::getDataGenerator()->create_user(); 4484 $user3 = self::getDataGenerator()->create_user(); 4485 4486 // This user will not be in the conversation, but a contact request will exist for them. 4487 $user4 = self::getDataGenerator()->create_user(); 4488 4489 // Add some contact requests. 4490 \core_message\api::create_contact_request($user1->id, $user3->id); 4491 \core_message\api::create_contact_request($user1->id, $user4->id); 4492 \core_message\api::create_contact_request($user2->id, $user3->id); 4493 4494 // User 1 and 2 are already contacts. 4495 \core_message\api::add_contact($user1->id, $user2->id); 4496 4497 // User 1 has blocked user 3. 4498 \core_message\api::block_user($user1->id, $user3->id); 4499 4500 $conversation = \core_message\api::create_conversation( 4501 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4502 [ 4503 $user1->id, 4504 $user2->id, 4505 $user3->id 4506 ] 4507 ); 4508 $conversationid = $conversation->id; 4509 4510 $this->setAdminUser(); 4511 4512 $members = core_message_external::get_conversation_members($user1->id, $conversationid, false); 4513 \external_api::clean_returnvalue(core_message_external::get_conversation_members_returns(), $members); 4514 4515 // Sort them by id. 4516 ksort($members); 4517 $this->assertCount(3, $members); 4518 $member1 = array_shift($members); 4519 $member2 = array_shift($members); 4520 $member3 = array_shift($members); 4521 4522 // Confirm the standard fields are OK. 4523 $this->assertEquals($user1->id, $member1->id); 4524 $this->assertEquals(fullname($user1), $member1->fullname); 4525 $this->assertEquals(true, $member1->isonline); 4526 $this->assertEquals(true, $member1->showonlinestatus); 4527 $this->assertEquals(false, $member1->iscontact); 4528 $this->assertEquals(false, $member1->isblocked); 4529 $this->assertObjectHasAttribute('contactrequests', $member1); 4530 $this->assertEmpty($member1->contactrequests); 4531 4532 $this->assertEquals($user2->id, $member2->id); 4533 $this->assertEquals(fullname($user2), $member2->fullname); 4534 $this->assertEquals(false, $member2->isonline); 4535 $this->assertEquals(true, $member2->showonlinestatus); 4536 $this->assertEquals(true, $member2->iscontact); 4537 $this->assertEquals(false, $member2->isblocked); 4538 $this->assertObjectHasAttribute('contactrequests', $member2); 4539 $this->assertEmpty($member2->contactrequests); 4540 4541 $this->assertEquals($user3->id, $member3->id); 4542 $this->assertEquals(fullname($user3), $member3->fullname); 4543 $this->assertEquals(false, $member3->isonline); 4544 $this->assertEquals(true, $member3->showonlinestatus); 4545 $this->assertEquals(false, $member3->iscontact); 4546 $this->assertEquals(true, $member3->isblocked); 4547 $this->assertObjectHasAttribute('contactrequests', $member3); 4548 $this->assertEmpty($member3->contactrequests); 4549 } 4550 4551 /** 4552 * Test returning members in a conversation with contact requests. 4553 */ 4554 public function test_get_conversation_members_with_contact_requests() { 4555 $this->resetAfterTest(); 4556 4557 $lastaccess = new \stdClass(); 4558 $lastaccess->lastaccess = time(); 4559 4560 $user1 = self::getDataGenerator()->create_user($lastaccess); 4561 $user2 = self::getDataGenerator()->create_user(); 4562 $user3 = self::getDataGenerator()->create_user(); 4563 4564 // This user will not be in the conversation, but a contact request will exist for them. 4565 $user4 = self::getDataGenerator()->create_user(); 4566 4567 // Add some contact requests. 4568 \core_message\api::create_contact_request($user1->id, $user2->id); 4569 \core_message\api::create_contact_request($user1->id, $user3->id); 4570 \core_message\api::create_contact_request($user1->id, $user4->id); 4571 \core_message\api::create_contact_request($user2->id, $user3->id); 4572 4573 // User 1 and 2 are already contacts. 4574 \core_message\api::add_contact($user1->id, $user2->id); 4575 // User 1 has blocked user 3. 4576 \core_message\api::block_user($user1->id, $user3->id); 4577 4578 $conversation = \core_message\api::create_conversation( 4579 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4580 [ 4581 $user1->id, 4582 $user2->id, 4583 $user3->id 4584 ] 4585 ); 4586 $conversationid = $conversation->id; 4587 4588 $this->setAdminUser(); 4589 4590 $members = core_message_external::get_conversation_members($user1->id, $conversationid, true); 4591 \external_api::clean_returnvalue(core_message_external::get_conversation_members_returns(), $members); 4592 4593 // Sort them by id. 4594 ksort($members); 4595 $this->assertCount(3, $members); 4596 $member1 = array_shift($members); 4597 $member2 = array_shift($members); 4598 $member3 = array_shift($members); 4599 4600 // Confirm the standard fields are OK. 4601 $this->assertEquals($user1->id, $member1->id); 4602 $this->assertEquals(fullname($user1), $member1->fullname); 4603 $this->assertEquals(true, $member1->isonline); 4604 $this->assertEquals(true, $member1->showonlinestatus); 4605 $this->assertEquals(false, $member1->iscontact); 4606 $this->assertEquals(false, $member1->isblocked); 4607 $this->assertCount(2, $member1->contactrequests); 4608 4609 $this->assertEquals($user2->id, $member2->id); 4610 $this->assertEquals(fullname($user2), $member2->fullname); 4611 $this->assertEquals(false, $member2->isonline); 4612 $this->assertEquals(true, $member2->showonlinestatus); 4613 $this->assertEquals(true, $member2->iscontact); 4614 $this->assertEquals(false, $member2->isblocked); 4615 $this->assertCount(1, $member2->contactrequests); 4616 4617 $this->assertEquals($user3->id, $member3->id); 4618 $this->assertEquals(fullname($user3), $member3->fullname); 4619 $this->assertEquals(false, $member3->isonline); 4620 $this->assertEquals(true, $member3->showonlinestatus); 4621 $this->assertEquals(false, $member3->iscontact); 4622 $this->assertEquals(true, $member3->isblocked); 4623 $this->assertCount(1, $member3->contactrequests); 4624 4625 // Confirm the contact requests are OK. 4626 $request1 = array_shift($member1->contactrequests); 4627 $request2 = array_shift($member1->contactrequests); 4628 4629 $this->assertEquals($user1->id, $request1->userid); 4630 $this->assertEquals($user2->id, $request1->requesteduserid); 4631 4632 $this->assertEquals($user1->id, $request2->userid); 4633 $this->assertEquals($user3->id, $request2->requesteduserid); 4634 4635 $request1 = array_shift($member2->contactrequests); 4636 4637 $this->assertEquals($user1->id, $request1->userid); 4638 $this->assertEquals($user2->id, $request1->requesteduserid); 4639 4640 $request1 = array_shift($member3->contactrequests); 4641 4642 $this->assertEquals($user1->id, $request1->userid); 4643 $this->assertEquals($user3->id, $request1->requesteduserid); 4644 } 4645 4646 /** 4647 * Test returning members in a conversation when you are not a member. 4648 */ 4649 public function test_get_conversation_members_not_a_member() { 4650 $this->resetAfterTest(); 4651 4652 $user1 = self::getDataGenerator()->create_user(); 4653 $user2 = self::getDataGenerator()->create_user(); 4654 4655 // This user will not be in the conversation. 4656 $user3 = self::getDataGenerator()->create_user(); 4657 4658 $conversation = \core_message\api::create_conversation( 4659 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 4660 [ 4661 $user1->id, 4662 $user2->id, 4663 ] 4664 ); 4665 $conversationid = $conversation->id; 4666 4667 $this->setUser($user3); 4668 4669 $this->expectException('moodle_exception'); 4670 core_message_external::get_conversation_members($user3->id, $conversationid); 4671 } 4672 4673 /** 4674 * Test verifying multiple messages can be sent to an individual conversation. 4675 */ 4676 public function test_send_messages_to_conversation_individual() { 4677 $this->resetAfterTest(true); 4678 4679 // Get a bunch of conversations, some group, some individual and in different states. 4680 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4681 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4682 4683 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4684 $course1 = $this->getDataGenerator()->create_course(); 4685 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4686 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4687 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4688 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4689 4690 // The user making the request. 4691 $this->setUser($user1); 4692 4693 // Try to send a message as user1 to a conversation user1 is a a part of. 4694 $messages = [ 4695 [ 4696 'text' => 'a message from user 1', 4697 'textformat' => FORMAT_MOODLE 4698 ], 4699 [ 4700 'text' => 'another message from user 1', 4701 'textformat' => FORMAT_MOODLE 4702 ], 4703 ]; 4704 // Redirect messages. 4705 // This marks messages as read, but we can still observe and verify the number of conversation recipients, 4706 // based on the message_viewed events generated as part of marking the message as read for each user. 4707 $this->preventResetByRollback(); 4708 $sink = $this->redirectMessages(); 4709 $writtenmessages = core_message_external::send_messages_to_conversation($ic1->id, $messages); 4710 4711 \external_api::clean_returnvalue(core_message_external::send_messages_to_conversation_returns(), $writtenmessages); 4712 4713 $this->assertCount(2, $writtenmessages); 4714 $this->assertObjectHasAttribute('id', $writtenmessages[0]); 4715 $this->assertEquals($user1->id, $writtenmessages[0]->useridfrom); 4716 $this->assertEquals('<p>a message from user 1</p>', $writtenmessages[0]->text); 4717 $this->assertNotEmpty($writtenmessages[0]->timecreated); 4718 4719 $this->assertObjectHasAttribute('id', $writtenmessages[1]); 4720 $this->assertEquals($user1->id, $writtenmessages[1]->useridfrom); 4721 $this->assertEquals('<p>another message from user 1</p>', $writtenmessages[1]->text); 4722 $this->assertNotEmpty($writtenmessages[1]->timecreated); 4723 } 4724 4725 /** 4726 * Test verifying multiple messages can be sent to an group conversation. 4727 */ 4728 public function test_send_messages_to_conversation_group() { 4729 $this->resetAfterTest(true); 4730 4731 // Get a bunch of conversations, some group, some individual and in different states. 4732 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4733 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4734 4735 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4736 $course1 = $this->getDataGenerator()->create_course(); 4737 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4738 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4739 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4740 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4741 4742 // The user making the request. 4743 $this->setUser($user1); 4744 4745 // Try to send a message as user1 to a conversation user1 is a a part of. 4746 $messages = [ 4747 [ 4748 'text' => 'a message from user 1 to group conv', 4749 'textformat' => FORMAT_MOODLE 4750 ], 4751 [ 4752 'text' => 'another message from user 1 to group conv', 4753 'textformat' => FORMAT_MOODLE 4754 ], 4755 ]; 4756 // Redirect messages. 4757 // This marks messages as read, but we can still observe and verify the number of conversation recipients, 4758 // based on the message_viewed events generated as part of marking the message as read for each user. 4759 $this->preventResetByRollback(); 4760 $sink = $this->redirectMessages(); 4761 $writtenmessages = core_message_external::send_messages_to_conversation($gc2->id, $messages); 4762 4763 \external_api::clean_returnvalue(core_message_external::send_messages_to_conversation_returns(), $writtenmessages); 4764 4765 $this->assertCount(2, $writtenmessages); 4766 $this->assertObjectHasAttribute('id', $writtenmessages[0]); 4767 $this->assertEquals($user1->id, $writtenmessages[0]->useridfrom); 4768 $this->assertEquals('<p>a message from user 1 to group conv</p>', $writtenmessages[0]->text); 4769 $this->assertNotEmpty($writtenmessages[0]->timecreated); 4770 4771 $this->assertObjectHasAttribute('id', $writtenmessages[1]); 4772 $this->assertEquals($user1->id, $writtenmessages[1]->useridfrom); 4773 $this->assertEquals('<p>another message from user 1 to group conv</p>', $writtenmessages[1]->text); 4774 $this->assertNotEmpty($writtenmessages[1]->timecreated); 4775 } 4776 4777 /** 4778 * Test verifying multiple messages can not be sent to a non existent conversation. 4779 */ 4780 public function test_send_messages_to_conversation_non_existent_conversation() { 4781 $this->resetAfterTest(true); 4782 4783 // Get a bunch of conversations, some group, some individual and in different states. 4784 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4785 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4786 4787 // The user making the request. 4788 $this->setUser($user1); 4789 4790 // Try to send a message as user1 to a conversation user1 is a a part of. 4791 $messages = [ 4792 [ 4793 'text' => 'a message from user 1', 4794 'textformat' => FORMAT_MOODLE 4795 ], 4796 [ 4797 'text' => 'another message from user 1', 4798 'textformat' => FORMAT_MOODLE 4799 ], 4800 ]; 4801 $this->expectException(\moodle_exception::class); 4802 $writtenmessages = core_message_external::send_messages_to_conversation(0, $messages); 4803 } 4804 4805 /** 4806 * Test verifying multiple messages can not be sent to a conversation by a non-member. 4807 */ 4808 public function test_send_messages_to_conversation_non_member() { 4809 $this->resetAfterTest(true); 4810 4811 // Get a bunch of conversations, some group, some individual and in different states. 4812 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4813 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4814 4815 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4816 $course1 = $this->getDataGenerator()->create_course(); 4817 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4818 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4819 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4820 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4821 4822 // The user making the request. This user is not a member of group conversation 1 (gc1). 4823 $this->setUser($user1); 4824 4825 // Try to send a message as user1 to a conversation user1 is a a part of. 4826 $messages = [ 4827 [ 4828 'text' => 'a message from user 1 to group conv', 4829 'textformat' => FORMAT_MOODLE 4830 ], 4831 [ 4832 'text' => 'another message from user 1 to group conv', 4833 'textformat' => FORMAT_MOODLE 4834 ], 4835 ]; 4836 $this->expectException(\moodle_exception::class); 4837 $writtenmessages = core_message_external::send_messages_to_conversation($gc1->id, $messages); 4838 } 4839 4840 /** 4841 * Test verifying a to long message can not be sent to a conversation. 4842 */ 4843 public function test_send_messages_to_conversation_long_text() { 4844 $this->resetAfterTest(true); 4845 4846 // Get a bunch of conversations, some group, some individual and in different states. 4847 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, 4848 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); 4849 4850 // Enrol the users in the same course, so the default privacy controls (course + contacts) can be used. 4851 $course1 = $this->getDataGenerator()->create_course(); 4852 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4853 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4854 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4855 $this->getDataGenerator()->enrol_user($user4->id, $course1->id); 4856 4857 // The user making the request. 4858 $this->setUser($user1); 4859 4860 // Try to send a message as user1 to a conversation user1 is a a part of. 4861 $messages = [ 4862 [ 4863 'text' => str_repeat("M", \core_message\api::MESSAGE_MAX_LENGTH + 100), 4864 'textformat' => FORMAT_MOODLE 4865 ], 4866 ]; 4867 4868 $this->expectException(\moodle_exception::class); 4869 $writtenmessages = core_message_external::send_messages_to_conversation($gc2->id, $messages); 4870 } 4871 4872 /** 4873 * Test getting a conversation that doesn't exist. 4874 */ 4875 public function test_get_conversation_no_conversation() { 4876 $this->resetAfterTest(); 4877 4878 $user1 = self::getDataGenerator()->create_user(); 4879 $user2 = self::getDataGenerator()->create_user(); 4880 4881 $name = 'lol conversation'; 4882 $conversation = \core_message\api::create_conversation( 4883 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4884 [ 4885 $user1->id, 4886 $user2->id, 4887 ], 4888 $name 4889 ); 4890 $conversationid = $conversation->id; 4891 4892 $this->setUser($user1); 4893 4894 $this->expectException('moodle_exception'); 4895 $conv = core_message_external::get_conversation($user1->id, $conversationid + 1); 4896 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4897 } 4898 4899 /** 4900 * Test verifying that the correct favourite information is returned for a non-linked converastion at user context. 4901 */ 4902 public function test_get_conversation_favourited() { 4903 $this->resetAfterTest(); 4904 4905 $user1 = self::getDataGenerator()->create_user(); 4906 $user2 = self::getDataGenerator()->create_user(); 4907 4908 // Create a conversation between the 2 users. 4909 $conversation = \core_message\api::create_conversation( 4910 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4911 [ 4912 $user1->id, 4913 $user2->id, 4914 ], 4915 'An individual conversation' 4916 ); 4917 4918 // Favourite the conversation as user 1 only. 4919 \core_message\api::set_favourite_conversation($conversation->id, $user1->id); 4920 4921 // Get the conversation for user1 and confirm it's favourited. 4922 $this->setUser($user1); 4923 $conv = core_message_external::get_conversation($user1->id, $conversation->id); 4924 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4925 $this->assertTrue($conv['isfavourite']); 4926 4927 // Get the conversation for user2 and confirm it's NOT favourited. 4928 $this->setUser($user2); 4929 $conv = core_message_external::get_conversation($user2->id, $conversation->id); 4930 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4931 $this->assertFalse($conv['isfavourite']); 4932 } 4933 4934 /** 4935 * Test verifying that the correct favourite information is returned for a group-linked conversation at course context. 4936 */ 4937 public function test_get_conversation_favourited_group_linked() { 4938 $this->resetAfterTest(); 4939 global $DB; 4940 4941 $user1 = self::getDataGenerator()->create_user(); 4942 $user2 = self::getDataGenerator()->create_user(); 4943 $user3 = self::getDataGenerator()->create_user(); 4944 4945 $course1 = $this->getDataGenerator()->create_course(); 4946 $course1context = \context_course::instance($course1->id); 4947 4948 // Create a group with a linked conversation and a valid image. 4949 $this->setAdminUser(); 4950 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 4951 $this->getDataGenerator()->enrol_user($user2->id, $course1->id); 4952 $this->getDataGenerator()->enrol_user($user3->id, $course1->id); 4953 $group1 = $this->getDataGenerator()->create_group([ 4954 'courseid' => $course1->id, 4955 'enablemessaging' => 1 4956 ]); 4957 4958 // Add users to group1. 4959 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); 4960 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); 4961 4962 // Verify that the conversation is a group linked conversation in the course context. 4963 $conversationrecord = $DB->get_record('message_conversations', ['component' => 'core_group', 'itemtype' => 'groups']); 4964 $this->assertEquals($course1context->id, $conversationrecord->contextid); 4965 4966 // Favourite the conversation as user 1 only. 4967 \core_message\api::set_favourite_conversation($conversationrecord->id, $user1->id); 4968 4969 // Get the conversation for user1 and confirm it's favourited. 4970 $this->setUser($user1); 4971 $conv = core_message_external::get_conversation($user1->id, $conversationrecord->id); 4972 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4973 $this->assertTrue($conv['isfavourite']); 4974 4975 // Get the conversation for user2 and confirm it's NOT favourited. 4976 $this->setUser($user2); 4977 $conv = core_message_external::get_conversation($user2->id, $conversationrecord->id); 4978 $conv = \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 4979 $this->assertFalse($conv['isfavourite']); 4980 } 4981 4982 /** 4983 * Test getting a conversation with no messages. 4984 */ 4985 public function test_get_conversation_no_messages() { 4986 $this->resetAfterTest(); 4987 4988 $user1 = self::getDataGenerator()->create_user(); 4989 $user2 = self::getDataGenerator()->create_user(); 4990 4991 $name = 'lol conversation'; 4992 $conversation = \core_message\api::create_conversation( 4993 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 4994 [ 4995 $user1->id, 4996 $user2->id, 4997 ], 4998 $name 4999 ); 5000 $conversationid = $conversation->id; 5001 5002 $this->setUser($user1); 5003 5004 $conv = core_message_external::get_conversation($user1->id, $conversationid); 5005 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5006 5007 $conv = (array) $conv; 5008 $this->assertEquals($conversationid, $conv['id']); 5009 $this->assertEquals($name, $conv['name']); 5010 $this->assertArrayHasKey('subname', $conv); 5011 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conv['type']); 5012 $this->assertEquals(2, $conv['membercount']); 5013 $this->assertEquals(false, $conv['isfavourite']); 5014 $this->assertEquals(true, $conv['isread']); 5015 $this->assertEquals(0, $conv['unreadcount']); 5016 $this->assertCount(1, $conv['members']); 5017 foreach ($conv['members'] as $member) { 5018 $member = (array) $member; 5019 $this->assertArrayHasKey('id', $member); 5020 $this->assertArrayHasKey('fullname', $member); 5021 $this->assertArrayHasKey('profileimageurl', $member); 5022 $this->assertArrayHasKey('profileimageurlsmall', $member); 5023 $this->assertArrayHasKey('isonline', $member); 5024 $this->assertArrayHasKey('showonlinestatus', $member); 5025 $this->assertArrayHasKey('isblocked', $member); 5026 $this->assertArrayHasKey('iscontact', $member); 5027 } 5028 $this->assertEmpty($conv['messages']); 5029 } 5030 5031 /** 5032 * Test getting a conversation with messages. 5033 */ 5034 public function test_get_conversation_with_messages() { 5035 $this->resetAfterTest(); 5036 5037 $user1 = self::getDataGenerator()->create_user(); 5038 $user2 = self::getDataGenerator()->create_user(); 5039 $user3 = self::getDataGenerator()->create_user(); 5040 5041 // Some random conversation. 5042 $otherconversation = \core_message\api::create_conversation( 5043 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 5044 [ 5045 $user1->id, 5046 $user3->id, 5047 ] 5048 ); 5049 5050 $conversation = \core_message\api::create_conversation( 5051 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 5052 [ 5053 $user1->id, 5054 $user2->id, 5055 ] 5056 ); 5057 $conversationid = $conversation->id; 5058 5059 $time = time(); 5060 $message1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'A', $time - 10); 5061 $message2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'B', $time - 5); 5062 $message3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'C', $time); 5063 5064 // Add some messages to the other convo to make sure they aren't included. 5065 testhelper::send_fake_message_to_conversation($user1, $otherconversation->id, 'foo'); 5066 5067 $this->setUser($user1); 5068 5069 // Test newest first. 5070 $conv = core_message_external::get_conversation( 5071 $user1->id, 5072 $conversationid, 5073 false, 5074 false, 5075 0, 5076 0, 5077 0, 5078 0, 5079 true 5080 ); 5081 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5082 5083 $conv = (array) $conv; 5084 $this->assertEquals(false, $conv['isread']); 5085 $this->assertEquals(1, $conv['unreadcount']); 5086 $this->assertCount(3, $conv['messages']); 5087 $this->assertEquals($message3id, $conv['messages'][0]->id); 5088 $this->assertEquals($user1->id, $conv['messages'][0]->useridfrom); 5089 $this->assertEquals($message2id, $conv['messages'][1]->id); 5090 $this->assertEquals($user2->id, $conv['messages'][1]->useridfrom); 5091 $this->assertEquals($message1id, $conv['messages'][2]->id); 5092 $this->assertEquals($user1->id, $conv['messages'][2]->useridfrom); 5093 5094 // Test newest last. 5095 $conv = core_message_external::get_conversation( 5096 $user1->id, 5097 $conversationid, 5098 false, 5099 false, 5100 0, 5101 0, 5102 0, 5103 0, 5104 false 5105 ); 5106 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5107 5108 $conv = (array) $conv; 5109 $this->assertCount(3, $conv['messages']); 5110 $this->assertEquals($message3id, $conv['messages'][2]->id); 5111 $this->assertEquals($user1->id, $conv['messages'][2]->useridfrom); 5112 $this->assertEquals($message2id, $conv['messages'][1]->id); 5113 $this->assertEquals($user2->id, $conv['messages'][1]->useridfrom); 5114 $this->assertEquals($message1id, $conv['messages'][0]->id); 5115 $this->assertEquals($user1->id, $conv['messages'][0]->useridfrom); 5116 5117 // Test message offest and limit. 5118 $conv = core_message_external::get_conversation( 5119 $user1->id, 5120 $conversationid, 5121 false, 5122 false, 5123 0, 5124 0, 5125 1, 5126 1, 5127 true 5128 ); 5129 \external_api::clean_returnvalue(core_message_external::get_conversation_returns(), $conv); 5130 5131 $conv = (array) $conv; 5132 $this->assertCount(1, $conv['messages']); 5133 $this->assertEquals($message2id, $conv['messages'][0]->id); 5134 $this->assertEquals($user2->id, $conv['messages'][0]->useridfrom); 5135 } 5136 5137 /** 5138 * Data provider for test_get_conversation_counts(). 5139 */ 5140 public function get_conversation_counts_test_cases() { 5141 $typeindividual = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL; 5142 $typegroup = \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP; 5143 $typeself = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF; 5144 list($user1, $user2, $user3, $user4, $user5, $user6, $user7, $user8) = [0, 1, 2, 3, 4, 5, 6, 7]; 5145 $conversations = [ 5146 [ 5147 'type' => $typeindividual, 5148 'users' => [$user1, $user2], 5149 'messages' => [$user1, $user2, $user2], 5150 'favourites' => [$user1], 5151 'enabled' => null // Individual conversations cannot be disabled. 5152 ], 5153 [ 5154 'type' => $typeindividual, 5155 'users' => [$user1, $user3], 5156 'messages' => [$user1, $user3, $user1], 5157 'favourites' => [], 5158 'enabled' => null // Individual conversations cannot be disabled. 5159 ], 5160 [ 5161 'type' => $typegroup, 5162 'users' => [$user1, $user2, $user3, $user4], 5163 'messages' => [$user1, $user2, $user3, $user4], 5164 'favourites' => [], 5165 'enabled' => true 5166 ], 5167 [ 5168 'type' => $typegroup, 5169 'users' => [$user2, $user3, $user4], 5170 'messages' => [$user2, $user3, $user4], 5171 'favourites' => [], 5172 'enabled' => true 5173 ], 5174 [ 5175 'type' => $typegroup, 5176 'users' => [$user6, $user7], 5177 'messages' => [$user6, $user7, $user7], 5178 'favourites' => [$user6], 5179 'enabled' => false 5180 ], 5181 [ 5182 'type' => $typeself, 5183 'users' => [$user8], 5184 'messages' => [$user8], 5185 'favourites' => [], 5186 'enabled' => null // Individual conversations cannot be disabled. 5187 ], 5188 ]; 5189 5190 return [ 5191 'No conversations' => [ 5192 'conversationConfigs' => $conversations, 5193 'deletemessagesuser' => null, 5194 'deletemessages' => [], 5195 'arguments' => [$user5], 5196 'expectedcounts' => ['favourites' => 1, 'types' => [ 5197 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5198 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5199 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5200 ]], 5201 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5202 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5203 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5204 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5205 ]], 5206 'deletedusers' => [] 5207 ], 5208 'No individual conversations, 2 group conversations' => [ 5209 'conversationConfigs' => $conversations, 5210 'deletemessagesuser' => null, 5211 'deletemessages' => [], 5212 'arguments' => [$user4], 5213 'expectedcounts' => ['favourites' => 1, 'types' => [ 5214 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5215 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5216 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5217 ]], 5218 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5219 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5220 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5221 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5222 ]], 5223 'deletedusers' => [] 5224 ], 5225 '2 individual conversations (one favourited), 1 group conversation' => [ 5226 'conversationConfigs' => $conversations, 5227 'deletemessagesuser' => null, 5228 'deletemessages' => [], 5229 'arguments' => [$user1], 5230 'expectedcounts' => ['favourites' => 2, 'types' => [ 5231 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5232 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5233 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5234 ]], 5235 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5236 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5237 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5238 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5239 ]], 5240 'deletedusers' => [] 5241 ], 5242 '1 individual conversation, 2 group conversations' => [ 5243 'conversationConfigs' => $conversations, 5244 'deletemessagesuser' => null, 5245 'deletemessages' => [], 5246 'arguments' => [$user2], 5247 'expectedcounts' => ['favourites' => 1, 'types' => [ 5248 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5249 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5250 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5251 ]], 5252 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5253 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5254 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5255 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5256 ]], 5257 'deletedusers' => [] 5258 ], 5259 '2 group conversations only' => [ 5260 'conversationConfigs' => $conversations, 5261 'deletemessagesuser' => null, 5262 'deletemessages' => [], 5263 'arguments' => [$user4], 5264 'expectedcounts' => ['favourites' => 1, 'types' => [ 5265 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5266 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5267 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5268 ]], 5269 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5270 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5271 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5272 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5273 ]], 5274 'deletedusers' => [] 5275 ], 5276 'All conversation types, delete a message from individual favourited, messages remaining' => [ 5277 'conversationConfigs' => $conversations, 5278 'deletemessagesuser' => $user1, 5279 'deletemessages' => [0], 5280 'arguments' => [$user1], 5281 'expectedcounts' => ['favourites' => 2, 'types' => [ 5282 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5283 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5284 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5285 ]], 5286 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5287 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5288 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5289 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5290 ]], 5291 'deletedusers' => [] 5292 ], 5293 'All conversation types, delete a message from individual non-favourited, messages remaining' => [ 5294 'conversationConfigs' => $conversations, 5295 'deletemessagesuser' => $user1, 5296 'deletemessages' => [3], 5297 'arguments' => [$user1], 5298 'expectedcounts' => ['favourites' => 2, 'types' => [ 5299 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5300 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5301 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5302 ]], 5303 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5304 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5305 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5306 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5307 ]], 5308 'deletedusers' => [] 5309 ], 5310 'All conversation types, delete all messages from individual favourited, no messages remaining' => [ 5311 'conversationConfigs' => $conversations, 5312 'deletemessagesuser' => $user1, 5313 'deletemessages' => [0, 1, 2], 5314 'arguments' => [$user1], 5315 'expectedcounts' => ['favourites' => 1, 'types' => [ 5316 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5317 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5318 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5319 ]], 5320 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5321 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5322 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5323 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5324 ]], 5325 'deletedusers' => [] 5326 ], 5327 'All conversation types, delete all messages from individual non-favourited, no messages remaining' => [ 5328 'conversationConfigs' => $conversations, 5329 'deletemessagesuser' => $user1, 5330 'deletemessages' => [3, 4, 5], 5331 'arguments' => [$user1], 5332 'expectedcounts' => ['favourites' => 2, 'types' => [ 5333 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5334 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5335 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5336 ]], 5337 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5338 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5339 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5340 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5341 ]], 5342 'deletedusers' => [] 5343 ], 5344 'All conversation types, delete all messages from individual favourited, no messages remaining, different user' => [ 5345 'conversationConfigs' => $conversations, 5346 'deletemessagesuser' => $user1, 5347 'deletemessages' => [0, 1, 2], 5348 'arguments' => [$user2], 5349 'expectedcounts' => ['favourites' => 1, 'types' => [ 5350 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5351 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5352 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5353 ]], 5354 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5355 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5356 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5357 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5358 ]], 5359 'deletedusers' => [] 5360 ], 5361 'All conversation types, delete all messages from individual non-favourited, no messages remaining, different user' => [ 5362 'conversationConfigs' => $conversations, 5363 'deletemessagesuser' => $user1, 5364 'deletemessages' => [3, 4, 5], 5365 'arguments' => [$user3], 5366 'expectedcounts' => ['favourites' => 1, 'types' => [ 5367 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5368 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5369 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5370 ]], 5371 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5372 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5373 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 2, 5374 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5375 ]], 5376 'deletedusers' => [] 5377 ], 5378 'All conversation types, delete some messages from group non-favourited, messages remaining,' => [ 5379 'conversationConfigs' => $conversations, 5380 'deletemessagesuser' => $user1, 5381 'deletemessages' => [6, 7], 5382 'arguments' => [$user1], 5383 'expectedcounts' => ['favourites' => 2, 'types' => [ 5384 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5385 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5386 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5387 ]], 5388 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5389 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5390 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5391 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5392 ]], 5393 'deletedusers' => [] 5394 ], 5395 'All conversation types, delete all messages from group non-favourited, no messages remaining,' => [ 5396 'conversationConfigs' => $conversations, 5397 'deletemessagesuser' => $user1, 5398 'deletemessages' => [6, 7, 8, 9], 5399 'arguments' => [$user1], 5400 'expectedcounts' => ['favourites' => 2, 'types' => [ 5401 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5402 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5403 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5404 ]], 5405 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5406 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5407 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5408 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5409 ]], 5410 'deletedusers' => [] 5411 ], 5412 'All conversation types, another user soft deleted' => [ 5413 'conversationConfigs' => $conversations, 5414 'deletemessagesuser' => null, 5415 'deletemessages' => [], 5416 'arguments' => [$user1], 5417 'expectedcounts' => ['favourites' => 2, 'types' => [ 5418 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5419 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5420 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5421 ]], 5422 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5423 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5424 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5425 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5426 ]], 5427 'deletedusers' => [$user2] 5428 ], 5429 'All conversation types, all group users soft deleted' => [ 5430 'conversationConfigs' => $conversations, 5431 'deletemessagesuser' => null, 5432 'deletemessages' => [], 5433 'arguments' => [$user1], 5434 'expectedcounts' => ['favourites' => 2, 'types' => [ 5435 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5436 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5437 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5438 ]], 5439 'expectedunreadcounts' => ['favourites' => 1, 'types' => [ 5440 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1, 5441 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 1, 5442 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5443 ]], 5444 'deletedusers' => [$user2, $user3, $user4] 5445 ], 5446 'Group conversation which is disabled, favourited' => [ 5447 'conversationConfigs' => $conversations, 5448 'deletemessagesuser' => null, 5449 'deletemessages' => [], 5450 'arguments' => [$user6], 5451 'expectedcounts' => ['favourites' => 1, 'types' => [ 5452 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5453 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5454 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5455 ]], 5456 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5457 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5458 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5459 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5460 ]], 5461 'deletedusers' => [] 5462 ], 5463 'Group conversation which is disabled, non-favourited' => [ 5464 'conversationConfigs' => $conversations, 5465 'deletemessagesuser' => null, 5466 'deletemessages' => [], 5467 'arguments' => [$user7], 5468 'expectedcounts' => ['favourites' => 1, 'types' => [ 5469 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5470 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5471 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5472 ]], 5473 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5474 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5475 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5476 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5477 ]], 5478 'deletedusers' => [] 5479 ], 5480 'Conversation with self' => [ 5481 'conversationConfigs' => $conversations, 5482 'deletemessagesuser' => null, 5483 'deletemessages' => [], 5484 'arguments' => [$user8], 5485 'expectedcounts' => ['favourites' => 0, 'types' => [ 5486 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5487 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5488 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 1 5489 ]], 5490 'expectedunreadcounts' => ['favourites' => 0, 'types' => [ 5491 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 5492 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0, 5493 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => 0 5494 ]], 5495 'deletedusers' => [] 5496 ], 5497 ]; 5498 } 5499 5500 /** 5501 * Test the get_conversation_counts() function. 5502 * 5503 * @dataProvider get_conversation_counts_test_cases() 5504 * @param array $conversationconfigs Conversations to create 5505 * @param int $deletemessagesuser The user who is deleting the messages 5506 * @param array $deletemessages The list of messages to delete (by index) 5507 * @param array $arguments Arguments for the count conversations function 5508 * @param array $expectedcounts the expected conversation counts 5509 * @param array $expectedunreadcounts the expected unread conversation counts 5510 * @param array $deletedusers the array of users to soft delete. 5511 */ 5512 public function test_get_conversation_counts( 5513 $conversationconfigs, 5514 $deletemessagesuser, 5515 $deletemessages, 5516 $arguments, 5517 $expectedcounts, 5518 $expectedunreadcounts, 5519 $deletedusers 5520 ) { 5521 $this->resetAfterTest(); 5522 $generator = $this->getDataGenerator(); 5523 $users = [ 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 $generator->create_user() 5532 ]; 5533 5534 $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null; 5535 $this->setUser($users[$arguments[0]]); 5536 $arguments[0] = $users[$arguments[0]]->id; 5537 $systemcontext = \context_system::instance(); 5538 $conversations = []; 5539 $messageids = []; 5540 5541 foreach ($conversationconfigs as $config) { 5542 $conversation = \core_message\api::create_conversation( 5543 $config['type'], 5544 array_map(function($userindex) use ($users) { 5545 return $users[$userindex]->id; 5546 }, $config['users']), 5547 null, 5548 ($config['enabled'] ?? true) 5549 ); 5550 5551 foreach ($config['messages'] as $userfromindex) { 5552 $userfrom = $users[$userfromindex]; 5553 $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id); 5554 } 5555 5556 // Remove the self conversations created by the generator, 5557 // so we can choose to set that ourself and honour the original intention of the test. 5558 $userids = array_map(function($userindex) use ($users) { 5559 return $users[$userindex]->id; 5560 }, $config['users']); 5561 foreach ($userids as $userid) { 5562 if ($conversation->type == \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) { 5563 \core_message\api::unset_favourite_conversation($conversation->id, $userid); 5564 } 5565 } 5566 5567 foreach ($config['favourites'] as $userfromindex) { 5568 $userfrom = $users[$userfromindex]; 5569 $usercontext = \context_user::instance($userfrom->id); 5570 $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); 5571 $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext); 5572 } 5573 5574 $conversations[] = $conversation; 5575 } 5576 5577 foreach ($deletemessages as $messageindex) { 5578 \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]); 5579 } 5580 5581 foreach ($deletedusers as $deleteduser) { 5582 delete_user($users[$deleteduser]); 5583 } 5584 5585 $counts = core_message_external::get_conversation_counts(...$arguments); 5586 $counts = \external_api::clean_returnvalue(core_message_external::get_conversation_counts_returns(), $counts); 5587 5588 $this->assertEquals($expectedcounts['favourites'], $counts['favourites']); 5589 $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL], 5590 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); 5591 $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP], 5592 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); 5593 $this->assertEquals($expectedcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF], 5594 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]); 5595 } 5596 5597 /** 5598 * Test the get_unread_conversation_counts() function. 5599 * 5600 * @dataProvider get_conversation_counts_test_cases 5601 * @param array $conversationconfigs Conversations to create 5602 * @param int $deletemessagesuser The user who is deleting the messages 5603 * @param array $deletemessages The list of messages to delete (by index) 5604 * @param array $arguments Arguments for the count conversations function 5605 * @param array $expectedcounts the expected conversation counts 5606 * @param array $expectedunreadcounts the expected unread conversation counts 5607 * @param array $deletedusers the list of users to soft-delete. 5608 */ 5609 public function test_get_unread_conversation_counts( 5610 $conversationconfigs, 5611 $deletemessagesuser, 5612 $deletemessages, 5613 $arguments, 5614 $expectedcounts, 5615 $expectedunreadcounts, 5616 $deletedusers 5617 ) { 5618 $this->resetAfterTest(); 5619 $generator = $this->getDataGenerator(); 5620 $users = [ 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 $generator->create_user() 5629 ]; 5630 5631 $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null; 5632 $this->setUser($users[$arguments[0]]); 5633 $arguments[0] = $users[$arguments[0]]->id; 5634 $systemcontext = \context_system::instance(); 5635 $conversations = []; 5636 $messageids = []; 5637 5638 foreach ($conversationconfigs as $config) { 5639 $conversation = \core_message\api::create_conversation( 5640 $config['type'], 5641 array_map(function($userindex) use ($users) { 5642 return $users[$userindex]->id; 5643 }, $config['users']), 5644 null, 5645 ($config['enabled'] ?? true) 5646 ); 5647 5648 foreach ($config['messages'] as $userfromindex) { 5649 $userfrom = $users[$userfromindex]; 5650 $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id); 5651 } 5652 5653 foreach ($config['favourites'] as $userfromindex) { 5654 $userfrom = $users[$userfromindex]; 5655 $usercontext = \context_user::instance($userfrom->id); 5656 $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); 5657 $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext); 5658 } 5659 5660 $conversations[] = $conversation; 5661 } 5662 5663 foreach ($deletemessages as $messageindex) { 5664 \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]); 5665 } 5666 5667 foreach ($deletedusers as $deleteduser) { 5668 delete_user($users[$deleteduser]); 5669 } 5670 5671 $counts = core_message_external::get_unread_conversation_counts(...$arguments); 5672 $counts = \external_api::clean_returnvalue(core_message_external::get_unread_conversation_counts_returns(), $counts); 5673 5674 $this->assertEquals($expectedunreadcounts['favourites'], $counts['favourites']); 5675 $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL], 5676 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); 5677 $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP], 5678 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); 5679 $this->assertEquals($expectedunreadcounts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF], 5680 $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF]); 5681 } 5682 5683 /** 5684 * Test delete_message for all users. 5685 */ 5686 public function test_delete_message_for_all_users() { 5687 global $DB; 5688 5689 $this->resetAfterTest(true); 5690 5691 // Create fake data to test it. 5692 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5693 5694 // Send message as user1 to group conversation. 5695 $messageid1 = testhelper::send_fake_message_to_conversation($user1, $convgroup->id); 5696 $messageid2 = testhelper::send_fake_message_to_conversation($user2, $convgroup->id); 5697 5698 // User1 deletes the first message for all users of group conversation. 5699 // First, we have to allow user1 (Teacher) can delete messages for all users. 5700 $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']); 5701 assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, \context_system::instance()); 5702 5703 $this->setUser($user1); 5704 5705 // Now, user1 deletes message for all users. 5706 $return = core_message_external::delete_message_for_all_users($messageid1, $user1->id); 5707 $return = \external_api::clean_returnvalue(core_message_external::delete_message_for_all_users_returns(), $return); 5708 // Check if everything is ok. 5709 $this->assertEquals(array(), $return); 5710 5711 // Check we have 3 records on message_user_actions with the mark MESSAGE_ACTION_DELETED. 5712 $muas = $DB->get_records('message_user_actions', array('messageid' => $messageid1), 'userid ASC'); 5713 $this->assertCount(3, $muas); 5714 $mua1 = array_shift($muas); 5715 $mua2 = array_shift($muas); 5716 $mua3 = array_shift($muas); 5717 5718 $this->assertEquals($user1->id, $mua1->userid); 5719 $this->assertEquals($messageid1, $mua1->messageid); 5720 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action); 5721 $this->assertEquals($user2->id, $mua2->userid); 5722 $this->assertEquals($messageid1, $mua2->messageid); 5723 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action); 5724 $this->assertEquals($user3->id, $mua3->userid); 5725 $this->assertEquals($messageid1, $mua3->messageid); 5726 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action); 5727 } 5728 5729 /** 5730 * Test delete_message for all users with messaging disabled. 5731 */ 5732 public function test_delete_message_for_all_users_messaging_disabled() { 5733 global $CFG; 5734 5735 $this->resetAfterTest(); 5736 5737 // Create fake data to test it. 5738 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5739 5740 // Send message as user1 to group conversation. 5741 $messageid = testhelper::send_fake_message_to_conversation($user1, $convgroup->id); 5742 5743 $this->setUser($user1); 5744 5745 // Disable messaging. 5746 $CFG->messaging = 0; 5747 5748 // Ensure an exception is thrown. 5749 $this->expectException('moodle_exception'); 5750 core_message_external::delete_message_for_all_users($messageid, $user1->id); 5751 } 5752 5753 /** 5754 * Test delete_message for all users with no permission. 5755 */ 5756 public function test_delete_message_for_all_users_no_permission() { 5757 $this->resetAfterTest(); 5758 5759 // Create fake data to test it. 5760 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5761 5762 // Send message as user1 to group conversation. 5763 $messageid = testhelper::send_fake_message_to_conversation($user1, $convgroup->id); 5764 5765 $this->setUser($user2); 5766 5767 // Try as user2 to delete a message for all users without permission to do it. 5768 $this->expectException('moodle_exception'); 5769 $this->expectExceptionMessage('You do not have permission to delete this message for everyone.'); 5770 core_message_external::delete_message_for_all_users($messageid, $user2->id); 5771 } 5772 5773 /** 5774 * Test delete_message for all users in a private conversation. 5775 */ 5776 public function test_delete_message_for_all_users_private_conversation() { 5777 global $DB; 5778 5779 $this->resetAfterTest(); 5780 5781 // Create fake data to test it. 5782 list($user1, $user2, $user3, $convgroup, $convindividual) = $this->create_delete_message_test_data(); 5783 5784 // Send message as user1 to private conversation. 5785 $messageid = testhelper::send_fake_message_to_conversation($user1, $convindividual->id); 5786 5787 // First, we have to allow user1 (Teacher) can delete messages for all users. 5788 $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']); 5789 assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, \context_system::instance()); 5790 5791 $this->setUser($user1); 5792 5793 // Try as user1 to delete a private message for all users on individual conversation. 5794 // User1 should not delete message for all users in a private conversations despite being a teacher. 5795 // Because is a teacher in a course and not in a system context. 5796 $this->expectException('moodle_exception'); 5797 $this->expectExceptionMessage('You do not have permission to delete this message for everyone.'); 5798 core_message_external::delete_message_for_all_users($messageid, $user1->id); 5799 } 5800 5801 /** 5802 * Test retrieving conversation messages by providing a timefrom higher than last message timecreated. It should return no 5803 * messages but keep the return structure to not break when called from the ws. 5804 */ 5805 public function test_get_conversation_messages_timefrom_higher_than_last_timecreated() { 5806 $this->resetAfterTest(true); 5807 5808 // Create some users. 5809 $user1 = self::getDataGenerator()->create_user(); 5810 $user2 = self::getDataGenerator()->create_user(); 5811 $user3 = self::getDataGenerator()->create_user(); 5812 $user4 = self::getDataGenerator()->create_user(); 5813 5814 // Create group conversation. 5815 $conversation = \core_message\api::create_conversation( 5816 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 5817 [$user1->id, $user2->id, $user3->id, $user4->id] 5818 ); 5819 5820 // The person asking for the messages for another user. 5821 $this->setUser($user1); 5822 5823 // Send some messages back and forth. 5824 $time = 1; 5825 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1); 5826 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2); 5827 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3); 5828 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4); 5829 5830 // Retrieve the messages. 5831 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, '', $time + 5); 5832 5833 // We need to execute the return values cleaning process to simulate the web service server. 5834 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), $result); 5835 5836 // Check the results are correct. 5837 $this->assertEquals($conversation->id, $result['id']); 5838 5839 // Confirm the message data is correct. 5840 $messages = $result['messages']; 5841 $this->assertEquals(0, count($messages)); 5842 5843 // Confirm that members key is present. 5844 $this->assertArrayHasKey('members', $result); 5845 } 5846 5847 /** 5848 * Helper to seed the database with initial state with data. 5849 */ 5850 protected function create_delete_message_test_data() { 5851 // Create some users. 5852 $user1 = self::getDataGenerator()->create_user(); 5853 $user2 = self::getDataGenerator()->create_user(); 5854 $user3 = self::getDataGenerator()->create_user(); 5855 5856 // Create a course and enrol the users. 5857 $course = $this->getDataGenerator()->create_course(); 5858 $coursecontext = \context_course::instance($course->id); 5859 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'editingteacher'); 5860 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 5861 $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student'); 5862 5863 // Create a group and added the users into. 5864 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 5865 groups_add_member($group1->id, $user1->id); 5866 groups_add_member($group1->id, $user2->id); 5867 groups_add_member($group1->id, $user3->id); 5868 5869 // Create a group conversation linked with the course. 5870 $convgroup = \core_message\api::create_conversation( 5871 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 5872 [$user1->id, $user2->id, $user3->id], 5873 'Group test delete for everyone', \core_message\api::MESSAGE_CONVERSATION_ENABLED, 5874 'core_group', 5875 'groups', 5876 $group1->id, 5877 \context_course::instance($course->id)->id 5878 ); 5879 5880 // Create and individual conversation. 5881 $convindividual = \core_message\api::create_conversation( 5882 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 5883 [$user1->id, $user2->id] 5884 ); 5885 5886 return [$user1, $user2, $user3, $convgroup, $convindividual]; 5887 } 5888 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body