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