Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 38 and 311] [Versions 39 and 311]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_message; 18 19 use core_message\tests\helper as testhelper; 20 use core_message_external; 21 use externallib_advanced_testcase; 22 23 defined('MOODLE_INTERNAL') || die(); 24 25 global $CFG; 26 27 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 28 require_once($CFG->dirroot . '/message/externallib.php'); 29 30 /** 31 * External message functions unit tests 32 * 33 * @package core_message 34 * @category external 35 * @copyright 2012 Jerome Mouneyrac 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class externallib_test extends externallib_advanced_testcase { 39 40 /** 41 * Tests set up 42 */ 43 protected function setUp(): void { 44 global $CFG; 45 46 require_once($CFG->dirroot . '/message/lib.php'); 47 } 48 49 /** 50 * Send a fake message. 51 * 52 * {@link message_send()} does not support transaction, this function will simulate a message 53 * sent from a user to another. We should stop using it once {@link message_send()} will support 54 * transactions. This is not clean at all, this is just used to add rows to the table. 55 * 56 * @param \stdClass $userfrom user object of the one sending the message. 57 * @param \stdClass $userto user object of the one receiving the message. 58 * @param string $message message to send. 59 * @param int $notification is the message a notification. 60 * @param int $time the time the message was sent 61 */ 62 protected function send_message($userfrom, $userto, $message = 'Hello world!', $notification = 0, $time = 0) { 63 global $DB; 64 65 if (empty($time)) { 66 $time = time(); 67 } 68 69 if ($notification) { 70 $record = new \stdClass(); 71 $record->useridfrom = $userfrom->id; 72 $record->useridto = $userto->id; 73 $record->subject = 'No subject'; 74 $record->fullmessage = $message; 75 $record->smallmessage = $message; 76 $record->timecreated = $time; 77 78 return $DB->insert_record('notifications', $record); 79 } 80 81 if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) { 82 $conversation = \core_message\api::create_conversation( 83 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 84 [ 85 $userfrom->id, 86 $userto->id 87 ] 88 ); 89 $conversationid = $conversation->id; 90 } 91 92 // Ok, send the message. 93 $record = new \stdClass(); 94 $record->useridfrom = $userfrom->id; 95 $record->conversationid = $conversationid; 96 $record->subject = 'No subject'; 97 $record->fullmessage = $message; 98 $record->smallmessage = $message; 99 $record->timecreated = $time; 100 101 return $DB->insert_record('messages', $record); 102 } 103 104 /** 105 * Test send_instant_messages. 106 */ 107 public function test_send_instant_messages() { 108 global $DB, $USER; 109 110 $this->resetAfterTest(); 111 112 // Transactions used in tests, tell phpunit use alternative reset method. 113 $this->preventResetByRollback(); 114 115 $user1 = self::getDataGenerator()->create_user(); 116 $user2 = self::getDataGenerator()->create_user(); 117 118 $this->setUser($user1); 119 120 // Create test message data. 121 $message1 = array(); 122 $message1['touserid'] = $user2->id; 123 $message1['text'] = 'the message.'; 124 $message1['clientmsgid'] = 4; 125 $messages = array($message1); 126 127 $sentmessages = core_message_external::send_instant_messages($messages); 128 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 129 $this->assertEquals( 130 get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message1['touserid']))), 131 array_pop($sentmessages)['errormessage'] 132 ); 133 134 // Add the user1 as a contact. 135 \core_message\api::add_contact($user1->id, $user2->id); 136 137 // Send message again. Now it should work properly. 138 $sentmessages = core_message_external::send_instant_messages($messages); 139 // We need to execute the return values cleaning process to simulate the web service server. 140 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 141 142 $sentmessage = reset($sentmessages); 143 144 $sql = "SELECT m.*, mcm.userid as useridto 145 FROM {messages} m 146 INNER JOIN {message_conversations} mc 147 ON m.conversationid = mc.id 148 INNER JOIN {message_conversation_members} mcm 149 ON mcm.conversationid = mc.id 150 WHERE mcm.userid != ? 151 AND m.id = ?"; 152 $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]); 153 154 // Confirm that the message was inserted correctly. 155 $this->assertEquals($themessage->useridfrom, $user1->id); 156 $this->assertEquals($themessage->useridto, $message1['touserid']); 157 $this->assertEquals($themessage->smallmessage, $message1['text']); 158 $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']); 159 } 160 161 /** 162 * Test send_instant_messages with a message text longer than permitted. 163 */ 164 public function test_send_instant_messages_long_text() { 165 global $CFG; 166 167 $this->resetAfterTest(true); 168 169 // Transactions used in tests, tell phpunit use alternative reset method. 170 $this->preventResetByRollback(); 171 172 $user1 = self::getDataGenerator()->create_user(); 173 $user2 = self::getDataGenerator()->create_user(); 174 175 $this->setUser($user1); 176 177 // Create test message data. 178 $message1 = [ 179 'touserid' => $user2->id, 180 'text' => str_repeat("M", \core_message\api::MESSAGE_MAX_LENGTH + 100), 181 'clientmsgid' => 4, 182 ]; 183 $messages = [$message1]; 184 185 // Add the user1 as a contact. 186 \core_message\api::add_contact($user1->id, $user2->id); 187 188 $sentmessages = core_message_external::send_instant_messages($messages); 189 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 190 $this->assertEquals( 191 get_string('errormessagetoolong', 'message'), 192 array_pop($sentmessages)['errormessage'] 193 ); 194 } 195 196 /** 197 * Test send_instant_messages to a user who has blocked you. 198 */ 199 public function test_send_instant_messages_blocked_user() { 200 global $DB; 201 202 $this->resetAfterTest(); 203 204 // Transactions used in tests, tell phpunit use alternative reset method. 205 $this->preventResetByRollback(); 206 207 $user1 = self::getDataGenerator()->create_user(); 208 $user2 = self::getDataGenerator()->create_user(); 209 210 $this->setUser($user1); 211 212 \core_message\api::block_user($user2->id, $user1->id); 213 214 // Create test message data. 215 $message1 = array(); 216 $message1['touserid'] = $user2->id; 217 $message1['text'] = 'the message.'; 218 $message1['clientmsgid'] = 4; 219 $messages = array($message1); 220 221 $sentmessages = core_message_external::send_instant_messages($messages); 222 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 223 224 $sentmessage = reset($sentmessages); 225 226 $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']); 227 228 $this->assertEquals(0, $DB->count_records('messages')); 229 } 230 231 /** 232 * Test send_instant_messages when sending a message to a non-contact who has blocked non-contacts. 233 */ 234 public function test_send_instant_messages_block_non_contacts() { 235 global $DB; 236 237 $this->resetAfterTest(true); 238 239 // Transactions used in tests, tell phpunit use alternative reset method. 240 $this->preventResetByRollback(); 241 242 $user1 = self::getDataGenerator()->create_user(); 243 $user2 = self::getDataGenerator()->create_user(); 244 245 $this->setUser($user1); 246 247 // Set the user preference so user 2 does not accept messages from non-contacts. 248 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2); 249 250 // Create test message data. 251 $message1 = array(); 252 $message1['touserid'] = $user2->id; 253 $message1['text'] = 'the message.'; 254 $message1['clientmsgid'] = 4; 255 $messages = array($message1); 256 257 $sentmessages = core_message_external::send_instant_messages($messages); 258 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 259 260 $sentmessage = reset($sentmessages); 261 262 $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']); 263 264 $this->assertEquals(0, $DB->count_records('messages')); 265 } 266 267 /** 268 * Test send_instant_messages when sending a message to a contact who has blocked non-contacts. 269 */ 270 public function test_send_instant_messages_block_non_contacts_but_am_contact() { 271 global $DB, $USER; 272 273 $this->resetAfterTest(true); 274 275 // Transactions used in tests, tell phpunit use alternative reset method. 276 $this->preventResetByRollback(); 277 278 $user1 = self::getDataGenerator()->create_user(); 279 $user2 = self::getDataGenerator()->create_user(); 280 281 $this->setUser($user1); 282 283 // Set the user preference so user 2 does not accept messages from non-contacts. 284 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2); 285 286 \core_message\api::add_contact($user1->id, $user2->id); 287 288 // Create test message data. 289 $message1 = array(); 290 $message1['touserid'] = $user2->id; 291 $message1['text'] = 'the message.'; 292 $message1['clientmsgid'] = 4; 293 $messages = array($message1); 294 295 $sentmessages = core_message_external::send_instant_messages($messages); 296 $sentmessages = \external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages); 297 298 $sentmessage = reset($sentmessages); 299 300 $sql = "SELECT m.*, mcm.userid as useridto 301 FROM {messages} m 302 INNER JOIN {message_conversations} mc 303 ON m.conversationid = mc.id 304 INNER JOIN {message_conversation_members} mcm 305 ON mcm.conversationid = mc.id 306 WHERE mcm.userid != ? 307 AND m.id = ?"; 308 $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]); 309 310 // Confirm that the message was inserted correctly. 311 $this->assertEquals($themessage->useridfrom, $user1->id); 312 $this->assertEquals($themessage->useridto, $message1['touserid']); 313 $this->assertEquals($themessage->smallmessage, $message1['text']); 314 $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']); 315 } 316 317 /** 318 * Test send_instant_messages with no capabilities 319 */ 320 public function test_send_instant_messages_no_capability() { 321 global $DB; 322 323 $this->resetAfterTest(true); 324 325 // Transactions used in tests, tell phpunit use alternative reset method. 326 $this->preventResetByRollback(); 327 328 $user1 = self::getDataGenerator()->create_user(); 329 $user2 = self::getDataGenerator()->create_user(); 330 331 $this->setUser($user1); 332 333 // Unset the required capabilities by the external function. 334 $contextid = \context_system::instance()->id; 335 $userrole = $DB->get_record('role', array('shortname' => 'user')); 336 $this->unassignUserCapability('moodle/site:sendmessage', $contextid, $userrole->id); 337 338 // Create test message data. 339 $message1 = array(); 340 $message1['touserid'] = $user2->id; 341 $message1['text'] = 'the message.'; 342 $message1['clientmsgid'] = 4; 343 $messages = array($message1); 344 345 $this->expectException('required_capability_exception'); 346 core_message_external::send_instant_messages($messages); 347 } 348 349 /** 350 * Test send_instant_messages when messaging is disabled. 351 */ 352 public function test_send_instant_messages_messaging_disabled() { 353 global $CFG; 354 355 $this->resetAfterTest(true); 356 357 // Transactions used in tests, tell phpunit use alternative reset method. 358 $this->preventResetByRollback(); 359 360 $user1 = self::getDataGenerator()->create_user(); 361 $user2 = self::getDataGenerator()->create_user(); 362 363 $this->setUser($user1); 364 365 // Disable messaging. 366 $CFG->messaging = 0; 367 368 // Create test message data. 369 $message1 = array(); 370 $message1['touserid'] = $user2->id; 371 $message1['text'] = 'the message.'; 372 $message1['clientmsgid'] = 4; 373 $messages = array($message1); 374 375 $this->expectException('moodle_exception'); 376 core_message_external::send_instant_messages($messages); 377 } 378 379 /** 380 * Test delete_contacts. 381 */ 382 public function test_delete_contacts() { 383 $this->resetAfterTest(true); 384 385 $user1 = self::getDataGenerator()->create_user(); 386 $user2 = self::getDataGenerator()->create_user(); 387 $user3 = self::getDataGenerator()->create_user(); 388 $user4 = self::getDataGenerator()->create_user(); 389 $user5 = self::getDataGenerator()->create_user(); 390 $user6 = self::getDataGenerator()->create_user(); 391 $this->setUser($user1); 392 393 \core_message\api::add_contact($user1->id, $user3->id); 394 \core_message\api::add_contact($user1->id, $user4->id); 395 \core_message\api::add_contact($user1->id, $user5->id); 396 \core_message\api::add_contact($user1->id, $user6->id); 397 398 // Removing a non-contact. 399 $return = core_message_external::delete_contacts(array($user2->id)); 400 $this->assertNull($return); 401 402 // Removing one contact. 403 $return = core_message_external::delete_contacts(array($user3->id)); 404 $this->assertNull($return); 405 406 // Removing multiple contacts. 407 $return = core_message_external::delete_contacts(array($user4->id, $user5->id)); 408 $this->assertNull($return); 409 410 // Removing contact from unexisting user. 411 $return = core_message_external::delete_contacts(array(99999)); 412 $this->assertNull($return); 413 414 // Removing mixed valid and invalid data. 415 $return = core_message_external::delete_contacts(array($user6->id, 99999)); 416 $this->assertNull($return); 417 418 // Try to delete a contact of another user contact list, should throw an exception. 419 // All assertions must be added before this point. 420 $this->expectException('required_capability_exception'); 421 core_message_external::delete_contacts(array($user2->id), $user3->id); 422 } 423 424 /** 425 * Test getting contact requests. 426 */ 427 public function test_get_contact_requests() { 428 global $PAGE; 429 430 $this->resetAfterTest(); 431 432 $user1 = self::getDataGenerator()->create_user(); 433 $user2 = self::getDataGenerator()->create_user(); 434 $user3 = self::getDataGenerator()->create_user(); 435 436 $this->setUser($user1); 437 438 // Block one user, their request should not show up. 439 \core_message\api::block_user($user1->id, $user3->id); 440 441 \core_message\api::create_contact_request($user2->id, $user1->id); 442 \core_message\api::create_contact_request($user3->id, $user1->id); 443 444 $requests = core_message_external::get_contact_requests($user1->id); 445 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 446 447 $this->assertCount(1, $requests); 448 449 $request = reset($requests); 450 $userpicture = new \user_picture($user2); 451 $profileimageurl = $userpicture->get_url($PAGE)->out(false); 452 453 $this->assertEquals($user2->id, $request['id']); 454 $this->assertEquals(fullname($user2), $request['fullname']); 455 $this->assertArrayHasKey('profileimageurl', $request); 456 $this->assertArrayHasKey('profileimageurlsmall', $request); 457 $this->assertArrayHasKey('isonline', $request); 458 $this->assertArrayHasKey('showonlinestatus', $request); 459 $this->assertArrayHasKey('isblocked', $request); 460 $this->assertArrayHasKey('iscontact', $request); 461 } 462 463 /** 464 * Test the get_contact_requests() function when the user has blocked the sender of the request. 465 */ 466 public function test_get_contact_requests_blocked_sender() { 467 $this->resetAfterTest(); 468 $user1 = self::getDataGenerator()->create_user(); 469 $user2 = self::getDataGenerator()->create_user(); 470 471 // User1 blocks User2. 472 \core_message\api::block_user($user1->id, $user2->id); 473 474 // User2 tries to add User1 as a contact. 475 \core_message\api::create_contact_request($user2->id, $user1->id); 476 477 // Verify we don't see the contact request from the blocked user User2 in the requests for User1. 478 $this->setUser($user1); 479 $requests = core_message_external::get_contact_requests($user1->id); 480 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 481 482 $this->assertCount(0, $requests); 483 } 484 485 /** 486 * Test getting contact requests when there are none. 487 */ 488 public function test_get_contact_requests_no_requests() { 489 $this->resetAfterTest(); 490 491 $user1 = self::getDataGenerator()->create_user(); 492 493 $this->setUser($user1); 494 495 $requests = core_message_external::get_contact_requests($user1->id); 496 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 497 498 $this->assertEmpty($requests); 499 } 500 501 /** 502 * Test getting contact requests with limits. 503 */ 504 public function test_get_contact_requests_with_limits() { 505 $this->resetAfterTest(); 506 507 $user1 = self::getDataGenerator()->create_user(); 508 $user2 = self::getDataGenerator()->create_user(); 509 $user3 = self::getDataGenerator()->create_user(); 510 511 $this->setUser($user1); 512 513 \core_message\api::create_contact_request($user2->id, $user1->id); 514 \core_message\api::create_contact_request($user3->id, $user1->id); 515 516 $requests = core_message_external::get_contact_requests($user1->id, 0, 1); 517 $requests = \external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests); 518 519 $this->assertCount(1, $requests); 520 } 521 522 /** 523 * Test getting contact requests with messaging disabled. 524 */ 525 public function test_get_contact_requests_messaging_disabled() { 526 global $CFG; 527 528 $this->resetAfterTest(); 529 530 // Create some skeleton data just so we can call the WS. 531 $user1 = self::getDataGenerator()->create_user(); 532 533 $this->setUser($user1); 534 535 // Disable messaging. 536 $CFG->messaging = 0; 537 538 // Ensure an exception is thrown. 539 $this->expectException('moodle_exception'); 540 core_message_external::get_contact_requests($user1->id); 541 } 542 543 /** 544 * Test getting contact requests with no permission. 545 */ 546 public function test_get_contact_requests_no_permission() { 547 $this->resetAfterTest(); 548 549 // Create some skeleton data just so we can call the WS. 550 $user1 = self::getDataGenerator()->create_user(); 551 $user2 = self::getDataGenerator()->create_user(); 552 $user3 = self::getDataGenerator()->create_user(); 553 554 $this->setUser($user3); 555 556 // Ensure an exception is thrown. 557 $this->expectException('required_capability_exception'); 558 core_message_external::create_contact_request($user1->id, $user2->id); 559 } 560 561 /** 562 * Test getting the number of received contact requests. 563 */ 564 public function test_get_received_contact_requests_count() { 565 $this->resetAfterTest(); 566 567 $user1 = self::getDataGenerator()->create_user(); 568 $user2 = self::getDataGenerator()->create_user(); 569 $user3 = self::getDataGenerator()->create_user(); 570 $user4 = self::getDataGenerator()->create_user(); 571 572 $this->setUser($user1); 573 574 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 575 $contactrequestnumber = \external_api::clean_returnvalue( 576 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 577 $this->assertEquals(0, $contactrequestnumber); 578 579 \core_message\api::create_contact_request($user2->id, $user1->id); 580 581 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 582 $contactrequestnumber = \external_api::clean_returnvalue( 583 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 584 $this->assertEquals(1, $contactrequestnumber); 585 586 \core_message\api::create_contact_request($user3->id, $user1->id); 587 588 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 589 $contactrequestnumber = \external_api::clean_returnvalue( 590 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 591 $this->assertEquals(2, $contactrequestnumber); 592 593 \core_message\api::create_contact_request($user1->id, $user4->id); 594 595 // Web service should ignore sent requests. 596 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 597 $contactrequestnumber = \external_api::clean_returnvalue( 598 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 599 $this->assertEquals(2, $contactrequestnumber); 600 } 601 602 /** 603 * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request. 604 */ 605 public function test_get_received_contact_requests_count_blocked_sender() { 606 $this->resetAfterTest(); 607 $user1 = self::getDataGenerator()->create_user(); 608 $user2 = self::getDataGenerator()->create_user(); 609 610 // User1 blocks User2. 611 \core_message\api::block_user($user1->id, $user2->id); 612 613 // User2 tries to add User1 as a contact. 614 \core_message\api::create_contact_request($user2->id, $user1->id); 615 616 // Verify we don't see the contact request from the blocked user User2 in the count for User1. 617 $this->setUser($user1); 618 $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id); 619 $contactrequestnumber = \external_api::clean_returnvalue( 620 core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber); 621 $this->assertEquals(0, $contactrequestnumber); 622 } 623 624 /** 625 * Test getting the number of received contact requests with no permissions. 626 */ 627 public function test_get_received_contact_requests_count_no_permission() { 628 $this->resetAfterTest(); 629 630 // Create some skeleton data just so we can call the WS. 631 $user1 = self::getDataGenerator()->create_user(); 632 $user2 = self::getDataGenerator()->create_user(); 633 634 $this->setUser($user2); 635 636 // Ensure an exception is thrown. 637 $this->expectException('required_capability_exception'); 638 core_message_external::get_received_contact_requests_count($user1->id); 639 } 640 641 /** 642 * Test getting the number of received contact requests with messaging disabled. 643 */ 644 public function test_get_received_contact_requests_count_messaging_disabled() { 645 global $CFG; 646 647 $this->resetAfterTest(); 648 649 // Create some skeleton data just so we can call the WS. 650 $user1 = self::getDataGenerator()->create_user(); 651 652 $this->setUser($user1); 653 654 // Disable messaging. 655 $CFG->messaging = 0; 656 657 // Ensure an exception is thrown. 658 $this->expectException('moodle_exception'); 659 core_message_external::get_received_contact_requests_count($user1->id); 660 } 661 662 /** 663 * Test creating a contact request. 664 */ 665 public function test_create_contact_request() { 666 global $CFG, $DB; 667 668 $this->resetAfterTest(); 669 670 $user1 = self::getDataGenerator()->create_user(); 671 $user2 = self::getDataGenerator()->create_user(); 672 673 $this->setUser($user1); 674 675 // Allow users to message anyone site-wide. 676 $CFG->messagingallusers = 1; 677 678 $return = core_message_external::create_contact_request($user1->id, $user2->id); 679 $return = \external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return); 680 $this->assertEquals([], $return['warnings']); 681 682 $request = $DB->get_records('message_contact_requests'); 683 684 $this->assertCount(1, $request); 685 686 $request = reset($request); 687 688 $this->assertEquals($request->id, $return['request']['id']); 689 $this->assertEquals($request->userid, $return['request']['userid']); 690 $this->assertEquals($request->requesteduserid, $return['request']['requesteduserid']); 691 $this->assertEquals($request->timecreated, $return['request']['timecreated']); 692 } 693 694 /** 695 * Test creating a contact request when not allowed. 696 */ 697 public function test_create_contact_request_not_allowed() { 698 global $CFG; 699 700 $this->resetAfterTest(); 701 702 $user1 = self::getDataGenerator()->create_user(); 703 $user2 = self::getDataGenerator()->create_user(); 704 705 $this->setUser($user1); 706 707 $CFG->messagingallusers = 0; 708 709 $return = core_message_external::create_contact_request($user1->id, $user2->id); 710 $return = \external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return); 711 712 $warning = reset($return['warnings']); 713 714 $this->assertEquals('user', $warning['item']); 715 $this->assertEquals($user2->id, $warning['itemid']); 716 $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']); 717 $this->assertEquals('You are unable to create a contact request for this user', $warning['message']); 718 } 719 720 /** 721 * Test creating a contact request with messaging disabled. 722 */ 723 public function test_create_contact_request_messaging_disabled() { 724 global $CFG; 725 726 $this->resetAfterTest(); 727 728 // Create some skeleton data just so we can call the WS. 729 $user1 = self::getDataGenerator()->create_user(); 730 $user2 = self::getDataGenerator()->create_user(); 731 732 $this->setUser($user1); 733 734 // Disable messaging. 735 $CFG->messaging = 0; 736 737 // Ensure an exception is thrown. 738 $this->expectException('moodle_exception'); 739 core_message_external::create_contact_request($user1->id, $user2->id); 740 } 741 742 /** 743 * Test creating a contact request with no permission. 744 */ 745 public function test_create_contact_request_no_permission() { 746 $this->resetAfterTest(); 747 748 // Create some skeleton data just so we can call the WS. 749 $user1 = self::getDataGenerator()->create_user(); 750 $user2 = self::getDataGenerator()->create_user(); 751 $user3 = self::getDataGenerator()->create_user(); 752 753 $this->setUser($user3); 754 755 // Ensure an exception is thrown. 756 $this->expectException('required_capability_exception'); 757 core_message_external::create_contact_request($user1->id, $user2->id); 758 } 759 760 /** 761 * Test confirming a contact request. 762 */ 763 public function test_confirm_contact_request() { 764 global $DB; 765 766 $this->resetAfterTest(); 767 768 $user1 = self::getDataGenerator()->create_user(); 769 $user2 = self::getDataGenerator()->create_user(); 770 771 $this->setUser($user1); 772 773 \core_message\api::create_contact_request($user1->id, $user2->id); 774 775 $this->setUser($user2); 776 777 $return = core_message_external::confirm_contact_request($user1->id, $user2->id); 778 $return = \external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return); 779 $this->assertEquals(array(), $return); 780 781 $this->assertEquals(0, $DB->count_records('message_contact_requests')); 782 783 $contact = $DB->get_records('message_contacts'); 784 785 $this->assertCount(1, $contact); 786 787 $contact = reset($contact); 788 789 $this->assertEquals($user1->id, $contact->userid); 790 $this->assertEquals($user2->id, $contact->contactid); 791 } 792 793 /** 794 * Test confirming a contact request with messaging disabled. 795 */ 796 public function test_confirm_contact_request_messaging_disabled() { 797 global $CFG; 798 799 $this->resetAfterTest(); 800 801 // Create some skeleton data just so we can call the WS. 802 $user1 = self::getDataGenerator()->create_user(); 803 $user2 = self::getDataGenerator()->create_user(); 804 805 $this->setUser($user1); 806 807 // Disable messaging. 808 $CFG->messaging = 0; 809 810 // Ensure an exception is thrown. 811 $this->expectException('moodle_exception'); 812 core_message_external::confirm_contact_request($user1->id, $user2->id); 813 } 814 815 /** 816 * Test confirming a contact request with no permission. 817 */ 818 public function test_confirm_contact_request_no_permission() { 819 $this->resetAfterTest(); 820 821 // Create some skeleton data just so we can call the WS. 822 $user1 = self::getDataGenerator()->create_user(); 823 $user2 = self::getDataGenerator()->create_user(); 824 $user3 = self::getDataGenerator()->create_user(); 825 826 $this->setUser($user3); 827 828 // Ensure an exception is thrown. 829 $this->expectException('required_capability_exception'); 830 core_message_external::confirm_contact_request($user1->id, $user2->id); 831 } 832 833 /** 834 * Test declining a contact request. 835 */ 836 public function test_decline_contact_request() { 837 global $DB; 838 839 $this->resetAfterTest(); 840 841 $user1 = self::getDataGenerator()->create_user(); 842 $user2 = self::getDataGenerator()->create_user(); 843 844 $this->setUser($user1); 845 846 \core_message\api::create_contact_request($user1->id, $user2->id); 847 848 $this->setUser($user2); 849 850 $return = core_message_external::decline_contact_request($user1->id, $user2->id); 851 $return = \external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return); 852 $this->assertEquals(array(), $return); 853 854 $this->assertEquals(0, $DB->count_records('message_contact_requests')); 855 $this->assertEquals(0, $DB->count_records('message_contacts')); 856 } 857 858 /** 859 * Test declining a contact request with messaging disabled. 860 */ 861 public function test_decline_contact_request_messaging_disabled() { 862 global $CFG; 863 864 $this->resetAfterTest(); 865 866 // Create some skeleton data just so we can call the WS. 867 $user1 = self::getDataGenerator()->create_user(); 868 $user2 = self::getDataGenerator()->create_user(); 869 870 $this->setUser($user1); 871 872 // Disable messaging. 873 $CFG->messaging = 0; 874 875 // Ensure an exception is thrown. 876 $this->expectException('moodle_exception'); 877 core_message_external::decline_contact_request($user1->id, $user2->id); 878 } 879 880 /** 881 * Test declining a contact request with no permission. 882 */ 883 public function test_decline_contact_request_no_permission() { 884 $this->resetAfterTest(); 885 886 // Create some skeleton data just so we can call the WS. 887 $user1 = self::getDataGenerator()->create_user(); 888 $user2 = self::getDataGenerator()->create_user(); 889 $user3 = self::getDataGenerator()->create_user(); 890 891 $this->setUser($user3); 892 893 // Ensure an exception is thrown. 894 $this->expectException('required_capability_exception'); 895 core_message_external::decline_contact_request($user1->id, $user2->id); 896 } 897 898 /** 899 * Test muting conversations. 900 */ 901 public function test_mute_conversations() { 902 global $DB; 903 904 $this->resetAfterTest(true); 905 906 $user1 = self::getDataGenerator()->create_user(); 907 $user2 = self::getDataGenerator()->create_user(); 908 909 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 910 [$user1->id, $user2->id]); 911 912 $this->setUser($user1); 913 914 // Muting a conversation. 915 $return = core_message_external::mute_conversations($user1->id, [$conversation->id]); 916 $return = \external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return); 917 $this->assertEquals(array(), $return); 918 919 // Get list of muted conversations. 920 $mca = $DB->get_record('message_conversation_actions', []); 921 922 $this->assertEquals($user1->id, $mca->userid); 923 $this->assertEquals($conversation->id, $mca->conversationid); 924 $this->assertEquals(\core_message\api::CONVERSATION_ACTION_MUTED, $mca->action); 925 926 // Muting a conversation that is already muted. 927 $return = core_message_external::mute_conversations($user1->id, [$conversation->id]); 928 $return = \external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return); 929 $this->assertEquals(array(), $return); 930 931 $this->assertEquals(1, $DB->count_records('message_conversation_actions')); 932 } 933 934 /** 935 * Test muting a conversation with messaging disabled. 936 */ 937 public function test_mute_conversations_messaging_disabled() { 938 global $CFG; 939 940 $this->resetAfterTest(); 941 942 // Create some skeleton data just so we can call the WS. 943 $user1 = self::getDataGenerator()->create_user(); 944 $user2 = self::getDataGenerator()->create_user(); 945 946 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 947 [$user1->id, $user2->id]); 948 949 $this->setUser($user1); 950 951 // Disable messaging. 952 $CFG->messaging = 0; 953 954 // Ensure an exception is thrown. 955 $this->expectException('moodle_exception'); 956 core_message_external::mute_conversations($user1->id, [$conversation->id]); 957 } 958 959 /** 960 * Test muting a conversation with no permission. 961 */ 962 public function test_mute_conversations_no_permission() { 963 $this->resetAfterTest(); 964 965 // Create some skeleton data just so we can call the WS. 966 $user1 = self::getDataGenerator()->create_user(); 967 $user2 = self::getDataGenerator()->create_user(); 968 $user3 = self::getDataGenerator()->create_user(); 969 970 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 971 [$user1->id, $user2->id]); 972 973 $this->setUser($user3); 974 975 // Ensure an exception is thrown. 976 $this->expectException('required_capability_exception'); 977 core_message_external::mute_conversations($user1->id, [$conversation->id]); 978 } 979 980 /** 981 * Test unmuting conversations. 982 */ 983 public function test_unmute_conversations() { 984 global $DB; 985 986 $this->resetAfterTest(true); 987 988 $user1 = self::getDataGenerator()->create_user(); 989 $user2 = self::getDataGenerator()->create_user(); 990 991 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 992 [$user1->id, $user2->id]); 993 994 $this->setUser($user1); 995 996 // Mute the conversation. 997 \core_message\api::mute_conversation($user1->id, $conversation->id); 998 999 // Unmuting a conversation. 1000 $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]); 1001 $return = \external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return); 1002 $this->assertEquals(array(), $return); 1003 1004 $this->assertEquals(0, $DB->count_records('message_conversation_actions')); 1005 1006 // Unmuting a conversation which is already unmuted. 1007 $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]); 1008 $return = \external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return); 1009 $this->assertEquals(array(), $return); 1010 1011 $this->assertEquals(0, $DB->count_records('message_conversation_actions')); 1012 } 1013 1014 /** 1015 * Test unmuting a conversation with messaging disabled. 1016 */ 1017 public function test_unmute_conversation_messaging_disabled() { 1018 global $CFG; 1019 1020 $this->resetAfterTest(); 1021 1022 // Create some skeleton data just so we can call the WS. 1023 $user1 = self::getDataGenerator()->create_user(); 1024 $user2 = self::getDataGenerator()->create_user(); 1025 1026 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 1027 [$user1->id, $user2->id]); 1028 1029 $this->setUser($user1); 1030 1031 // Disable messaging. 1032 $CFG->messaging = 0; 1033 1034 // Ensure an exception is thrown. 1035 $this->expectException('moodle_exception'); 1036 core_message_external::unmute_conversations($user1->id, [$user2->id]); 1037 } 1038 1039 /** 1040 * Test unmuting a conversation with no permission. 1041 */ 1042 public function test_unmute_conversation_no_permission() { 1043 $this->resetAfterTest(); 1044 1045 // Create some skeleton data just so we can call the WS. 1046 $user1 = self::getDataGenerator()->create_user(); 1047 $user2 = self::getDataGenerator()->create_user(); 1048 $user3 = self::getDataGenerator()->create_user(); 1049 1050 $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 1051 [$user1->id, $user2->id]); 1052 1053 $this->setUser($user3); 1054 1055 // Ensure an exception is thrown. 1056 $this->expectException('required_capability_exception'); 1057 core_message_external::unmute_conversations($user1->id, [$conversation->id]); 1058 } 1059 1060 /** 1061 * Test blocking a user. 1062 */ 1063 public function test_block_user() { 1064 global $DB; 1065 1066 $this->resetAfterTest(true); 1067 1068 $user1 = self::getDataGenerator()->create_user(); 1069 $user2 = self::getDataGenerator()->create_user(); 1070 1071 $this->setUser($user1); 1072 1073 // Blocking a user. 1074 $return = core_message_external::block_user($user1->id, $user2->id); 1075 $return = \external_api::clean_returnvalue(core_message_external::block_user_returns(), $return); 1076 $this->assertEquals(array(), $return); 1077 1078 // Get list of blocked users. 1079 $record = $DB->get_record('message_users_blocked', []); 1080 1081 $this->assertEquals($user1->id, $record->userid); 1082 $this->assertEquals($user2->id, $record->blockeduserid); 1083 1084 // Blocking a user who is already blocked. 1085 $return = core_message_external::block_user($user1->id, $user2->id); 1086 $return = \external_api::clean_returnvalue(core_message_external::block_user_returns(), $return); 1087 $this->assertEquals(array(), $return); 1088 1089 $this->assertEquals(1, $DB->count_records('message_users_blocked')); 1090 } 1091 1092 /** 1093 * Test blocking a user. 1094 */ 1095 public function test_block_user_when_ineffective() { 1096 global $DB; 1097 1098 $this->resetAfterTest(true); 1099 1100 $user1 = self::getDataGenerator()->create_user(); 1101 $user2 = self::getDataGenerator()->create_user(); 1102 1103 $this->setUser($user1); 1104 1105 $authenticateduser = $DB->get_record('role', array('shortname' => 'user')); 1106 assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, \context_system::instance(), true); 1107 1108 // Blocking a user. 1109 $return = core_message_external::block_user($user1->id, $user2->id); 1110 $return = \external_api::clean_returnvalue(core_message_external::block_user_returns(), $return); 1111 $this->assertEquals(array(), $return); 1112 1113 $this->assertEquals(0, $DB->count_records('message_users_blocked')); 1114 } 1115 1116 /** 1117 * Test blocking a user with messaging disabled. 1118 */ 1119 public function test_block_user_messaging_disabled() { 1120 global $CFG; 1121 1122 $this->resetAfterTest(); 1123 1124 // Create some skeleton data just so we can call the WS. 1125 $user1 = self::getDataGenerator()->create_user(); 1126 $user2 = self::getDataGenerator()->create_user(); 1127 1128 $this->setUser($user1); 1129 1130 // Disable messaging. 1131 $CFG->messaging = 0; 1132 1133 // Ensure an exception is thrown. 1134 $this->expectException('moodle_exception'); 1135 core_message_external::block_user($user1->id, $user2->id); 1136 } 1137 1138 /** 1139 * Test blocking a user with no permission. 1140 */ 1141 public function test_block_user_no_permission() { 1142 $this->resetAfterTest(); 1143 1144 // Create some skeleton data just so we can call the WS. 1145 $user1 = self::getDataGenerator()->create_user(); 1146 $user2 = self::getDataGenerator()->create_user(); 1147 $user3 = self::getDataGenerator()->create_user(); 1148 1149 $this->setUser($user3); 1150 1151 // Ensure an exception is thrown. 1152 $this->expectException('required_capability_exception'); 1153 core_message_external::block_user($user1->id, $user2->id); 1154 } 1155 1156 /** 1157 * Test unblocking a user. 1158 */ 1159 public function test_unblock_user() { 1160 global $DB; 1161 1162 $this->resetAfterTest(true); 1163 1164 $user1 = self::getDataGenerator()->create_user(); 1165 $user2 = self::getDataGenerator()->create_user(); 1166 1167 $this->setUser($user1); 1168 1169 // Block the user. 1170 \core_message\api::block_user($user1->id, $user2->id); 1171 1172 // Unblocking a user. 1173 $return = core_message_external::unblock_user($user1->id, $user2->id); 1174 $return = \external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return); 1175 $this->assertEquals(array(), $return); 1176 1177 $this->assertEquals(0, $DB->count_records('message_users_blocked')); 1178 1179 // Unblocking a user who is already unblocked. 1180 $return = core_message_external::unblock_user($user1->id, $user2->id); 1181 $return = \external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return); 1182 $this->assertEquals(array(), $return); 1183 1184 $this->assertEquals(0, $DB->count_records('message_users_blocked')); 1185 } 1186 1187 /** 1188 * Test unblocking a user with messaging disabled. 1189 */ 1190 public function test_unblock_user_messaging_disabled() { 1191 global $CFG; 1192 1193 $this->resetAfterTest(); 1194 1195 // Create some skeleton data just so we can call the WS. 1196 $user1 = self::getDataGenerator()->create_user(); 1197 $user2 = self::getDataGenerator()->create_user(); 1198 1199 $this->setUser($user1); 1200 1201 // Disable messaging. 1202 $CFG->messaging = 0; 1203 1204 // Ensure an exception is thrown. 1205 $this->expectException('moodle_exception'); 1206 core_message_external::unblock_user($user1->id, $user2->id); 1207 } 1208 1209 /** 1210 * Test unblocking a user with no permission. 1211 */ 1212 public function test_unblock_user_no_permission() { 1213 $this->resetAfterTest(); 1214 1215 // Create some skeleton data just so we can call the WS. 1216 $user1 = self::getDataGenerator()->create_user(); 1217 $user2 = self::getDataGenerator()->create_user(); 1218 $user3 = self::getDataGenerator()->create_user(); 1219 1220 $this->setUser($user3); 1221 1222 // Ensure an exception is thrown. 1223 $this->expectException('required_capability_exception'); 1224 core_message_external::unblock_user($user1->id, $user2->id); 1225 } 1226 1227 /** 1228 * Test search_contacts. 1229 */ 1230 public function test_search_contacts() { 1231 global $DB; 1232 $this->resetAfterTest(true); 1233 1234 $course1 = $this->getDataGenerator()->create_course(); 1235 $course2 = $this->getDataGenerator()->create_course(); 1236 1237 $user1 = new \stdClass(); 1238 $user1->firstname = 'X'; 1239 $user1->lastname = 'X'; 1240 $user1 = $this->getDataGenerator()->create_user($user1); 1241 $this->getDataGenerator()->enrol_user($user1->id, $course1->id); 1242 $this->getDataGenerator()->enrol_user($user1->id, $course2->id); 1243 1244 $user2 = new \stdClass(); 1245 $user2->firstname = 'Eric'; 1246 $user2->lastname = 'Cartman'; 1247 $user2 = self::getDataGenerator()->create_user($user2); 1248 $user3 = new \stdClass(); 1249 $user3->firstname = 'Stan'; 1250 $user3->lastname = 'Marsh'; 1251 $user3 = self::getDataGenerator()->create_user($user3); 1252 self::getDataGenerator()->enrol_user($user3->id, $course1->id); 1253 $user4 = new \stdClass(); 1254 $user4->firstname = 'Kyle'; 1255 $user4->lastname = 'Broflovski'; 1256 $user4 = self::getDataGenerator()->create_user($user4); 1257 $user5 = new \stdClass(); 1258 $user5->firstname = 'Kenny'; 1259 $user5->lastname = 'McCormick'; 1260 $user5 = self::getDataGenerator()->create_user($user5); 1261 self::getDataGenerator()->enrol_user($user5->id, $course2->id); 1262 1263 $this->setUser($user1); 1264 1265 $results = core_message_external::search_contacts('r'); 1266 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1267 $this->assertCount(5, $results); // Users 2 through 5 + admin 1268 1269 $results = core_message_external::search_contacts('r', true); 1270 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1271 $this->assertCount(2, $results); 1272 1273 $results = core_message_external::search_contacts('Kyle', false); 1274 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1275 $this->assertCount(1, $results); 1276 $result = reset($results); 1277 $this->assertEquals($user4->id, $result['id']); 1278 1279 $results = core_message_external::search_contacts('y', false); 1280 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1281 $this->assertCount(2, $results); 1282 1283 $results = core_message_external::search_contacts('y', true); 1284 $results = \external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results); 1285 $this->assertCount(1, $results); 1286 $result = reset($results); 1287 $this->assertEquals($user5->id, $result['id']); 1288 1289 // Empty query, will throw an exception. 1290 $this->expectException(\moodle_exception::class); 1291 $results = core_message_external::search_contacts(''); 1292 } 1293 1294 /** 1295 * Test get_messages. 1296 */ 1297 public function test_get_messages() { 1298 global $CFG, $DB; 1299 $this->resetAfterTest(true); 1300 1301 $this->preventResetByRollback(); 1302 // This mark the messages as read!. 1303 $sink = $this->redirectMessages(); 1304 1305 $user1 = self::getDataGenerator()->create_user(); 1306 $user2 = self::getDataGenerator()->create_user(); 1307 $user3 = self::getDataGenerator()->create_user(); 1308 1309 $course = self::getDataGenerator()->create_course(); 1310 1311 // Send a message from one user to another. 1312 message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); 1313 message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE); 1314 message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); 1315 message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); 1316 message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE); 1317 1318 $this->setUser($user1); 1319 // Get read conversations from user1 to user2. 1320 $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0); 1321 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1322 $this->assertCount(1, $messages['messages']); 1323 1324 // Delete the message. 1325 $message = array_shift($messages['messages']); 1326 \core_message\api::delete_message($user1->id, $message['id']); 1327 1328 $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0); 1329 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1330 $this->assertCount(0, $messages['messages']); 1331 1332 // Get unread conversations from user1 to user2. 1333 $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0); 1334 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1335 $this->assertCount(0, $messages['messages']); 1336 1337 // Get read messages send from user1. 1338 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); 1339 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1340 $this->assertCount(1, $messages['messages']); 1341 1342 $this->setUser($user2); 1343 // Get read conversations from any user to user2. 1344 $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0); 1345 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1346 $this->assertCount(2, $messages['messages']); 1347 1348 // Conversations from user3 to user2. 1349 $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0); 1350 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1351 $this->assertCount(1, $messages['messages']); 1352 1353 // Delete the message. 1354 $message = array_shift($messages['messages']); 1355 \core_message\api::delete_message($user2->id, $message['id']); 1356 1357 $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0); 1358 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1359 $this->assertCount(0, $messages['messages']); 1360 1361 $this->setUser($user3); 1362 // Get read notifications received by user3. 1363 $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0); 1364 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1365 $this->assertCount(0, $messages['messages']); 1366 1367 // Now, create some notifications... 1368 // We are creating fake notifications but based on real ones. 1369 1370 // This one comes from a disabled plugin's provider and therefore is not sent. 1371 $eventdata = new \core\message\message(); 1372 $eventdata->courseid = $course->id; 1373 $eventdata->notification = 1; 1374 $eventdata->modulename = 'moodle'; 1375 $eventdata->component = 'enrol_paypal'; 1376 $eventdata->name = 'paypal_enrolment'; 1377 $eventdata->userfrom = get_admin(); 1378 $eventdata->userto = $user1; 1379 $eventdata->subject = "Moodle: PayPal payment"; 1380 $eventdata->fullmessage = "Your PayPal payment is pending."; 1381 $eventdata->fullmessageformat = FORMAT_PLAIN; 1382 $eventdata->fullmessagehtml = ''; 1383 $eventdata->smallmessage = ''; 1384 message_send($eventdata); 1385 $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '. 1386 'that is inactive or not allowed for the user id='.$user1->id); 1387 1388 // This one omits notification = 1. 1389 $message = new \core\message\message(); 1390 $message->courseid = $course->id; 1391 $message->component = 'enrol_manual'; 1392 $message->name = 'expiry_notification'; 1393 $message->userfrom = $user2; 1394 $message->userto = $user1; 1395 $message->subject = 'Test: This is not a notification but otherwise is valid'; 1396 $message->fullmessage = 'Test: Full message'; 1397 $message->fullmessageformat = FORMAT_MARKDOWN; 1398 $message->fullmessagehtml = markdown_to_html($message->fullmessage); 1399 $message->smallmessage = $message->subject; 1400 $message->contexturlname = $course->fullname; 1401 $message->contexturl = (string)new \moodle_url('/course/view.php', array('id' => $course->id)); 1402 message_send($message); 1403 1404 $message = new \core\message\message(); 1405 $message->courseid = $course->id; 1406 $message->notification = 1; 1407 $message->component = 'enrol_manual'; 1408 $message->name = 'expiry_notification'; 1409 $message->userfrom = $user2; 1410 $message->userto = $user1; 1411 $message->subject = 'Enrolment expired'; 1412 $message->fullmessage = 'Enrolment expired blah blah blah'; 1413 $message->fullmessageformat = FORMAT_MARKDOWN; 1414 $message->fullmessagehtml = markdown_to_html($message->fullmessage); 1415 $message->smallmessage = $message->subject; 1416 $message->contexturlname = $course->fullname; 1417 $message->contexturl = (string)new \moodle_url('/course/view.php', array('id' => $course->id)); 1418 message_send($message); 1419 1420 $userfrom = \core_user::get_noreply_user(); 1421 $userfrom->maildisplay = true; 1422 $eventdata = new \core\message\message(); 1423 $eventdata->courseid = $course->id; 1424 $eventdata->component = 'moodle'; 1425 $eventdata->name = 'badgecreatornotice'; 1426 $eventdata->userfrom = $userfrom; 1427 $eventdata->userto = $user1; 1428 $eventdata->notification = 1; 1429 $eventdata->subject = 'New badge'; 1430 $eventdata->fullmessage = format_text_email($eventdata->subject, FORMAT_HTML); 1431 $eventdata->fullmessageformat = FORMAT_PLAIN; 1432 $eventdata->fullmessagehtml = $eventdata->subject; 1433 $eventdata->smallmessage = $eventdata->subject; 1434 message_send($eventdata); 1435 1436 $eventdata = new \core\message\message(); 1437 $eventdata->courseid = $course->id; 1438 $eventdata->name = 'submission'; 1439 $eventdata->component = 'mod_feedback'; 1440 $eventdata->userfrom = $user1; 1441 $eventdata->userto = $user2; 1442 $eventdata->subject = 'Feedback submitted'; 1443 $eventdata->fullmessage = 'Feedback submitted from an user'; 1444 $eventdata->fullmessageformat = FORMAT_PLAIN; 1445 $eventdata->fullmessagehtml = '<strong>Feedback submitted</strong>'; 1446 $eventdata->smallmessage = ''; 1447 $eventdata->customdata = ['datakey' => 'data']; 1448 message_send($eventdata); 1449 1450 $this->setUser($user1); 1451 // Get read notifications from any user to user1. 1452 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0); 1453 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1454 $this->assertCount(3, $messages['messages']); 1455 1456 // Get one read notifications from any user to user1. 1457 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1); 1458 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1459 $this->assertCount(1, $messages['messages']); 1460 1461 // Get unread notifications from any user to user1. 1462 $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0); 1463 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1464 $this->assertCount(0, $messages['messages']); 1465 1466 // Get read both type of messages from any user to user1. 1467 $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0); 1468 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1469 $this->assertCount(4, $messages['messages']); 1470 1471 // Get read notifications from no-reply-user to user1. 1472 $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0); 1473 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1474 $this->assertCount(1, $messages['messages']); 1475 1476 // Get notifications send by user1 to any user. 1477 $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0); 1478 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1479 $this->assertCount(1, $messages['messages']); 1480 // Check we receive custom data as a unserialisable json. 1481 $this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata'])); 1482 $this->assertEquals('mod_feedback', $messages['messages'][0]['component']); 1483 $this->assertEquals('submission', $messages['messages'][0]['eventtype']); 1484 1485 // Test warnings. 1486 $CFG->messaging = 0; 1487 1488 $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0); 1489 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1490 $this->assertCount(1, $messages['warnings']); 1491 1492 // Test exceptions. 1493 1494 // Messaging disabled. 1495 try { 1496 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); 1497 $this->fail('Exception expected due messaging disabled.'); 1498 } catch (\moodle_exception $e) { 1499 $this->assertEquals('disabled', $e->errorcode); 1500 } 1501 1502 $CFG->messaging = 1; 1503 1504 // Invalid users. 1505 try { 1506 $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0); 1507 $this->fail('Exception expected due invalid users.'); 1508 } catch (\moodle_exception $e) { 1509 $this->assertEquals('accessdenied', $e->errorcode); 1510 } 1511 1512 // Invalid user ids. 1513 try { 1514 $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0); 1515 $this->fail('Exception expected due invalid users.'); 1516 } catch (\moodle_exception $e) { 1517 $this->assertEquals('invaliduser', $e->errorcode); 1518 } 1519 1520 // Invalid users (permissions). 1521 $this->setUser($user2); 1522 try { 1523 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); 1524 $this->fail('Exception expected due invalid user.'); 1525 } catch (\moodle_exception $e) { 1526 $this->assertEquals('accessdenied', $e->errorcode); 1527 } 1528 1529 } 1530 1531 /** 1532 * Test get_messages where we want all messages from a user, sent to any user. 1533 */ 1534 public function test_get_messages_useridto_all() { 1535 $this->resetAfterTest(true); 1536 1537 $user1 = self::getDataGenerator()->create_user(); 1538 $user2 = self::getDataGenerator()->create_user(); 1539 $user3 = self::getDataGenerator()->create_user(); 1540 1541 $this->setUser($user1); 1542 1543 // Send a message from user 1 to two other users. 1544 $this->send_message($user1, $user2, 'some random text 1', 0, 1); 1545 $this->send_message($user1, $user3, 'some random text 2', 0, 2); 1546 1547 // Get messages sent from user 1. 1548 $messages = core_message_external::get_messages(0, $user1->id, 'conversations', false, false, 0, 0); 1549 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1550 1551 // Confirm the data is correct. 1552 $messages = $messages['messages']; 1553 $this->assertCount(2, $messages); 1554 1555 $message1 = array_shift($messages); 1556 $message2 = array_shift($messages); 1557 1558 $this->assertEquals($user1->id, $message1['useridfrom']); 1559 $this->assertEquals($user2->id, $message1['useridto']); 1560 1561 $this->assertEquals($user1->id, $message2['useridfrom']); 1562 $this->assertEquals($user3->id, $message2['useridto']); 1563 } 1564 1565 /** 1566 * Test get_messages where we want all messages to a user, sent by any user. 1567 */ 1568 public function test_get_messages_useridfrom_all() { 1569 $this->resetAfterTest(); 1570 1571 $user1 = self::getDataGenerator()->create_user(); 1572 $user2 = self::getDataGenerator()->create_user(); 1573 $user3 = self::getDataGenerator()->create_user(); 1574 1575 $this->setUser($user1); 1576 1577 // Send a message to user 1 from two other users. 1578 $this->send_message($user2, $user1, 'some random text 1', 0, 1); 1579 $this->send_message($user3, $user1, 'some random text 2', 0, 2); 1580 1581 // Get messages sent to user 1. 1582 $messages = core_message_external::get_messages($user1->id, 0, 'conversations', false, false, 0, 0); 1583 $messages = \external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); 1584 1585 // Confirm the data is correct. 1586 $messages = $messages['messages']; 1587 $this->assertCount(2, $messages); 1588 1589 $message1 = array_shift($messages); 1590 $message2 = array_shift($messages); 1591 1592 $this->assertEquals($user2->id, $message1['useridfrom']); 1593 $this->assertEquals($user1->id, $message1['useridto']); 1594 1595 $this->assertEquals($user3->id, $message2['useridfrom']); 1596 $this->assertEquals($user1->id, $message2['useridto']); 1597 } 1598 1599 /** 1600 * Test get_blocked_users. 1601 */ 1602 public function test_get_blocked_users() { 1603 $this->resetAfterTest(true); 1604 1605 $user1 = self::getDataGenerator()->create_user(); 1606 $userstranger = self::getDataGenerator()->create_user(); 1607 $useroffline1 = self::getDataGenerator()->create_user(); 1608 $useroffline2 = self::getDataGenerator()->create_user(); 1609 $userblocked = self::getDataGenerator()->create_user(); 1610 1611 // Login as user1. 1612 $this->setUser($user1); 1613 1614 \core_message\api::add_contact($user1->id, $useroffline1->id); 1615 \core_message\api::add_contact($user1->id, $useroffline2->id); 1616 1617 // The userstranger sends a couple of messages to user1. 1618 $this->send_message($userstranger, $user1, 'Hello there!'); 1619 $this->send_message($userstranger, $user1, 'How you goin?'); 1620 1621 // The userblocked sends a message to user1. 1622 // Note that this user is not blocked at this point. 1623 $this->send_message($userblocked, $user1, 'Here, have some spam.'); 1624 1625 // Retrieve the list of blocked users. 1626 $this->setUser($user1); 1627 $blockedusers = core_message_external::get_blocked_users($user1->id); 1628 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1629 $this->assertCount(0, $blockedusers['users']); 1630 1631 // Block the $userblocked and retrieve again the list. 1632 \core_message\api::block_user($user1->id, $userblocked->id); 1633 $blockedusers = core_message_external::get_blocked_users($user1->id); 1634 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1635 $this->assertCount(1, $blockedusers['users']); 1636 1637 // Remove the $userblocked and check that the list now is empty. 1638 delete_user($userblocked); 1639 $blockedusers = core_message_external::get_blocked_users($user1->id); 1640 $blockedusers = \external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers); 1641 $this->assertCount(0, $blockedusers['users']); 1642 } 1643 1644 /** 1645 * Test mark_message_read. 1646 */ 1647 public function test_mark_message_read() { 1648 $this->resetAfterTest(true); 1649 1650 $user1 = self::getDataGenerator()->create_user(); 1651 $user2 = self::getDataGenerator()->create_user(); 1652 $user3 = self::getDataGenerator()->create_user(); 1653 1654 // Login as user1. 1655 $this->setUser($user1); 1656 \core_message\api::add_contact($user1->id, $user2->id); 1657 \core_message\api::add_contact($user1->id, $user3->id); 1658 1659 // The user2 sends a couple of messages to user1. 1660 $this->send_message($user2, $user1, 'Hello there!'); 1661 $this->send_message($user2, $user1, 'How you goin?'); 1662 $this->send_message($user3, $user1, 'How you goin?'); 1663 $this->send_message($user3, $user2, 'How you goin?'); 1664 1665 // Retrieve all messages sent by user2 (they are currently unread). 1666 $lastmessages = message_get_messages($user1->id, $user2->id, 0, false); 1667 1668 $messageids = array(); 1669 foreach ($lastmessages as $m) { 1670 $messageid = core_message_external::mark_message_read($m->id, time()); 1671 $messageids[] = \external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid); 1672 } 1673 1674 // Retrieve all messages sent (they are currently read). 1675 $lastmessages = message_get_messages($user1->id, $user2->id, 0, true); 1676 $this->assertCount(2, $lastmessages); 1677 $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages); 1678 $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages); 1679 1680 // Retrieve all messages sent by any user (that are currently unread). 1681 $lastmessages = message_get_messages($user1->id, 0, 0, false); 1682 $this->assertCount(1, $lastmessages); 1683 1684 // Invalid message ids. 1685 try { 1686 $messageid = core_message_external::mark_message_read(1337, time()); 1687 $this->fail('Exception expected due invalid messageid.'); 1688 } catch (\dml_missing_record_exception $e) { 1689 $this->assertEquals('invalidrecordunknown', $e->errorcode); 1690 } 1691 1692 // A message to a different user. 1693 $lastmessages = message_get_messages($user2->id, $user3->id, 0, false); 1694 $messageid = array_pop($lastmessages)->id; 1695 try { 1696 $messageid = core_message_external::mark_message_read($messageid, time()); 1697 $this->fail('Exception expected due invalid messageid.'); 1698 } catch (\invalid_parameter_exception $e) { 1699 $this->assertEquals('invalidparameter', $e->errorcode); 1700 } 1701 } 1702 1703 /** 1704 * Test mark_notification_read. 1705 */ 1706 public function test_mark_notification_read() { 1707 $this->resetAfterTest(true); 1708 1709 $user1 = self::getDataGenerator()->create_user(); 1710 $user2 = self::getDataGenerator()->create_user(); 1711 $user3 = self::getDataGenerator()->create_user(); 1712 1713 // Login as user1. 1714 $this->setUser($user1); 1715 \core_message\api::add_contact($user1->id, $user2->id); 1716 \core_message\api::add_contact($user1->id, $user3->id); 1717 1718 // The user2 sends a couple of notifications to user1. 1719 $this->send_message($user2, $user1, 'Hello there!', 1); 1720 $this->send_message($user2, $user1, 'How you goin?', 1); 1721 $this->send_message($user3, $user1, 'How you goin?', 1); 1722 $this->send_message($user3, $user2, 'How you goin?', 1); 1723 1724 // Retrieve all notifications sent by user2 (they are currently unread). 1725 $lastnotifications = message_get_messages($user1->id, $user2->id, 1, false); 1726 1727 $notificationids = array(); 1728 foreach ($lastnotifications as $n) { 1729 $notificationid = core_message_external::mark_notification_read($n->id, time()); 1730 $notificationids[] = \external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(), 1731 $notificationid); 1732 } 1733 1734 // Retrieve all notifications sent (they are currently read). 1735 $lastnotifications = message_get_messages($user1->id, $user2->id, 1, true); 1736 $this->assertCount(2, $lastnotifications); 1737 $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications); 1738 $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications); 1739 1740 // Retrieve all notifications sent by any user (that are currently unread). 1741 $lastnotifications = message_get_messages($user1->id, 0, 1, false); 1742 $this->assertCount(1, $lastnotifications); 1743 1744 // Invalid notification ids. 1745 try { 1746 $notificationid = core_message_external::mark_notification_read(1337, time()); 1747 $this->fail('Exception expected due invalid notificationid.'); 1748 } catch (\dml_missing_record_exception $e) { 1749 $this->assertEquals('invalidrecord', $e->errorcode); 1750 } 1751 1752 // A notification to a different user. 1753 $lastnotifications = message_get_messages($user2->id, $user3->id, 1, false); 1754 $notificationid = array_pop($lastnotifications)->id; 1755 try { 1756 $notificationid = core_message_external::mark_notification_read($notificationid, time()); 1757 $this->fail('Exception expected due invalid notificationid.'); 1758 } catch (\invalid_parameter_exception $e) { 1759 $this->assertEquals('invalidparameter', $e->errorcode); 1760 } 1761 } 1762 1763 /** 1764 * Test delete_message. 1765 */ 1766 public function test_delete_message() { 1767 global $DB; 1768 $this->resetAfterTest(true); 1769 1770 $user1 = self::getDataGenerator()->create_user(); 1771 $user2 = self::getDataGenerator()->create_user(); 1772 $user3 = self::getDataGenerator()->create_user(); 1773 $user4 = self::getDataGenerator()->create_user(); 1774 1775 // Login as user1. 1776 $this->setUser($user1); 1777 \core_message\api::add_contact($user1->id, $user2->id); 1778 \core_message\api::add_contact($user1->id, $user3->id); 1779 1780 // User user1 does not interchange messages with user3. 1781 $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); 1782 $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); 1783 $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); 1784 $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE); 1785 1786 // Retrieve all messages sent by user2 (they are currently unread). 1787 $lastmessages = message_get_messages($user1->id, $user2->id, 0, false); 1788 1789 // Delete a message not read, as a user from. 1790 $result = core_message_external::delete_message($m1to2, $user1->id, false); 1791 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1792 $this->assertTrue($result['status']); 1793 $this->assertCount(0, $result['warnings']); 1794 $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id)); 1795 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action); 1796 1797 // Try to delete the same message again. 1798 $result = core_message_external::delete_message($m1to2, $user1->id, false); 1799 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1800 $this->assertFalse($result['status']); 1801 1802 // Try to delete a message that does not belong to me. 1803 try { 1804 $messageid = core_message_external::delete_message($m2to3, $user3->id, false); 1805 $this->fail('Exception expected due invalid messageid.'); 1806 } catch (\moodle_exception $e) { 1807 $this->assertEquals('You do not have permission to delete this message', $e->errorcode); 1808 } 1809 1810 $this->setUser($user3); 1811 // Delete a message not read, as a user to. 1812 $result = core_message_external::delete_message($m2to3, $user3->id, false); 1813 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1814 $this->assertTrue($result['status']); 1815 $this->assertCount(0, $result['warnings']); 1816 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id, 1817 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1818 1819 // Delete a message read. 1820 $message = $DB->get_record('messages', ['id' => $m3to2]); 1821 \core_message\api::mark_message_as_read($user3->id, $message, time()); 1822 $result = core_message_external::delete_message($m3to2, $user3->id); 1823 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1824 $this->assertTrue($result['status']); 1825 $this->assertCount(0, $result['warnings']); 1826 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id, 1827 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1828 1829 // Invalid message ids. 1830 try { 1831 $result = core_message_external::delete_message(-1, $user1->id); 1832 $this->fail('Exception expected due invalid messageid.'); 1833 } catch (\dml_missing_record_exception $e) { 1834 $this->assertEquals('invalidrecord', $e->errorcode); 1835 } 1836 1837 // Invalid user. 1838 try { 1839 $result = core_message_external::delete_message($m1to2, -1, false); 1840 $this->fail('Exception expected due invalid user.'); 1841 } catch (\moodle_exception $e) { 1842 $this->assertEquals('invaliduser', $e->errorcode); 1843 } 1844 1845 // Not active user. 1846 delete_user($user2); 1847 try { 1848 $result = core_message_external::delete_message($m1to2, $user2->id, false); 1849 $this->fail('Exception expected due invalid user.'); 1850 } catch (\moodle_exception $e) { 1851 $this->assertEquals('userdeleted', $e->errorcode); 1852 } 1853 1854 // Now, as an admin, try to delete any message. 1855 $this->setAdminUser(); 1856 $result = core_message_external::delete_message($m3to4, $user4->id, false); 1857 $result = \external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result); 1858 $this->assertTrue($result['status']); 1859 $this->assertCount(0, $result['warnings']); 1860 $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id, 1861 'action' => \core_message\api::MESSAGE_ACTION_DELETED))); 1862 1863 } 1864 1865 public function test_mark_all_notifications_as_read_invalid_user_exception() { 1866 $this->resetAfterTest(true); 1867 1868 $this->expectException('moodle_exception'); 1869 core_message_external::mark_all_notifications_as_read(-2132131, 0); 1870 } 1871 1872 public function test_mark_all_notifications_as_read_access_denied_exception() { 1873 $this->resetAfterTest(true); 1874 1875 $sender = $this->getDataGenerator()->create_user(); 1876 $user = $this->getDataGenerator()->create_user(); 1877 1878 $this->setUser($user); 1879 $this->expectException('moodle_exception'); 1880 core_message_external::mark_all_notifications_as_read($sender->id, 0); 1881 } 1882 1883 public function test_mark_all_notifications_as_read_missing_from_user_exception() { 1884 $this->resetAfterTest(true); 1885 1886 $sender = $this->getDataGenerator()->create_user(); 1887 1888 $this->setUser($sender); 1889 $this->expectException('moodle_exception'); 1890 core_message_external::mark_all_notifications_as_read($sender->id, 99999); 1891 } 1892 1893 public function test_mark_all_notifications_as_read() { 1894 global $DB; 1895 1896 $this->resetAfterTest(true); 1897 1898 $sender1 = $this->getDataGenerator()->create_user(); 1899 $sender2 = $this->getDataGenerator()->create_user(); 1900 $sender3 = $this->getDataGenerator()->create_user(); 1901 $recipient = $this->getDataGenerator()->create_user(); 1902 1903 $this->setUser($recipient); 1904 1905 $this->send_message($sender1, $recipient, 'Notification', 1); 1906 $this->send_message($sender1, $recipient, 'Notification', 1); 1907 $this->send_message($sender2, $recipient, 'Notification', 1); 1908 $this->send_message($sender2, $recipient, 'Notification', 1); 1909 $this->send_message($sender3, $recipient, 'Notification', 1); 1910 $this->send_message($sender3, $recipient, 'Notification', 1); 1911 1912 core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id); 1913 $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]); 1914 $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]); 1915 1916 $this->assertCount(2, $readnotifications); 1917 $this->assertCount(4, $unreadnotifications); 1918 1919 core_message_external::mark_all_notifications_as_read($recipient->id, 0); 1920 $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]); 1921 $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]); 1922 1923 $this->assertCount(6, $readnotifications); 1924 $this->assertCount(0, $unreadnotifications); 1925 } 1926 1927 public function test_mark_all_notifications_as_read_time_created_to() { 1928 global $DB; 1929 1930 $this->resetAfterTest(true); 1931 1932 $sender1 = $this->getDataGenerator()->create_user(); 1933 $sender2 = $this->getDataGenerator()->create_user(); 1934 1935 $recipient = $this->getDataGenerator()->create_user(); 1936 $this->setUser($recipient); 1937 1938 // Record messages as sent on one second intervals. 1939 $time = time(); 1940 1941 $this->send_message($sender1, $recipient, 'Message 1', 1, $time); 1942 $this->send_message($sender2, $recipient, 'Message 2', 1, $time + 1); 1943 $this->send_message($sender1, $recipient, 'Message 3', 1, $time + 2); 1944 $this->send_message($sender2, $recipient, 'Message 4', 1, $time + 3); 1945 1946 // Mark notifications sent from sender1 up until the second message; should only mark the first notification as read. 1947 core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id, $time + 1); 1948 1949 $params = [$recipient->id]; 1950 1951 $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1952 $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1953 1954 // Mark all notifications as read from any sender up to the time the third message was sent. 1955 core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 2); 1956 1957 $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1958 $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1959 1960 // Mark all notifications as read from any sender with a time after all messages were sent. 1961 core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 10); 1962 1963 $this->assertEquals(4, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params)); 1964 $this->assertEquals(0, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params)); 1965 } 1966 1967 /** 1968 * Test get_user_notification_preferences 1969 */ 1970 public function test_get_user_notification_preferences() { 1971 $this->resetAfterTest(true); 1972 1973 $user = self::getDataGenerator()->create_user(); 1974 $this->setUser($user); 1975 1976 // Set a couple of preferences to test. 1977 set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user); 1978 set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user); 1979 1980 $prefs = core_message_external::get_user_notification_preferences(); 1981 $prefs = \external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs); 1982 // Check processors. 1983 $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors'])); 1984 $this->assertEquals($user->id, $prefs['preferences']['userid']); 1985 1986 // Check components. 1987 $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components'])); 1988 1989 // Check some preferences that we previously set. 1990 $found = 0; 1991 foreach ($prefs['preferences']['components'] as $component) { 1992 foreach ($component['notifications'] as $prefdata) { 1993 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') { 1994 continue; 1995 } 1996 foreach ($prefdata['processors'] as $processor) { 1997 if ($processor['name'] == 'popup') { 1998 $this->assertTrue($processor['loggedin']['checked']); 1999 $found++; 2000 } else if ($processor['name'] == 'email') { 2001 $this->assertTrue($processor['loggedoff']['checked']); 2002 $found++; 2003 } 2004 } 2005 } 2006 } 2007 $this->assertEquals(2, $found); 2008 } 2009 2010 /** 2011 * Test get_user_notification_preferences permissions 2012 */ 2013 public function test_get_user_notification_preferences_permissions() { 2014 $this->resetAfterTest(true); 2015 2016 $user = self::getDataGenerator()->create_user(); 2017 $otheruser = self::getDataGenerator()->create_user(); 2018 $this->setUser($user); 2019 2020 $this->expectException('moodle_exception'); 2021 $prefs = core_message_external::get_user_notification_preferences($otheruser->id); 2022 } 2023 2024 /** 2025 * Tests searching for users when site-wide messaging is disabled. 2026 * 2027 * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view. 2028 * If checks this by placing some users in the same course, where default caps would permit a user to view another user's 2029 * profile. 2030 */ 2031 public function test_message_search_users_messagingallusers_disabled() { 2032 global $DB; 2033 $this->resetAfterTest(); 2034 2035 // Create some users. 2036 $users = []; 2037 foreach (range(1, 8) as $i) { 2038 $user = new \stdClass(); 2039 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2040 $user->lastname = $i; 2041 $user = $this->getDataGenerator()->create_user($user); 2042 $users[$i] = $user; 2043 } 2044 2045 // Enrol a few users in the same course, but leave them as non-contacts. 2046 $course1 = $this->getDataGenerator()->create_course(); 2047 $course2 = $this->getDataGenerator()->create_course(); 2048 2049 $this->setAdminUser(); 2050 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2051 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2052 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2053 2054 // Add some other users as contacts. 2055 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2056 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2057 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2058 2059 // Enrol a user as a teacher in the course, and make the teacher role a course contact role. 2060 $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher'); 2061 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 2062 set_config('coursecontact', $teacherrole->id); 2063 2064 // Create individual conversations between some users, one contact and one non-contact. 2065 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2066 [$users[1]->id, $users[2]->id]); 2067 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2068 [$users[6]->id, $users[1]->id]); 2069 2070 // Create a group conversation between 4 users, including a contact and a non-contact. 2071 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2072 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat'); 2073 2074 // Set as the user performing the search. 2075 $this->setUser($users[1]); 2076 2077 // Perform a search with $CFG->messagingallusers disabled. 2078 set_config('messagingallusers', 0); 2079 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2080 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2081 2082 // Confirm that we returns contacts and non-contacts. 2083 $this->assertArrayHasKey('contacts', $result); 2084 $this->assertArrayHasKey('noncontacts', $result); 2085 $contacts = $result['contacts']; 2086 $noncontacts = $result['noncontacts']; 2087 2088 // Check that we retrieved the correct contacts. 2089 $this->assertCount(2, $contacts); 2090 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2091 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2092 2093 // Verify the correct conversations were returned for the contacts. 2094 $this->assertCount(2, $contacts[0]['conversations']); 2095 // We can't rely on the ordering of conversations within the results, so sort by id first. 2096 usort($contacts[0]['conversations'], function($a, $b) { 2097 return $b['id'] <=> $a['id']; 2098 }); 2099 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']); 2100 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']); 2101 2102 $this->assertCount(0, $contacts[1]['conversations']); 2103 2104 // Check that we retrieved the correct non-contacts. 2105 // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles 2106 // are visible in that course. This excludes users like course contacts. 2107 $this->assertCount(3, $noncontacts); 2108 // Self-conversation first. 2109 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2110 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2111 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2112 2113 // Verify the correct conversations were returned for the non-contacts. 2114 $this->assertCount(1, $noncontacts[1]['conversations']); 2115 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']); 2116 2117 $this->assertCount(1, $noncontacts[2]['conversations']); 2118 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']); 2119 } 2120 2121 /** 2122 * Tests searching for users when site-wide messaging is enabled. 2123 * 2124 * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user 2125 * can view their respective profile. 2126 */ 2127 public function test_message_search_users_messagingallusers_enabled() { 2128 global $DB; 2129 $this->resetAfterTest(); 2130 2131 // Create some users. 2132 $users = []; 2133 foreach (range(1, 9) as $i) { 2134 $user = new \stdClass(); 2135 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2136 $user->lastname = $i; 2137 $user = $this->getDataGenerator()->create_user($user); 2138 $users[$i] = $user; 2139 } 2140 2141 // Enrol a few users in the same course, but leave them as non-contacts. 2142 $course1 = $this->getDataGenerator()->create_course(); 2143 $course2 = $this->getDataGenerator()->create_course(); 2144 2145 $this->setAdminUser(); 2146 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2147 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2148 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2149 2150 // Add some other users as contacts. 2151 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2152 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2153 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2154 2155 // Enrol a user as a teacher in the course, and make the teacher role a course contact role. 2156 $this->getDataGenerator()->enrol_user($users[9]->id, $course2->id, 'editingteacher'); 2157 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 2158 set_config('coursecontact', $teacherrole->id); 2159 2160 // Create individual conversations between some users, one contact and one non-contact. 2161 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2162 [$users[1]->id, $users[2]->id]); 2163 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, 2164 [$users[6]->id, $users[1]->id]); 2165 2166 // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course. 2167 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2168 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat'); 2169 2170 // Set as the user performing the search. 2171 $this->setUser($users[1]); 2172 2173 // Perform a search with $CFG->messagingallusers enabled. 2174 set_config('messagingallusers', 1); 2175 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2176 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2177 2178 // Confirm that we returns contacts and non-contacts. 2179 $this->assertArrayHasKey('contacts', $result); 2180 $this->assertArrayHasKey('noncontacts', $result); 2181 $contacts = $result['contacts']; 2182 $noncontacts = $result['noncontacts']; 2183 2184 // Check that we retrieved the correct contacts. 2185 $this->assertCount(2, $contacts); 2186 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2187 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2188 2189 // Verify the correct conversations were returned for the contacts. 2190 $this->assertCount(2, $contacts[0]['conversations']); 2191 // We can't rely on the ordering of conversations within the results, so sort by id first. 2192 usort($contacts[0]['conversations'], function($a, $b) { 2193 return $b['id'] <=> $a['id']; 2194 }); 2195 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']); 2196 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']); 2197 2198 $this->assertCount(0, $contacts[1]['conversations']); 2199 2200 // Check that we retrieved the correct non-contacts. 2201 // If site wide messaging is enabled, we expect to be able to search for any users whose profiles we can view. 2202 // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1. 2203 $this->assertCount(4, $noncontacts); 2204 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2205 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2206 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2207 $this->assertEquals($users[9]->id, $noncontacts[3]['id']); 2208 2209 // Verify the correct conversations were returned for the non-contacts. 2210 $this->assertCount(1, $noncontacts[1]['conversations']); 2211 $this->assertCount(1, $noncontacts[2]['conversations']); 2212 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']); 2213 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']); 2214 $this->assertCount(0, $noncontacts[3]['conversations']); 2215 } 2216 2217 /** 2218 * Verify searching for users find themselves when they have self-conversations. 2219 */ 2220 public function test_message_search_users_self_conversations() { 2221 $this->resetAfterTest(); 2222 2223 // Create some users. 2224 $user1 = new \stdClass(); 2225 $user1->firstname = 'User'; 2226 $user1->lastname = 'One'; 2227 $user1 = $this->getDataGenerator()->create_user($user1); 2228 $user2 = new \stdClass(); 2229 $user2->firstname = 'User'; 2230 $user2->lastname = 'Two'; 2231 $user2 = $this->getDataGenerator()->create_user($user2); 2232 2233 // Get self-conversation for user1. 2234 $sc1 = \core_message\api::get_self_conversation($user1->id); 2235 testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!'); 2236 2237 // Perform a search as user1. 2238 $this->setUser($user1); 2239 $result = core_message_external::message_search_users($user1->id, 'One'); 2240 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2241 2242 // Check results are empty. 2243 $this->assertCount(0, $result['contacts']); 2244 $this->assertCount(1, $result['noncontacts']); 2245 } 2246 2247 /** 2248 * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found. 2249 */ 2250 public function test_message_search_users_with_empty_result() { 2251 $this->resetAfterTest(); 2252 2253 // Create some users, but make sure neither will match the search term. 2254 $user1 = new \stdClass(); 2255 $user1->firstname = 'User'; 2256 $user1->lastname = 'One'; 2257 $user1 = $this->getDataGenerator()->create_user($user1); 2258 $user2 = new \stdClass(); 2259 $user2->firstname = 'User'; 2260 $user2->lastname = 'Two'; 2261 $user2 = $this->getDataGenerator()->create_user($user2); 2262 2263 // Perform a search as user1. 2264 $this->setUser($user1); 2265 $result = core_message_external::message_search_users($user1->id, 'search'); 2266 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2267 2268 // Check results are empty. 2269 $this->assertCount(0, $result['contacts']); 2270 $this->assertCount(0, $result['noncontacts']); 2271 } 2272 2273 /** 2274 * Test verifying that limits and offsets work for both the contacts and non-contacts return data. 2275 */ 2276 public function test_message_search_users_limit_offset() { 2277 $this->resetAfterTest(); 2278 2279 // Create 20 users. 2280 $users = []; 2281 foreach (range(1, 20) as $i) { 2282 $user = new \stdClass(); 2283 $user->firstname = "User search"; 2284 $user->lastname = $i; 2285 $user = $this->getDataGenerator()->create_user($user); 2286 $users[$i] = $user; 2287 } 2288 2289 // Enrol the first 8 users in the same course, but leave them as non-contacts. 2290 $this->setAdminUser(); 2291 $course1 = $this->getDataGenerator()->create_course(); 2292 foreach (range(1, 8) as $i) { 2293 $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id); 2294 } 2295 2296 // Add 5 users, starting at the 11th user, as contacts for user1. 2297 foreach (range(11, 15) as $i) { 2298 \core_message\api::add_contact($users[1]->id, $users[$i]->id); 2299 } 2300 2301 // Set as the user performing the search. 2302 $this->setUser($users[1]); 2303 2304 // Search using a limit of 3. 2305 // This tests the case where we have more results than the limit for both contacts and non-contacts. 2306 $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3); 2307 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2308 $contacts = $result['contacts']; 2309 $noncontacts = $result['noncontacts']; 2310 2311 // Check that we retrieved the correct contacts. 2312 $this->assertCount(3, $contacts); 2313 $this->assertEquals($users[11]->id, $contacts[0]['id']); 2314 $this->assertEquals($users[12]->id, $contacts[1]['id']); 2315 $this->assertEquals($users[13]->id, $contacts[2]['id']); 2316 2317 // Check that we retrieved the correct non-contacts. 2318 // Consider first conversation is self-conversation. 2319 $this->assertCount(3, $noncontacts); 2320 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2321 $this->assertEquals($users[2]->id, $noncontacts[1]['id']); 2322 $this->assertEquals($users[3]->id, $noncontacts[2]['id']); 2323 2324 // Now, offset to get the next batch of results. 2325 // We expect to see 2 contacts, and 3 non-contacts. 2326 $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3); 2327 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2328 $contacts = $result['contacts']; 2329 $noncontacts = $result['noncontacts']; 2330 $this->assertCount(2, $contacts); 2331 $this->assertEquals($users[14]->id, $contacts[0]['id']); 2332 $this->assertEquals($users[15]->id, $contacts[1]['id']); 2333 2334 $this->assertCount(3, $noncontacts); 2335 $this->assertEquals($users[4]->id, $noncontacts[0]['id']); 2336 $this->assertEquals($users[5]->id, $noncontacts[1]['id']); 2337 $this->assertEquals($users[6]->id, $noncontacts[2]['id']); 2338 2339 // Now, offset to get the next batch of results. 2340 // We expect to see 0 contacts, and 2 non-contacts. 2341 $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3); 2342 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2343 $contacts = $result['contacts']; 2344 $noncontacts = $result['noncontacts']; 2345 $this->assertCount(0, $contacts); 2346 2347 $this->assertCount(2, $noncontacts); 2348 $this->assertEquals($users[7]->id, $noncontacts[0]['id']); 2349 $this->assertEquals($users[8]->id, $noncontacts[1]['id']); 2350 } 2351 2352 /** 2353 * Tests searching users as another user having the 'moodle/user:viewdetails' capability. 2354 */ 2355 public function test_message_search_users_with_cap() { 2356 $this->resetAfterTest(); 2357 global $DB; 2358 2359 // Create some users. 2360 $users = []; 2361 foreach (range(1, 8) as $i) { 2362 $user = new \stdClass(); 2363 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term. 2364 $user->lastname = $i; 2365 $user = $this->getDataGenerator()->create_user($user); 2366 $users[$i] = $user; 2367 } 2368 2369 // Enrol a few users in the same course, but leave them as non-contacts. 2370 $course1 = $this->getDataGenerator()->create_course(); 2371 $this->setAdminUser(); 2372 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id); 2373 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id); 2374 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id); 2375 2376 // Add some other users as contacts. 2377 \core_message\api::add_contact($users[1]->id, $users[2]->id); 2378 \core_message\api::add_contact($users[3]->id, $users[1]->id); 2379 \core_message\api::add_contact($users[1]->id, $users[4]->id); 2380 2381 // Set as the user performing the search. 2382 $this->setUser($users[1]); 2383 2384 // Grant the authenticated user role the capability 'user:viewdetails' at site context. 2385 $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST); 2386 assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, \context_system::instance()); 2387 2388 // Perform a search with $CFG->messagingallusers disabled. 2389 set_config('messagingallusers', 0); 2390 $result = core_message_external::message_search_users($users[1]->id, 'search'); 2391 $result = \external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result); 2392 $contacts = $result['contacts']; 2393 $noncontacts = $result['noncontacts']; 2394 2395 // Check that we retrieved the correct contacts. 2396 $this->assertCount(2, $contacts); 2397 $this->assertEquals($users[2]->id, $contacts[0]['id']); 2398 $this->assertEquals($users[3]->id, $contacts[1]['id']); 2399 2400 // Check that we retrieved the correct non-contacts. 2401 // Site-wide messaging is disabled, so we expect to be able to search for any users whose profile we can view. 2402 // Consider first conversations is self-conversation. 2403 $this->assertCount(3, $noncontacts); 2404 $this->assertEquals($users[1]->id, $noncontacts[0]['id']); 2405 $this->assertEquals($users[6]->id, $noncontacts[1]['id']); 2406 $this->assertEquals($users[7]->id, $noncontacts[2]['id']); 2407 } 2408 2409 /** 2410 * Tests searching users as another user without the 'moodle/user:viewdetails' capability. 2411 */ 2412 public function test_message_search_users_without_cap() { 2413 $this->resetAfterTest(); 2414 2415 // Create some users. 2416 $user1 = $this->getDataGenerator()->create_user(); 2417 $user2 = $this->getDataGenerator()->create_user(); 2418 2419 // The person doing the search for another user. 2420 $this->setUser($user1); 2421 2422 // Ensure an exception is thrown. 2423 $this->expectException('moodle_exception'); 2424 core_message_external::message_search_users($user2->id, 'User'); 2425 $this->assertDebuggingCalled(); 2426 } 2427 2428 /** 2429 * Tests searching users with messaging disabled. 2430 */ 2431 public function test_message_search_users_messaging_disabled() { 2432 $this->resetAfterTest(); 2433 2434 // Create some skeleton data just so we can call the WS. 2435 $user = $this->getDataGenerator()->create_user(); 2436 2437 // The person doing the search. 2438 $this->setUser($user); 2439 2440 // Disable messaging. 2441 set_config('messaging', 0); 2442 2443 // Ensure an exception is thrown. 2444 $this->expectException('moodle_exception'); 2445 core_message_external::message_search_users($user->id, 'User'); 2446 } 2447 2448 /** 2449 * Tests searching messages. 2450 */ 2451 public function test_messagearea_search_messages() { 2452 $this->resetAfterTest(true); 2453 2454 // Create some users. 2455 $user1 = self::getDataGenerator()->create_user(); 2456 $user2 = self::getDataGenerator()->create_user(); 2457 2458 // The person doing the search. 2459 $this->setUser($user1); 2460 2461 // Send some messages back and forth. 2462 $time = time(); 2463 $this->send_message($user1, $user2, 'Yo!', 0, $time); 2464 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 2465 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 2466 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 2467 $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); 2468 2469 // Perform a search. 2470 $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o'); 2471 2472 // We need to execute the return values cleaning process to simulate the web service server. 2473 $result = \external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result); 2474 2475 // Confirm the data is correct. 2476 $messages = $result['contacts']; 2477 $this->assertCount(2, $messages); 2478 2479 $message1 = $messages[0]; 2480 $message2 = $messages[1]; 2481 2482 $this->assertEquals($user2->id, $message1['userid']); 2483 $this->assertEquals(fullname($user2), $message1['fullname']); 2484 $this->assertTrue($message1['ismessaging']); 2485 $this->assertFalse($message1['sentfromcurrentuser']); 2486 $this->assertEquals('Word.', $message1['lastmessage']); 2487 $this->assertNotEmpty($message1['messageid']); 2488 $this->assertNull($message1['isonline']); 2489 $this->assertFalse($message1['isread']); 2490 $this->assertFalse($message1['isblocked']); 2491 $this->assertNull($message1['unreadcount']); 2492 $this->assertEquals($convid, $message1['conversationid']); 2493 2494 $this->assertEquals($user2->id, $message2['userid']); 2495 $this->assertEquals(fullname($user2), $message2['fullname']); 2496 $this->assertTrue($message2['ismessaging']); 2497 $this->assertTrue($message2['sentfromcurrentuser']); 2498 $this->assertEquals('Yo!', $message2['lastmessage']); 2499 $this->assertNotEmpty($message2['messageid']); 2500 $this->assertNull($message2['isonline']); 2501 $this->assertTrue($message2['isread']); 2502 $this->assertFalse($message2['isblocked']); 2503 $this->assertNull($message2['unreadcount']); 2504 $this->assertEquals($convid, $message2['conversationid']); 2505 } 2506 2507 /** 2508 * Tests searching messages as another user. 2509 */ 2510 public function test_messagearea_search_messages_as_other_user() { 2511 $this->resetAfterTest(true); 2512 2513 // The person doing the search. 2514 $this->setAdminUser(); 2515 2516 // Create some users. 2517 $user1 = self::getDataGenerator()->create_user(); 2518 $user2 = self::getDataGenerator()->create_user(); 2519 2520 // Send some messages back and forth. 2521 $time = time(); 2522 $this->send_message($user1, $user2, 'Yo!', 0, $time); 2523 $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1); 2524 $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2); 2525 $this->send_message($user2, $user1, 'Word.', 0, $time + 3); 2526 2527 // Perform a search. 2528 $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o'); 2529 2530 // We need to execute the return values cleaning process to simulate the web service server. 2531 $result = \external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), 2532 $result); 2533 2534 // Confirm the data is correct. 2535 $messages = $result['contacts']; 2536 $this->assertCount(2, $messages); 2537 2538 $message1 = $messages[0]; 2539 $message2 = $messages[1]; 2540 2541 $this->assertEquals($user2->id, $message1['userid']); 2542 $this->assertEquals(fullname($user2), $message1['fullname']); 2543 $this->assertTrue($message1['ismessaging']); 2544 $this->assertFalse($message1['sentfromcurrentuser']); 2545 $this->assertEquals('Word.', $message1['lastmessage']); 2546 $this->assertNotEmpty($message1['messageid']); 2547 $this->assertFalse($message1['isonline']); 2548 $this->assertFalse($message1['isread']); 2549 $this->assertFalse($message1['isblocked']); 2550 $this->assertNull($message1['unreadcount']); 2551 2552 $this->assertEquals($user2->id, $message2['userid']); 2553 $this->assertEquals(fullname($user2), $message2['fullname']); 2554 $this->assertTrue($message2['ismessaging']); 2555 $this->assertTrue($message2['sentfromcurrentuser']); 2556 $this->assertEquals('Yo!', $message2['lastmessage']); 2557 $this->assertNotEmpty($message2['messageid']); 2558 $this->assertFalse($message2['isonline']); 2559 $this->assertTrue($message2['isread']); 2560 $this->assertFalse($message2['isblocked']); 2561 $this->assertNull($message2['unreadcount']); 2562 } 2563 2564 /** 2565 * Tests searching messages as another user without the proper capabilities. 2566 */ 2567 public function test_messagearea_search_messages_as_other_user_without_cap() { 2568 $this->resetAfterTest(true); 2569 2570 // Create some users. 2571 $user1 = self::getDataGenerator()->create_user(); 2572 $user2 = self::getDataGenerator()->create_user(); 2573 2574 // The person doing the search for another user. 2575 $this->setUser($user1); 2576 2577 // Ensure an exception is thrown. 2578 $this->expectException('moodle_exception'); 2579 core_message_external::data_for_messagearea_search_messages($user2->id, 'Search'); 2580 } 2581 2582 /** 2583 * Tests searching messages with messaging disabled 2584 */ 2585 public function test_messagearea_search_messages_messaging_disabled() { 2586 global $CFG; 2587 2588 $this->resetAfterTest(true); 2589 2590 // Create some skeleton data just so we can call the WS. 2591 $user = self::getDataGenerator()->create_user(); 2592 2593 // The person doing the search . 2594 $this->setUser($user); 2595 2596 // Disable messaging. 2597 $CFG->messaging = 0; 2598 2599 // Ensure an exception is thrown. 2600 $this->expectException('moodle_exception'); 2601 core_message_external::data_for_messagearea_search_messages($user->id, 'Search'); 2602 } 2603 2604 /** 2605 * Tests retrieving contacts. 2606 */ 2607 public function test_get_user_contacts() { 2608 $this->resetAfterTest(true); 2609 2610 // Create some users. 2611 $user1 = self::getDataGenerator()->create_user(); 2612 2613 // Set as the user. 2614 $this->setUser($user1); 2615 2616 $user2 = new \stdClass(); 2617 $user2->firstname = 'User'; 2618 $user2->lastname = 'A'; 2619 $user2 = self::getDataGenerator()->create_user($user2); 2620 2621 $user3 = new \stdClass(); 2622 $user3->firstname = 'User'; 2623 $user3->lastname = 'B'; 2624 $user3 = self::getDataGenerator()->create_user($user3); 2625 2626 $user4 = new \stdClass(); 2627 $user4->firstname = 'User'; 2628 $user4->lastname = 'C'; 2629 $user4 = self::getDataGenerator()->create_user($user4); 2630 2631 $user5 = new \stdClass(); 2632 $user5->firstname = 'User'; 2633 $user5->lastname = 'D'; 2634 $user5 = self::getDataGenerator()->create_user($user5); 2635 2636 // Add some users as contacts. 2637 \core_message\api::add_contact($user1->id, $user2->id); 2638 \core_message\api::add_contact($user1->id, $user3->id); 2639 \core_message\api::add_contact($user1->id, $user4->id); 2640 2641 // Retrieve the contacts. 2642 $result = core_message_external::get_user_contacts($user1->id); 2643 2644 // We need to execute the return values cleaning process to simulate the web service server. 2645 $result = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), 2646 $result); 2647 2648 // Confirm the data is correct. 2649 $contacts = $result; 2650 usort($contacts, ['static', 'sort_contacts_id']); 2651 $this->assertCount(3, $contacts); 2652 2653 $contact1 = array_shift($contacts); 2654 $contact2 = array_shift($contacts); 2655 $contact3 = array_shift($contacts); 2656 2657 $this->assertEquals($user2->id, $contact1['id']); 2658 $this->assertEquals(fullname($user2), $contact1['fullname']); 2659 $this->assertTrue($contact1['iscontact']); 2660 2661 $this->assertEquals($user3->id, $contact2['id']); 2662 $this->assertEquals(fullname($user3), $contact2['fullname']); 2663 $this->assertTrue($contact2['iscontact']); 2664 2665 $this->assertEquals($user4->id, $contact3['id']); 2666 $this->assertEquals(fullname($user4), $contact3['fullname']); 2667 $this->assertTrue($contact3['iscontact']); 2668 } 2669 2670 /** 2671 * Tests retrieving contacts as another user. 2672 */ 2673 public function test_get_user_contacts_as_other_user() { 2674 $this->resetAfterTest(true); 2675 2676 $this->setAdminUser(); 2677 2678 // Create some users. 2679 $user1 = self::getDataGenerator()->create_user(); 2680 2681 $user2 = new \stdClass(); 2682 $user2->firstname = 'User'; 2683 $user2->lastname = 'A'; 2684 $user2 = self::getDataGenerator()->create_user($user2); 2685 2686 $user3 = new \stdClass(); 2687 $user3->firstname = 'User'; 2688 $user3->lastname = 'B'; 2689 $user3 = self::getDataGenerator()->create_user($user3); 2690 2691 $user4 = new \stdClass(); 2692 $user4->firstname = 'User'; 2693 $user4->lastname = 'C'; 2694 $user4 = self::getDataGenerator()->create_user($user4); 2695 2696 $user5 = new \stdClass(); 2697 $user5->firstname = 'User'; 2698 $user5->lastname = 'D'; 2699 $user5 = self::getDataGenerator()->create_user($user5); 2700 2701 // Add some users as contacts. 2702 \core_message\api::add_contact($user1->id, $user2->id); 2703 \core_message\api::add_contact($user1->id, $user3->id); 2704 \core_message\api::add_contact($user1->id, $user4->id); 2705 2706 // Retrieve the contacts. 2707 $result = core_message_external::get_user_contacts($user1->id); 2708 2709 // We need to execute the return values cleaning process to simulate the web service server. 2710 $result = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), 2711 $result); 2712 2713 // Confirm the data is correct. 2714 $contacts = $result; 2715 usort($contacts, ['static', 'sort_contacts_id']); 2716 $this->assertCount(3, $contacts); 2717 2718 $contact1 = array_shift($contacts); 2719 $contact2 = array_shift($contacts); 2720 $contact3 = array_shift($contacts); 2721 2722 $this->assertEquals($user2->id, $contact1['id']); 2723 $this->assertEquals(fullname($user2), $contact1['fullname']); 2724 $this->assertTrue($contact1['iscontact']); 2725 2726 $this->assertEquals($user3->id, $contact2['id']); 2727 $this->assertEquals(fullname($user3), $contact2['fullname']); 2728 $this->assertTrue($contact2['iscontact']); 2729 2730 $this->assertEquals($user4->id, $contact3['id']); 2731 $this->assertEquals(fullname($user4), $contact3['fullname']); 2732 $this->assertTrue($contact3['iscontact']); 2733 } 2734 2735 /** 2736 * Tests retrieving contacts as another user without the proper capabilities. 2737 */ 2738 public function test_get_user_contacts_as_other_user_without_cap() { 2739 $this->resetAfterTest(true); 2740 2741 // Create some users. 2742 $user1 = self::getDataGenerator()->create_user(); 2743 $user2 = self::getDataGenerator()->create_user(); 2744 2745 // The person retrieving the contacts for another user. 2746 $this->setUser($user1); 2747 2748 // Perform the WS call and ensure an exception is thrown. 2749 $this->expectException('moodle_exception'); 2750 core_message_external::get_user_contacts($user2->id); 2751 } 2752 2753 /** 2754 * Tests retrieving contacts with messaging disabled. 2755 */ 2756 public function test_get_user_contacts_messaging_disabled() { 2757 global $CFG; 2758 2759 $this->resetAfterTest(true); 2760 2761 // Create some skeleton data just so we can call the WS. 2762 $user = self::getDataGenerator()->create_user(); 2763 2764 // The person retrieving the contacts. 2765 $this->setUser($user); 2766 2767 // Disable messaging. 2768 $CFG->messaging = 0; 2769 2770 // Perform the WS call and ensure we are shown that it is disabled. 2771 $this->expectException('moodle_exception'); 2772 core_message_external::get_user_contacts($user->id); 2773 } 2774 2775 /** 2776 * Test getting contacts when there are no results. 2777 */ 2778 public function test_get_user_contacts_no_results() { 2779 $this->resetAfterTest(); 2780 2781 $user1 = self::getDataGenerator()->create_user(); 2782 2783 $this->setUser($user1); 2784 2785 $requests = core_message_external::get_user_contacts($user1->id); 2786 $requests = \external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), $requests); 2787 2788 $this->assertEmpty($requests); 2789 } 2790 2791 /** 2792 * Tests get_conversation_messages for retrieving messages. 2793 */ 2794 public function test_get_conversation_messages() { 2795 $this->resetAfterTest(true); 2796 2797 // Create some users. 2798 $user1 = self::getDataGenerator()->create_user(); 2799 $user2 = self::getDataGenerator()->create_user(); 2800 $user3 = self::getDataGenerator()->create_user(); 2801 $user4 = self::getDataGenerator()->create_user(); 2802 $user5 = self::getDataGenerator()->create_user(); 2803 2804 // Create group conversation. 2805 $conversation = \core_message\api::create_conversation( 2806 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2807 [$user1->id, $user2->id, $user3->id, $user4->id] 2808 ); 2809 2810 // The person asking for the messages. 2811 $this->setUser($user1); 2812 2813 // Send some messages back and forth. 2814 $time = time(); 2815 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time); 2816 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1); 2817 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2); 2818 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3); 2819 2820 // Retrieve the messages. 2821 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id); 2822 2823 // We need to execute the return values cleaning process to simulate the web service server. 2824 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2825 $result); 2826 2827 // Check the results are correct. 2828 $this->assertEquals($conversation->id, $result['id']); 2829 2830 // Confirm the members data is correct. 2831 $members = $result['members']; 2832 $this->assertCount(3, $members); 2833 $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']]; 2834 $this->assertContainsEquals($user1->id, $membersid); 2835 $this->assertContainsEquals($user2->id, $membersid); 2836 $this->assertContainsEquals($user3->id, $membersid); 2837 2838 $membersfullnames = [$members[0]['fullname'], $members[1]['fullname'], $members[2]['fullname']]; 2839 $this->assertContainsEquals(fullname($user1), $membersfullnames); 2840 $this->assertContainsEquals(fullname($user2), $membersfullnames); 2841 $this->assertContainsEquals(fullname($user3), $membersfullnames); 2842 2843 // Confirm the messages data is correct. 2844 $messages = $result['messages']; 2845 $this->assertCount(4, $messages); 2846 2847 $message1 = $messages[0]; 2848 $message2 = $messages[1]; 2849 $message3 = $messages[2]; 2850 $message4 = $messages[3]; 2851 2852 $this->assertEquals($user1->id, $message1['useridfrom']); 2853 $this->assertStringContainsString('Yo!', $message1['text']); 2854 2855 $this->assertEquals($user3->id, $message2['useridfrom']); 2856 $this->assertStringContainsString('Sup mang?', $message2['text']); 2857 2858 $this->assertEquals($user2->id, $message3['useridfrom']); 2859 $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']); 2860 2861 $this->assertEquals($user1->id, $message4['useridfrom']); 2862 $this->assertStringContainsString('Word.', $message4['text']); 2863 } 2864 2865 /** 2866 * Tests get_conversation_messages for retrieving messages using timefrom parameter. 2867 */ 2868 public function test_get_conversation_messages_timefrom() { 2869 $this->resetAfterTest(true); 2870 2871 // Create some users. 2872 $user1 = self::getDataGenerator()->create_user(); 2873 $user2 = self::getDataGenerator()->create_user(); 2874 $user3 = self::getDataGenerator()->create_user(); 2875 $user4 = self::getDataGenerator()->create_user(); 2876 2877 // Create group conversation. 2878 $conversation = \core_message\api::create_conversation( 2879 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, 2880 [$user1->id, $user2->id, $user3->id] 2881 ); 2882 2883 // The person asking for the messages. 2884 $this->setUser($user1); 2885 2886 // Send some messages back and forth. 2887 $time = time(); 2888 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time - 4); 2889 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time - 3); 2890 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 3', $time - 2); 2891 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 4', $time - 1); 2892 2893 // Retrieve the messages from $time - 3, which should be the 3 most recent messages. 2894 $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, false, $time - 3); 2895 2896 // We need to execute the return values cleaning process to simulate the web service server. 2897 $result = \external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(), 2898 $result); 2899 2900 // Check the results are correct. 2901 $this->assertEquals($conversation->id, $result['id']); 2902 2903 // Confirm the messages data is correct. 2904 $messages = $result['messages']; 2905 $this->assertCount(3, $messages); 2906 2907 $message1 = $messages[0]; 2908 $message2 = $messages[1]; 2909 $message3 = $messages[2]; 2910 2911 $this->assertStringContainsString('Message 2', $message1['text']); 2912 $this->assertStringContainsString('Message 3', $message2['text']); 2913 $this->assertStringContainsString('Message 4', $message3['text']); 2914 2915 // Confirm the members data is correct. 2916 $members = $result['members'];