MDL-65132 core_message: Added WS to delete message for all users
[moodle.git] / message / tests / externallib_test.php
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/>.
17 /**
18  * External message functions unit tests
19  *
20  * @package    core_message
21  * @category   external
22  * @copyright  2012 Jerome Mouneyrac
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
31 require_once($CFG->dirroot . '/message/externallib.php');
33 use \core_message\tests\helper as testhelper;
35 class core_message_externallib_testcase extends externallib_advanced_testcase {
37     /**
38      * Tests set up
39      */
40     protected function setUp() {
41         global $CFG;
43         require_once($CFG->dirroot . '/message/lib.php');
44     }
46     /**
47      * Send a fake message.
48      *
49      * {@link message_send()} does not support transaction, this function will simulate a message
50      * sent from a user to another. We should stop using it once {@link message_send()} will support
51      * transactions. This is not clean at all, this is just used to add rows to the table.
52      *
53      * @param stdClass $userfrom user object of the one sending the message.
54      * @param stdClass $userto user object of the one receiving the message.
55      * @param string $message message to send.
56      * @param int $notification is the message a notification.
57      * @param int $time the time the message was sent
58      */
59     protected function send_message($userfrom, $userto, $message = 'Hello world!', $notification = 0, $time = 0) {
60         global $DB;
62         if (empty($time)) {
63             $time = time();
64         }
66         if ($notification) {
67             $record = new stdClass();
68             $record->useridfrom = $userfrom->id;
69             $record->useridto = $userto->id;
70             $record->subject = 'No subject';
71             $record->fullmessage = $message;
72             $record->smallmessage = $message;
73             $record->timecreated = $time;
75             return $DB->insert_record('notifications', $record);
76         }
78         if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) {
79             $conversation = \core_message\api::create_conversation(
80                 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
81                 [
82                     $userfrom->id,
83                     $userto->id
84                 ]
85             );
86             $conversationid = $conversation->id;
87         }
89         // Ok, send the message.
90         $record = new stdClass();
91         $record->useridfrom = $userfrom->id;
92         $record->conversationid = $conversationid;
93         $record->subject = 'No subject';
94         $record->fullmessage = $message;
95         $record->smallmessage = $message;
96         $record->timecreated = $time;
98         return $DB->insert_record('messages', $record);
99     }
101     /**
102      * Test send_instant_messages.
103      */
104     public function test_send_instant_messages() {
105         global $DB, $USER;
107         $this->resetAfterTest();
109         // Transactions used in tests, tell phpunit use alternative reset method.
110         $this->preventResetByRollback();
112         $user1 = self::getDataGenerator()->create_user();
113         $user2 = self::getDataGenerator()->create_user();
115         $this->setUser($user1);
117         // Create test message data.
118         $message1 = array();
119         $message1['touserid'] = $user2->id;
120         $message1['text'] = 'the message.';
121         $message1['clientmsgid'] = 4;
122         $messages = array($message1);
124         $sentmessages = core_message_external::send_instant_messages($messages);
125         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
126         $this->assertEquals(
127             get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message1['touserid']))),
128             array_pop($sentmessages)['errormessage']
129         );
131         // Add the user1 as a contact.
132         \core_message\api::add_contact($user1->id, $user2->id);
134         // Send message again. Now it should work properly.
135         $sentmessages = core_message_external::send_instant_messages($messages);
136         // We need to execute the return values cleaning process to simulate the web service server.
137         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
139         $sentmessage = reset($sentmessages);
141         $sql = "SELECT m.*, mcm.userid as useridto
142                  FROM {messages} m
143            INNER JOIN {message_conversations} mc
144                    ON m.conversationid = mc.id
145            INNER JOIN {message_conversation_members} mcm
146                    ON mcm.conversationid = mc.id
147                 WHERE mcm.userid != ?
148                   AND m.id = ?";
149         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
151         // Confirm that the message was inserted correctly.
152         $this->assertEquals($themessage->useridfrom, $user1->id);
153         $this->assertEquals($themessage->useridto, $message1['touserid']);
154         $this->assertEquals($themessage->smallmessage, $message1['text']);
155         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
156     }
158     /**
159      * Test send_instant_messages to a user who has blocked you.
160      */
161     public function test_send_instant_messages_blocked_user() {
162         global $DB;
164         $this->resetAfterTest();
166         // Transactions used in tests, tell phpunit use alternative reset method.
167         $this->preventResetByRollback();
169         $user1 = self::getDataGenerator()->create_user();
170         $user2 = self::getDataGenerator()->create_user();
172         $this->setUser($user1);
174         \core_message\api::block_user($user2->id, $user1->id);
176         // Create test message data.
177         $message1 = array();
178         $message1['touserid'] = $user2->id;
179         $message1['text'] = 'the message.';
180         $message1['clientmsgid'] = 4;
181         $messages = array($message1);
183         $sentmessages = core_message_external::send_instant_messages($messages);
184         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
186         $sentmessage = reset($sentmessages);
188         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
190         $this->assertEquals(0, $DB->count_records('messages'));
191     }
193     /**
194      * Test send_instant_messages when sending a message to a non-contact who has blocked non-contacts.
195      */
196     public function test_send_instant_messages_block_non_contacts() {
197         global $DB;
199         $this->resetAfterTest(true);
201         // Transactions used in tests, tell phpunit use alternative reset method.
202         $this->preventResetByRollback();
204         $user1 = self::getDataGenerator()->create_user();
205         $user2 = self::getDataGenerator()->create_user();
207         $this->setUser($user1);
209         // Set the user preference so user 2 does not accept messages from non-contacts.
210         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
212         // Create test message data.
213         $message1 = array();
214         $message1['touserid'] = $user2->id;
215         $message1['text'] = 'the message.';
216         $message1['clientmsgid'] = 4;
217         $messages = array($message1);
219         $sentmessages = core_message_external::send_instant_messages($messages);
220         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
222         $sentmessage = reset($sentmessages);
224         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
226         $this->assertEquals(0, $DB->count_records('messages'));
227     }
229     /**
230      * Test send_instant_messages when sending a message to a contact who has blocked non-contacts.
231      */
232     public function test_send_instant_messages_block_non_contacts_but_am_contact() {
233         global $DB, $USER;
235         $this->resetAfterTest(true);
237         // Transactions used in tests, tell phpunit use alternative reset method.
238         $this->preventResetByRollback();
240         $user1 = self::getDataGenerator()->create_user();
241         $user2 = self::getDataGenerator()->create_user();
243         $this->setUser($user1);
245         // Set the user preference so user 2 does not accept messages from non-contacts.
246         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
248         \core_message\api::add_contact($user1->id, $user2->id);
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);
257         $sentmessages = core_message_external::send_instant_messages($messages);
258         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
260         $sentmessage = reset($sentmessages);
262         $sql = "SELECT m.*, mcm.userid as useridto
263                  FROM {messages} m
264            INNER JOIN {message_conversations} mc
265                    ON m.conversationid = mc.id
266            INNER JOIN {message_conversation_members} mcm
267                    ON mcm.conversationid = mc.id
268                 WHERE mcm.userid != ?
269                   AND m.id = ?";
270         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
272         // Confirm that the message was inserted correctly.
273         $this->assertEquals($themessage->useridfrom, $user1->id);
274         $this->assertEquals($themessage->useridto, $message1['touserid']);
275         $this->assertEquals($themessage->smallmessage, $message1['text']);
276         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
277     }
279     /**
280      * Test send_instant_messages with no capabilities
281      */
282     public function test_send_instant_messages_no_capability() {
283         global $DB;
285         $this->resetAfterTest(true);
287         // Transactions used in tests, tell phpunit use alternative reset method.
288         $this->preventResetByRollback();
290         $user1 = self::getDataGenerator()->create_user();
291         $user2 = self::getDataGenerator()->create_user();
293         $this->setUser($user1);
295         // Unset the required capabilities by the external function.
296         $contextid = context_system::instance()->id;
297         $userrole = $DB->get_record('role', array('shortname' => 'user'));
298         $this->unassignUserCapability('moodle/site:sendmessage', $contextid, $userrole->id);
300         // Create test message data.
301         $message1 = array();
302         $message1['touserid'] = $user2->id;
303         $message1['text'] = 'the message.';
304         $message1['clientmsgid'] = 4;
305         $messages = array($message1);
307         $this->expectException('required_capability_exception');
308         core_message_external::send_instant_messages($messages);
309     }
311     /**
312      * Test send_instant_messages when messaging is disabled.
313      */
314     public function test_send_instant_messages_messaging_disabled() {
315         global $CFG;
317         $this->resetAfterTest(true);
319         // Transactions used in tests, tell phpunit use alternative reset method.
320         $this->preventResetByRollback();
322         $user1 = self::getDataGenerator()->create_user();
323         $user2 = self::getDataGenerator()->create_user();
325         $this->setUser($user1);
327         // Disable messaging.
328         $CFG->messaging = 0;
330         // Create test message data.
331         $message1 = array();
332         $message1['touserid'] = $user2->id;
333         $message1['text'] = 'the message.';
334         $message1['clientmsgid'] = 4;
335         $messages = array($message1);
337         $this->expectException('moodle_exception');
338         core_message_external::send_instant_messages($messages);
339     }
341     /**
342      * Test create_contacts.
343      */
344     public function test_create_contacts() {
345         $this->resetAfterTest(true);
347         $user1 = self::getDataGenerator()->create_user();
348         $user2 = self::getDataGenerator()->create_user();
349         $user3 = self::getDataGenerator()->create_user();
350         $user4 = self::getDataGenerator()->create_user();
351         $user5 = self::getDataGenerator()->create_user();
352         $this->setUser($user1);
354         // Adding a contact.
355         $return = core_message_external::create_contacts(array($user2->id));
356         $this->assertDebuggingCalled();
357         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
358         $this->assertEquals(array(), $return);
360         // Adding a contact who is already a contact.
361         $return = core_message_external::create_contacts(array($user2->id));
362         $this->assertDebuggingCalled();
363         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
364         $this->assertEquals(array(), $return);
366         // Adding multiple contacts.
367         $return = core_message_external::create_contacts(array($user3->id, $user4->id));
368         $this->assertDebuggingCalledCount(2);
369         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
370         $this->assertEquals(array(), $return);
372         // Adding a non-existing user.
373         $return = core_message_external::create_contacts(array(99999));
374         $this->assertDebuggingCalled();
375         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
376         $this->assertCount(1, $return);
377         $return = array_pop($return);
378         $this->assertEquals($return['warningcode'], 'contactnotcreated');
379         $this->assertEquals($return['itemid'], 99999);
381         // Adding contacts with valid and invalid parameters.
382         $return = core_message_external::create_contacts(array($user5->id, 99999));
383         $this->assertDebuggingCalledCount(2);
384         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
385         $this->assertCount(1, $return);
386         $return = array_pop($return);
387         $this->assertEquals($return['warningcode'], 'contactnotcreated');
388         $this->assertEquals($return['itemid'], 99999);
390         // Try to add a contact to another user, should throw an exception.
391         // All assertions must be added before this point.
392         $this->expectException('required_capability_exception');
393         core_message_external::create_contacts(array($user2->id), $user3->id);
394     }
396     /**
397      * Test delete_contacts.
398      */
399     public function test_delete_contacts() {
400         $this->resetAfterTest(true);
402         $user1 = self::getDataGenerator()->create_user();
403         $user2 = self::getDataGenerator()->create_user();
404         $user3 = self::getDataGenerator()->create_user();
405         $user4 = self::getDataGenerator()->create_user();
406         $user5 = self::getDataGenerator()->create_user();
407         $user6 = self::getDataGenerator()->create_user();
408         $this->setUser($user1);
410         \core_message\api::add_contact($user1->id, $user3->id);
411         \core_message\api::add_contact($user1->id, $user4->id);
412         \core_message\api::add_contact($user1->id, $user5->id);
413         \core_message\api::add_contact($user1->id, $user6->id);
415         // Removing a non-contact.
416         $return = core_message_external::delete_contacts(array($user2->id));
417         $this->assertNull($return);
419         // Removing one contact.
420         $return = core_message_external::delete_contacts(array($user3->id));
421         $this->assertNull($return);
423         // Removing multiple contacts.
424         $return = core_message_external::delete_contacts(array($user4->id, $user5->id));
425         $this->assertNull($return);
427         // Removing contact from unexisting user.
428         $return = core_message_external::delete_contacts(array(99999));
429         $this->assertNull($return);
431         // Removing mixed valid and invalid data.
432         $return = core_message_external::delete_contacts(array($user6->id, 99999));
433         $this->assertNull($return);
435         // Try to delete a contact of another user contact list, should throw an exception.
436         // All assertions must be added before this point.
437         $this->expectException('required_capability_exception');
438         core_message_external::delete_contacts(array($user2->id), $user3->id);
439     }
441     /**
442      * Test block_contacts.
443      */
444     public function test_block_contacts() {
445         $this->resetAfterTest(true);
447         $user1 = self::getDataGenerator()->create_user();
448         $user2 = self::getDataGenerator()->create_user();
449         $user3 = self::getDataGenerator()->create_user();
450         $user4 = self::getDataGenerator()->create_user();
451         $user5 = self::getDataGenerator()->create_user();
452         $this->setUser($user1);
454         \core_message\api::add_contact($user1->id, $user3->id);
455         \core_message\api::add_contact($user1->id, $user4->id);
456         \core_message\api::add_contact($user1->id, $user5->id);
458         // Blocking a contact.
459         $return = core_message_external::block_contacts(array($user2->id));
460         $this->assertDebuggingCalled();
461         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
462         $this->assertEquals(array(), $return);
464         // Blocking a contact who is already a contact.
465         $return = core_message_external::block_contacts(array($user2->id));
466         $this->assertDebuggingCalled();
467         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
468         $this->assertEquals(array(), $return);
470         // Blocking multiple contacts.
471         $return = core_message_external::block_contacts(array($user3->id, $user4->id));
472         $this->assertDebuggingCalledCount(2);
473         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
474         $this->assertEquals(array(), $return);
476         // Blocking a non-existing user.
477         $return = core_message_external::block_contacts(array(99999));
478         $this->assertDebuggingCalled();
479         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
480         $this->assertCount(1, $return);
481         $return = array_pop($return);
482         $this->assertEquals($return['warningcode'], 'contactnotblocked');
483         $this->assertEquals($return['itemid'], 99999);
485         // Blocking contacts with valid and invalid parameters.
486         $return = core_message_external::block_contacts(array($user5->id, 99999));
487         $this->assertDebuggingCalledCount(2);
488         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
489         $this->assertCount(1, $return);
490         $return = array_pop($return);
491         $this->assertEquals($return['warningcode'], 'contactnotblocked');
492         $this->assertEquals($return['itemid'], 99999);
494         // Try to block a contact of another user contact list, should throw an exception.
495         // All assertions must be added before this point.
496         $this->expectException('required_capability_exception');
497         core_message_external::block_contacts(array($user2->id), $user3->id);
498     }
500     /**
501      * Test unblock_contacts.
502      */
503     public function test_unblock_contacts() {
504         $this->resetAfterTest(true);
506         $user1 = self::getDataGenerator()->create_user();
507         $user2 = self::getDataGenerator()->create_user();
508         $user3 = self::getDataGenerator()->create_user();
509         $user4 = self::getDataGenerator()->create_user();
510         $user5 = self::getDataGenerator()->create_user();
511         $user6 = self::getDataGenerator()->create_user();
512         $this->setUser($user1);
514         \core_message\api::add_contact($user1->id, $user3->id);
515         \core_message\api::add_contact($user1->id, $user4->id);
516         \core_message\api::add_contact($user1->id, $user5->id);
517         \core_message\api::add_contact($user1->id, $user6->id);
519         // Removing a non-contact.
520         $return = core_message_external::unblock_contacts(array($user2->id));
521         $this->assertDebuggingCalled();
522         $this->assertNull($return);
524         // Removing one contact.
525         $return = core_message_external::unblock_contacts(array($user3->id));
526         $this->assertDebuggingCalled();
527         $this->assertNull($return);
529         // Removing multiple contacts.
530         $return = core_message_external::unblock_contacts(array($user4->id, $user5->id));
531         $this->assertDebuggingCalledCount(2);
532         $this->assertNull($return);
534         // Removing contact from unexisting user.
535         $return = core_message_external::unblock_contacts(array(99999));
536         $this->assertDebuggingCalled();
537         $this->assertNull($return);
539         // Removing mixed valid and invalid data.
540         $return = core_message_external::unblock_contacts(array($user6->id, 99999));
541         $this->assertDebuggingCalledCount(2);
542         $this->assertNull($return);
544         // Try to unblock a contact of another user contact list, should throw an exception.
545         // All assertions must be added before this point.
546         $this->expectException('required_capability_exception');
547         core_message_external::unblock_contacts(array($user2->id), $user3->id);
548         $this->assertDebuggingCalled();
549     }
551     /**
552      * Test getting contact requests.
553      */
554     public function test_get_contact_requests() {
555         global $PAGE;
557         $this->resetAfterTest();
559         $user1 = self::getDataGenerator()->create_user();
560         $user2 = self::getDataGenerator()->create_user();
561         $user3 = self::getDataGenerator()->create_user();
563         $this->setUser($user1);
565         // Block one user, their request should not show up.
566         \core_message\api::block_user($user1->id, $user3->id);
568         \core_message\api::create_contact_request($user2->id, $user1->id);
569         \core_message\api::create_contact_request($user3->id, $user1->id);
571         $requests = core_message_external::get_contact_requests($user1->id);
572         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
574         $this->assertCount(1, $requests);
576         $request = reset($requests);
577         $userpicture = new \user_picture($user2);
578         $profileimageurl = $userpicture->get_url($PAGE)->out(false);
580         $this->assertEquals($user2->id, $request['id']);
581         $this->assertEquals(fullname($user2), $request['fullname']);
582         $this->assertArrayHasKey('profileimageurl', $request);
583         $this->assertArrayHasKey('profileimageurlsmall', $request);
584         $this->assertArrayHasKey('isonline', $request);
585         $this->assertArrayHasKey('showonlinestatus', $request);
586         $this->assertArrayHasKey('isblocked', $request);
587         $this->assertArrayHasKey('iscontact', $request);
588     }
590     /**
591      * Test the get_contact_requests() function when the user has blocked the sender of the request.
592      */
593     public function test_get_contact_requests_blocked_sender() {
594         $this->resetAfterTest();
595         $user1 = self::getDataGenerator()->create_user();
596         $user2 = self::getDataGenerator()->create_user();
598         // User1 blocks User2.
599         \core_message\api::block_user($user1->id, $user2->id);
601         // User2 tries to add User1 as a contact.
602         \core_message\api::create_contact_request($user2->id, $user1->id);
604         // Verify we don't see the contact request from the blocked user User2 in the requests for User1.
605         $this->setUser($user1);
606         $requests = core_message_external::get_contact_requests($user1->id);
607         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
609         $this->assertCount(0, $requests);
610     }
612     /**
613      * Test getting contact requests when there are none.
614      */
615     public function test_get_contact_requests_no_requests() {
616         $this->resetAfterTest();
618         $user1 = self::getDataGenerator()->create_user();
620         $this->setUser($user1);
622         $requests = core_message_external::get_contact_requests($user1->id);
623         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
625         $this->assertEmpty($requests);
626     }
628     /**
629      * Test getting contact requests with limits.
630      */
631     public function test_get_contact_requests_with_limits() {
632         $this->resetAfterTest();
634         $user1 = self::getDataGenerator()->create_user();
635         $user2 = self::getDataGenerator()->create_user();
636         $user3 = self::getDataGenerator()->create_user();
638         $this->setUser($user1);
640         \core_message\api::create_contact_request($user2->id, $user1->id);
641         \core_message\api::create_contact_request($user3->id, $user1->id);
643         $requests = core_message_external::get_contact_requests($user1->id, 0, 1);
644         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
646         $this->assertCount(1, $requests);
647     }
649     /**
650      * Test getting contact requests with messaging disabled.
651      */
652     public function test_get_contact_requests_messaging_disabled() {
653         global $CFG;
655         $this->resetAfterTest();
657         // Create some skeleton data just so we can call the WS.
658         $user1 = self::getDataGenerator()->create_user();
660         $this->setUser($user1);
662         // Disable messaging.
663         $CFG->messaging = 0;
665         // Ensure an exception is thrown.
666         $this->expectException('moodle_exception');
667         core_message_external::get_contact_requests($user1->id);
668     }
670     /**
671      * Test getting contact requests with no permission.
672      */
673     public function test_get_contact_requests_no_permission() {
674         $this->resetAfterTest();
676         // Create some skeleton data just so we can call the WS.
677         $user1 = self::getDataGenerator()->create_user();
678         $user2 = self::getDataGenerator()->create_user();
679         $user3 = self::getDataGenerator()->create_user();
681         $this->setUser($user3);
683         // Ensure an exception is thrown.
684         $this->expectException('required_capability_exception');
685         core_message_external::create_contact_request($user1->id, $user2->id);
686     }
688     /**
689      * Test getting the number of received contact requests.
690      */
691     public function test_get_received_contact_requests_count() {
692         $this->resetAfterTest();
694         $user1 = self::getDataGenerator()->create_user();
695         $user2 = self::getDataGenerator()->create_user();
696         $user3 = self::getDataGenerator()->create_user();
697         $user4 = self::getDataGenerator()->create_user();
699         $this->setUser($user1);
701         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
702         $contactrequestnumber = external_api::clean_returnvalue(
703             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
704         $this->assertEquals(0, $contactrequestnumber);
706         \core_message\api::create_contact_request($user2->id, $user1->id);
708         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
709         $contactrequestnumber = external_api::clean_returnvalue(
710             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
711         $this->assertEquals(1, $contactrequestnumber);
713         \core_message\api::create_contact_request($user3->id, $user1->id);
715         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
716         $contactrequestnumber = external_api::clean_returnvalue(
717             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
718         $this->assertEquals(2, $contactrequestnumber);
720         \core_message\api::create_contact_request($user1->id, $user4->id);
722         // Web service should ignore sent requests.
723         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
724         $contactrequestnumber = external_api::clean_returnvalue(
725             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
726         $this->assertEquals(2, $contactrequestnumber);
727     }
729     /**
730      * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request.
731      */
732     public function test_get_received_contact_requests_count_blocked_sender() {
733         $this->resetAfterTest();
734         $user1 = self::getDataGenerator()->create_user();
735         $user2 = self::getDataGenerator()->create_user();
737         // User1 blocks User2.
738         \core_message\api::block_user($user1->id, $user2->id);
740         // User2 tries to add User1 as a contact.
741         \core_message\api::create_contact_request($user2->id, $user1->id);
743         // Verify we don't see the contact request from the blocked user User2 in the count for User1.
744         $this->setUser($user1);
745         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
746         $contactrequestnumber = external_api::clean_returnvalue(
747             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
748         $this->assertEquals(0, $contactrequestnumber);
749     }
751     /**
752      * Test getting the number of received contact requests with no permissions.
753      */
754     public function test_get_received_contact_requests_count_no_permission() {
755         $this->resetAfterTest();
757         // Create some skeleton data just so we can call the WS.
758         $user1 = self::getDataGenerator()->create_user();
759         $user2 = self::getDataGenerator()->create_user();
761         $this->setUser($user2);
763         // Ensure an exception is thrown.
764         $this->expectException('required_capability_exception');
765         core_message_external::get_received_contact_requests_count($user1->id);
766     }
768     /**
769      * Test getting the number of received contact requests with messaging disabled.
770      */
771     public function test_get_received_contact_requests_count_messaging_disabled() {
772         global $CFG;
774         $this->resetAfterTest();
776         // Create some skeleton data just so we can call the WS.
777         $user1 = self::getDataGenerator()->create_user();
779         $this->setUser($user1);
781         // Disable messaging.
782         $CFG->messaging = 0;
784         // Ensure an exception is thrown.
785         $this->expectException('moodle_exception');
786         core_message_external::get_received_contact_requests_count($user1->id);
787     }
789     /**
790      * Test creating a contact request.
791      */
792     public function test_create_contact_request() {
793         global $CFG, $DB;
795         $this->resetAfterTest();
797         $user1 = self::getDataGenerator()->create_user();
798         $user2 = self::getDataGenerator()->create_user();
800         $this->setUser($user1);
802         // Allow users to message anyone site-wide.
803         $CFG->messagingallusers = 1;
805         $return = core_message_external::create_contact_request($user1->id, $user2->id);
806         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
807         $this->assertEquals([], $return['warnings']);
809         $request = $DB->get_records('message_contact_requests');
811         $this->assertCount(1, $request);
813         $request = reset($request);
815         $this->assertEquals($request->id, $return['request']['id']);
816         $this->assertEquals($request->userid, $return['request']['userid']);
817         $this->assertEquals($request->requesteduserid, $return['request']['requesteduserid']);
818         $this->assertEquals($request->timecreated, $return['request']['timecreated']);
819     }
821     /**
822      * Test creating a contact request when not allowed.
823      */
824     public function test_create_contact_request_not_allowed() {
825         global $CFG;
827         $this->resetAfterTest();
829         $user1 = self::getDataGenerator()->create_user();
830         $user2 = self::getDataGenerator()->create_user();
832         $this->setUser($user1);
834         $CFG->messagingallusers = 0;
836         $return = core_message_external::create_contact_request($user1->id, $user2->id);
837         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
839         $warning = reset($return['warnings']);
841         $this->assertEquals('user', $warning['item']);
842         $this->assertEquals($user2->id, $warning['itemid']);
843         $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']);
844         $this->assertEquals('You are unable to create a contact request for this user', $warning['message']);
845     }
847     /**
848      * Test creating a contact request with messaging disabled.
849      */
850     public function test_create_contact_request_messaging_disabled() {
851         global $CFG;
853         $this->resetAfterTest();
855         // Create some skeleton data just so we can call the WS.
856         $user1 = self::getDataGenerator()->create_user();
857         $user2 = self::getDataGenerator()->create_user();
859         $this->setUser($user1);
861         // Disable messaging.
862         $CFG->messaging = 0;
864         // Ensure an exception is thrown.
865         $this->expectException('moodle_exception');
866         core_message_external::create_contact_request($user1->id, $user2->id);
867     }
869     /**
870      * Test creating a contact request with no permission.
871      */
872     public function test_create_contact_request_no_permission() {
873         $this->resetAfterTest();
875         // Create some skeleton data just so we can call the WS.
876         $user1 = self::getDataGenerator()->create_user();
877         $user2 = self::getDataGenerator()->create_user();
878         $user3 = self::getDataGenerator()->create_user();
880         $this->setUser($user3);
882         // Ensure an exception is thrown.
883         $this->expectException('required_capability_exception');
884         core_message_external::create_contact_request($user1->id, $user2->id);
885     }
887     /**
888      * Test confirming a contact request.
889      */
890     public function test_confirm_contact_request() {
891         global $DB;
893         $this->resetAfterTest();
895         $user1 = self::getDataGenerator()->create_user();
896         $user2 = self::getDataGenerator()->create_user();
898         $this->setUser($user1);
900         \core_message\api::create_contact_request($user1->id, $user2->id);
902         $this->setUser($user2);
904         $return = core_message_external::confirm_contact_request($user1->id, $user2->id);
905         $return = external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return);
906         $this->assertEquals(array(), $return);
908         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
910         $contact = $DB->get_records('message_contacts');
912         $this->assertCount(1, $contact);
914         $contact = reset($contact);
916         $this->assertEquals($user1->id, $contact->userid);
917         $this->assertEquals($user2->id, $contact->contactid);
918     }
920     /**
921      * Test confirming a contact request with messaging disabled.
922      */
923     public function test_confirm_contact_request_messaging_disabled() {
924         global $CFG;
926         $this->resetAfterTest();
928         // Create some skeleton data just so we can call the WS.
929         $user1 = self::getDataGenerator()->create_user();
930         $user2 = self::getDataGenerator()->create_user();
932         $this->setUser($user1);
934         // Disable messaging.
935         $CFG->messaging = 0;
937         // Ensure an exception is thrown.
938         $this->expectException('moodle_exception');
939         core_message_external::confirm_contact_request($user1->id, $user2->id);
940     }
942     /**
943      * Test confirming a contact request with no permission.
944      */
945     public function test_confirm_contact_request_no_permission() {
946         $this->resetAfterTest();
948         // Create some skeleton data just so we can call the WS.
949         $user1 = self::getDataGenerator()->create_user();
950         $user2 = self::getDataGenerator()->create_user();
951         $user3 = self::getDataGenerator()->create_user();
953         $this->setUser($user3);
955         // Ensure an exception is thrown.
956         $this->expectException('required_capability_exception');
957         core_message_external::confirm_contact_request($user1->id, $user2->id);
958     }
960     /**
961      * Test declining a contact request.
962      */
963     public function test_decline_contact_request() {
964         global $DB;
966         $this->resetAfterTest();
968         $user1 = self::getDataGenerator()->create_user();
969         $user2 = self::getDataGenerator()->create_user();
971         $this->setUser($user1);
973         \core_message\api::create_contact_request($user1->id, $user2->id);
975         $this->setUser($user2);
977         $return = core_message_external::decline_contact_request($user1->id, $user2->id);
978         $return = external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return);
979         $this->assertEquals(array(), $return);
981         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
982         $this->assertEquals(0, $DB->count_records('message_contacts'));
983     }
985     /**
986      * Test declining a contact request with messaging disabled.
987      */
988     public function test_decline_contact_request_messaging_disabled() {
989         global $CFG;
991         $this->resetAfterTest();
993         // Create some skeleton data just so we can call the WS.
994         $user1 = self::getDataGenerator()->create_user();
995         $user2 = self::getDataGenerator()->create_user();
997         $this->setUser($user1);
999         // Disable messaging.
1000         $CFG->messaging = 0;
1002         // Ensure an exception is thrown.
1003         $this->expectException('moodle_exception');
1004         core_message_external::decline_contact_request($user1->id, $user2->id);
1005     }
1007     /**
1008      * Test declining a contact request with no permission.
1009      */
1010     public function test_decline_contact_request_no_permission() {
1011         $this->resetAfterTest();
1013         // Create some skeleton data just so we can call the WS.
1014         $user1 = self::getDataGenerator()->create_user();
1015         $user2 = self::getDataGenerator()->create_user();
1016         $user3 = self::getDataGenerator()->create_user();
1018         $this->setUser($user3);
1020         // Ensure an exception is thrown.
1021         $this->expectException('required_capability_exception');
1022         core_message_external::decline_contact_request($user1->id, $user2->id);
1023     }
1025     /**
1026      * Test muting conversations.
1027      */
1028     public function test_mute_conversations() {
1029         global $DB;
1031         $this->resetAfterTest(true);
1033         $user1 = self::getDataGenerator()->create_user();
1034         $user2 = self::getDataGenerator()->create_user();
1036         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1037             [$user1->id, $user2->id]);
1039         $this->setUser($user1);
1041         // Muting a conversation.
1042         $return = core_message_external::mute_conversations($user1->id, [$conversation->id]);
1043         $return = external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return);
1044         $this->assertEquals(array(), $return);
1046         // Get list of muted conversations.
1047         $mca = $DB->get_record('message_conversation_actions', []);
1049         $this->assertEquals($user1->id, $mca->userid);
1050         $this->assertEquals($conversation->id, $mca->conversationid);
1051         $this->assertEquals(\core_message\api::CONVERSATION_ACTION_MUTED, $mca->action);
1053         // Muting a conversation that is already muted.
1054         $return = core_message_external::mute_conversations($user1->id, [$conversation->id]);
1055         $return = external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return);
1056         $this->assertEquals(array(), $return);
1058         $this->assertEquals(1, $DB->count_records('message_conversation_actions'));
1059     }
1061     /**
1062      * Test muting a conversation with messaging disabled.
1063      */
1064     public function test_mute_conversations_messaging_disabled() {
1065         global $CFG;
1067         $this->resetAfterTest();
1069         // Create some skeleton data just so we can call the WS.
1070         $user1 = self::getDataGenerator()->create_user();
1071         $user2 = self::getDataGenerator()->create_user();
1073         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1074             [$user1->id, $user2->id]);
1076         $this->setUser($user1);
1078         // Disable messaging.
1079         $CFG->messaging = 0;
1081         // Ensure an exception is thrown.
1082         $this->expectException('moodle_exception');
1083         core_message_external::mute_conversations($user1->id, [$conversation->id]);
1084     }
1086     /**
1087      * Test muting a conversation with no permission.
1088      */
1089     public function test_mute_conversations_no_permission() {
1090         $this->resetAfterTest();
1092         // Create some skeleton data just so we can call the WS.
1093         $user1 = self::getDataGenerator()->create_user();
1094         $user2 = self::getDataGenerator()->create_user();
1095         $user3 = self::getDataGenerator()->create_user();
1097         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1098             [$user1->id, $user2->id]);
1100         $this->setUser($user3);
1102         // Ensure an exception is thrown.
1103         $this->expectException('required_capability_exception');
1104         core_message_external::mute_conversations($user1->id, [$conversation->id]);
1105     }
1107     /**
1108      * Test unmuting conversations.
1109      */
1110     public function test_unmute_conversations() {
1111         global $DB;
1113         $this->resetAfterTest(true);
1115         $user1 = self::getDataGenerator()->create_user();
1116         $user2 = self::getDataGenerator()->create_user();
1118         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1119             [$user1->id, $user2->id]);
1121         $this->setUser($user1);
1123         // Mute the conversation.
1124         \core_message\api::mute_conversation($user1->id, $conversation->id);
1126         // Unmuting a conversation.
1127         $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]);
1128         $return = external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return);
1129         $this->assertEquals(array(), $return);
1131         $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
1133         // Unmuting a conversation which is already unmuted.
1134         $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]);
1135         $return = external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return);
1136         $this->assertEquals(array(), $return);
1138         $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
1139     }
1141     /**
1142      * Test unmuting a conversation with messaging disabled.
1143      */
1144     public function test_unmute_conversation_messaging_disabled() {
1145         global $CFG;
1147         $this->resetAfterTest();
1149         // Create some skeleton data just so we can call the WS.
1150         $user1 = self::getDataGenerator()->create_user();
1151         $user2 = self::getDataGenerator()->create_user();
1153         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1154             [$user1->id, $user2->id]);
1156         $this->setUser($user1);
1158         // Disable messaging.
1159         $CFG->messaging = 0;
1161         // Ensure an exception is thrown.
1162         $this->expectException('moodle_exception');
1163         core_message_external::unmute_conversations($user1->id, [$user2->id]);
1164     }
1166     /**
1167      * Test unmuting a conversation with no permission.
1168      */
1169     public function test_unmute_conversation_no_permission() {
1170         $this->resetAfterTest();
1172         // Create some skeleton data just so we can call the WS.
1173         $user1 = self::getDataGenerator()->create_user();
1174         $user2 = self::getDataGenerator()->create_user();
1175         $user3 = self::getDataGenerator()->create_user();
1177         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1178             [$user1->id, $user2->id]);
1180         $this->setUser($user3);
1182         // Ensure an exception is thrown.
1183         $this->expectException('required_capability_exception');
1184         core_message_external::unmute_conversations($user1->id, [$conversation->id]);
1185     }
1187     /**
1188      * Test blocking a user.
1189      */
1190     public function test_block_user() {
1191         global $DB;
1193         $this->resetAfterTest(true);
1195         $user1 = self::getDataGenerator()->create_user();
1196         $user2 = self::getDataGenerator()->create_user();
1198         $this->setUser($user1);
1200         // Blocking a user.
1201         $return = core_message_external::block_user($user1->id, $user2->id);
1202         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1203         $this->assertEquals(array(), $return);
1205         // Get list of blocked users.
1206         $record = $DB->get_record('message_users_blocked', []);
1208         $this->assertEquals($user1->id, $record->userid);
1209         $this->assertEquals($user2->id, $record->blockeduserid);
1211         // Blocking a user who is already blocked.
1212         $return = core_message_external::block_user($user1->id, $user2->id);
1213         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1214         $this->assertEquals(array(), $return);
1216         $this->assertEquals(1, $DB->count_records('message_users_blocked'));
1217     }
1219     /**
1220      * Test blocking a user with messaging disabled.
1221      */
1222     public function test_block_user_messaging_disabled() {
1223         global $CFG;
1225         $this->resetAfterTest();
1227         // Create some skeleton data just so we can call the WS.
1228         $user1 = self::getDataGenerator()->create_user();
1229         $user2 = self::getDataGenerator()->create_user();
1231         $this->setUser($user1);
1233         // Disable messaging.
1234         $CFG->messaging = 0;
1236         // Ensure an exception is thrown.
1237         $this->expectException('moodle_exception');
1238         core_message_external::block_user($user1->id, $user2->id);
1239     }
1241     /**
1242      * Test blocking a user with no permission.
1243      */
1244     public function test_block_user_no_permission() {
1245         $this->resetAfterTest();
1247         // Create some skeleton data just so we can call the WS.
1248         $user1 = self::getDataGenerator()->create_user();
1249         $user2 = self::getDataGenerator()->create_user();
1250         $user3 = self::getDataGenerator()->create_user();
1252         $this->setUser($user3);
1254         // Ensure an exception is thrown.
1255         $this->expectException('required_capability_exception');
1256         core_message_external::block_user($user1->id, $user2->id);
1257     }
1259     /**
1260      * Test unblocking a user.
1261      */
1262     public function test_unblock_user() {
1263         global $DB;
1265         $this->resetAfterTest(true);
1267         $user1 = self::getDataGenerator()->create_user();
1268         $user2 = self::getDataGenerator()->create_user();
1270         $this->setUser($user1);
1272         // Block the user.
1273         \core_message\api::block_user($user1->id, $user2->id);
1275         // Unblocking a user.
1276         $return = core_message_external::unblock_user($user1->id, $user2->id);
1277         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1278         $this->assertEquals(array(), $return);
1280         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1282         // Unblocking a user who is already unblocked.
1283         $return = core_message_external::unblock_user($user1->id, $user2->id);
1284         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1285         $this->assertEquals(array(), $return);
1287         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1288     }
1290     /**
1291      * Test unblocking a user with messaging disabled.
1292      */
1293     public function test_unblock_user_messaging_disabled() {
1294         global $CFG;
1296         $this->resetAfterTest();
1298         // Create some skeleton data just so we can call the WS.
1299         $user1 = self::getDataGenerator()->create_user();
1300         $user2 = self::getDataGenerator()->create_user();
1302         $this->setUser($user1);
1304         // Disable messaging.
1305         $CFG->messaging = 0;
1307         // Ensure an exception is thrown.
1308         $this->expectException('moodle_exception');
1309         core_message_external::unblock_user($user1->id, $user2->id);
1310     }
1312     /**
1313      * Test unblocking a user with no permission.
1314      */
1315     public function test_unblock_user_no_permission() {
1316         $this->resetAfterTest();
1318         // Create some skeleton data just so we can call the WS.
1319         $user1 = self::getDataGenerator()->create_user();
1320         $user2 = self::getDataGenerator()->create_user();
1321         $user3 = self::getDataGenerator()->create_user();
1323         $this->setUser($user3);
1325         // Ensure an exception is thrown.
1326         $this->expectException('required_capability_exception');
1327         core_message_external::unblock_user($user1->id, $user2->id);
1328     }
1330     /**
1331      * Test get_contacts.
1332      */
1333     public function test_get_contacts() {
1334         $this->resetAfterTest(true);
1336         $user1 = self::getDataGenerator()->create_user();
1337         $user_stranger = self::getDataGenerator()->create_user();
1338         $user_offline1 = self::getDataGenerator()->create_user();
1339         $user_offline2 = self::getDataGenerator()->create_user();
1340         $user_offline3 = self::getDataGenerator()->create_user();
1341         $user_online = new stdClass();
1342         $user_online->lastaccess = time();
1343         $user_online = self::getDataGenerator()->create_user($user_online);
1344         $user_blocked = self::getDataGenerator()->create_user();
1345         $noreplyuser = core_user::get_user(core_user::NOREPLY_USER);
1347         // Login as user1.
1348         $this->setUser($user1);
1349         \core_message\api::add_contact($user1->id, $user_offline1->id);
1350         \core_message\api::add_contact($user1->id, $user_offline2->id);
1351         \core_message\api::add_contact($user1->id, $user_offline3->id);
1352         \core_message\api::add_contact($user1->id, $user_online->id);
1354         // User_stranger sends a couple of messages to user1.
1355         $this->send_message($user_stranger, $user1, 'Hello there!');
1356         $this->send_message($user_stranger, $user1, 'How you goin?');
1357         $this->send_message($user_stranger, $user1, 'Cya!');
1358         $this->send_message($noreplyuser, $user1, 'I am not a real user');
1360         // User_blocked sends a message to user1.
1361         $this->send_message($user_blocked, $user1, 'Here, have some spam.');
1363         // Retrieve the contacts of the user.
1364         $this->setUser($user1);
1365         $contacts = core_message_external::get_contacts();
1366         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1367         $this->assertCount(3, $contacts['offline']);
1368         $this->assertCount(1, $contacts['online']);
1369         $this->assertCount(3, $contacts['strangers']);
1370         core_message_external::block_contacts(array($user_blocked->id));
1371         $this->assertDebuggingCalled();
1372         $contacts = core_message_external::get_contacts();
1373         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1374         $this->assertCount(3, $contacts['offline']);
1375         $this->assertCount(1, $contacts['online']);
1376         $this->assertCount(2, $contacts['strangers']);
1378         // Checking some of the fields returned.
1379         $stranger = array_pop($contacts['strangers']);
1381         $this->assertEquals(core_user::NOREPLY_USER, $stranger['id']);
1382         $this->assertEquals(1, $stranger['unread']);
1384         // Check that deleted users are not returned.
1385         delete_user($user_offline1);
1386         delete_user($user_stranger);
1387         delete_user($user_online);
1388         $contacts = core_message_external::get_contacts();
1389         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1390         $this->assertCount(2, $contacts['offline']);
1391         $this->assertCount(0, $contacts['online']);
1392         $this->assertCount(1, $contacts['strangers']);
1393     }
1395     /**
1396      * Test search_contacts.
1397      * @expectedException moodle_exception
1398      */
1399     public function test_search_contacts() {
1400         global $DB;
1401         $this->resetAfterTest(true);
1403         $course1 = $this->getDataGenerator()->create_course();
1404         $course2 = $this->getDataGenerator()->create_course();
1406         $user1 = new stdClass();
1407         $user1->firstname = 'X';
1408         $user1->lastname = 'X';
1409         $user1 = $this->getDataGenerator()->create_user($user1);
1410         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1411         $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1413         $user2 = new stdClass();
1414         $user2->firstname = 'Eric';
1415         $user2->lastname = 'Cartman';
1416         $user2 = self::getDataGenerator()->create_user($user2);
1417         $user3 = new stdClass();
1418         $user3->firstname = 'Stan';
1419         $user3->lastname = 'Marsh';
1420         $user3 = self::getDataGenerator()->create_user($user3);
1421         self::getDataGenerator()->enrol_user($user3->id, $course1->id);
1422         $user4 = new stdClass();
1423         $user4->firstname = 'Kyle';
1424         $user4->lastname = 'Broflovski';
1425         $user4 = self::getDataGenerator()->create_user($user4);
1426         $user5 = new stdClass();
1427         $user5->firstname = 'Kenny';
1428         $user5->lastname = 'McCormick';
1429         $user5 = self::getDataGenerator()->create_user($user5);
1430         self::getDataGenerator()->enrol_user($user5->id, $course2->id);
1432         $this->setUser($user1);
1434         $results = core_message_external::search_contacts('r');
1435         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1436         $this->assertCount(5, $results); // Users 2 through 5 + admin
1438         $results = core_message_external::search_contacts('r', true);
1439         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1440         $this->assertCount(2, $results);
1442         $results = core_message_external::search_contacts('Kyle', false);
1443         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1444         $this->assertCount(1, $results);
1445         $result = reset($results);
1446         $this->assertEquals($user4->id, $result['id']);
1448         $results = core_message_external::search_contacts('y', false);
1449         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1450         $this->assertCount(2, $results);
1452         $results = core_message_external::search_contacts('y', true);
1453         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1454         $this->assertCount(1, $results);
1455         $result = reset($results);
1456         $this->assertEquals($user5->id, $result['id']);
1458         // Empty query, will throw an exception.
1459         $results = core_message_external::search_contacts('');
1460     }
1462     /**
1463      * Test get_messages.
1464      */
1465     public function test_get_messages() {
1466         global $CFG, $DB;
1467         $this->resetAfterTest(true);
1469         $this->preventResetByRollback();
1470         // This mark the messages as read!.
1471         $sink = $this->redirectMessages();
1473         $user1 = self::getDataGenerator()->create_user();
1474         $user2 = self::getDataGenerator()->create_user();
1475         $user3 = self::getDataGenerator()->create_user();
1477         $course = self::getDataGenerator()->create_course();
1479         // Send a message from one user to another.
1480         message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1481         message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE);
1482         message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1483         message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1484         message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE);
1486         $this->setUser($user1);
1487         // Get read conversations from user1 to user2.
1488         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1489         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1490         $this->assertCount(1, $messages['messages']);
1492         // Delete the message.
1493         $message = array_shift($messages['messages']);
1494         \core_message\api::delete_message($user1->id, $message['id']);
1496         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1497         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1498         $this->assertCount(0, $messages['messages']);
1500         // Get unread conversations from user1 to user2.
1501         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0);
1502         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1503         $this->assertCount(0, $messages['messages']);
1505         // Get read messages send from user1.
1506         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1507         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1508         $this->assertCount(1, $messages['messages']);
1510         $this->setUser($user2);
1511         // Get read conversations from any user to user2.
1512         $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0);
1513         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1514         $this->assertCount(2, $messages['messages']);
1516         // Conversations from user3 to user2.
1517         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1518         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1519         $this->assertCount(1, $messages['messages']);
1521         // Delete the message.
1522         $message = array_shift($messages['messages']);
1523         \core_message\api::delete_message($user2->id, $message['id']);
1525         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1526         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1527         $this->assertCount(0, $messages['messages']);
1529         $this->setUser($user3);
1530         // Get read notifications received by user3.
1531         $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0);
1532         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1533         $this->assertCount(0, $messages['messages']);
1535         // Now, create some notifications...
1536         // We are creating fake notifications but based on real ones.
1538         // This one comes from a disabled plugin's provider and therefore is not sent.
1539         $eventdata = new \core\message\message();
1540         $eventdata->courseid          = $course->id;
1541         $eventdata->notification      = 1;
1542         $eventdata->modulename        = 'moodle';
1543         $eventdata->component         = 'enrol_paypal';
1544         $eventdata->name              = 'paypal_enrolment';
1545         $eventdata->userfrom          = get_admin();
1546         $eventdata->userto            = $user1;
1547         $eventdata->subject           = "Moodle: PayPal payment";
1548         $eventdata->fullmessage       = "Your PayPal payment is pending.";
1549         $eventdata->fullmessageformat = FORMAT_PLAIN;
1550         $eventdata->fullmessagehtml   = '';
1551         $eventdata->smallmessage      = '';
1552         message_send($eventdata);
1553         $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '.
1554             'that is inactive or not allowed for the user id='.$user1->id);
1556         // This one omits notification = 1.
1557         $message = new \core\message\message();
1558         $message->courseid          = $course->id;
1559         $message->component         = 'enrol_manual';
1560         $message->name              = 'expiry_notification';
1561         $message->userfrom          = $user2;
1562         $message->userto            = $user1;
1563         $message->subject           = 'Test: This is not a notification but otherwise is valid';
1564         $message->fullmessage       = 'Test: Full message';
1565         $message->fullmessageformat = FORMAT_MARKDOWN;
1566         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1567         $message->smallmessage      = $message->subject;
1568         $message->contexturlname    = $course->fullname;
1569         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1570         message_send($message);
1572         $message = new \core\message\message();
1573         $message->courseid          = $course->id;
1574         $message->notification      = 1;
1575         $message->component         = 'enrol_manual';
1576         $message->name              = 'expiry_notification';
1577         $message->userfrom          = $user2;
1578         $message->userto            = $user1;
1579         $message->subject           = 'Enrolment expired';
1580         $message->fullmessage       = 'Enrolment expired blah blah blah';
1581         $message->fullmessageformat = FORMAT_MARKDOWN;
1582         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1583         $message->smallmessage      = $message->subject;
1584         $message->contexturlname    = $course->fullname;
1585         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1586         message_send($message);
1588         $userfrom = core_user::get_noreply_user();
1589         $userfrom->maildisplay = true;
1590         $eventdata = new \core\message\message();
1591         $eventdata->courseid          = $course->id;
1592         $eventdata->component         = 'moodle';
1593         $eventdata->name              = 'badgecreatornotice';
1594         $eventdata->userfrom          = $userfrom;
1595         $eventdata->userto            = $user1;
1596         $eventdata->notification      = 1;
1597         $eventdata->subject           = 'New badge';
1598         $eventdata->fullmessage       = format_text_email($eventdata->subject, FORMAT_HTML);
1599         $eventdata->fullmessageformat = FORMAT_PLAIN;
1600         $eventdata->fullmessagehtml   = $eventdata->subject;
1601         $eventdata->smallmessage      = $eventdata->subject;
1602         message_send($eventdata);
1604         $eventdata = new \core\message\message();
1605         $eventdata->courseid         = $course->id;
1606         $eventdata->name             = 'submission';
1607         $eventdata->component        = 'mod_feedback';
1608         $eventdata->userfrom         = $user1;
1609         $eventdata->userto           = $user2;
1610         $eventdata->subject          = 'Feedback submitted';
1611         $eventdata->fullmessage      = 'Feedback submitted from an user';
1612         $eventdata->fullmessageformat = FORMAT_PLAIN;
1613         $eventdata->fullmessagehtml  = '<strong>Feedback submitted</strong>';
1614         $eventdata->smallmessage     = '';
1615         $eventdata->customdata         = ['datakey' => 'data'];
1616         message_send($eventdata);
1618         $this->setUser($user1);
1619         // Get read notifications from any user to user1.
1620         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0);
1621         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1622         $this->assertCount(3, $messages['messages']);
1624         // Get one read notifications from any user to user1.
1625         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1);
1626         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1627         $this->assertCount(1, $messages['messages']);
1629         // Get unread notifications from any user to user1.
1630         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0);
1631         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1632         $this->assertCount(0, $messages['messages']);
1634         // Get read both type of messages from any user to user1.
1635         $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0);
1636         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1637         $this->assertCount(4, $messages['messages']);
1639         // Get read notifications from no-reply-user to user1.
1640         $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0);
1641         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1642         $this->assertCount(1, $messages['messages']);
1644         // Get notifications send by user1 to any user.
1645         $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0);
1646         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1647         $this->assertCount(1, $messages['messages']);
1648         // Check we receive custom data as a unserialisable json.
1649         $this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata']));
1650         $this->assertEquals('mod_feedback', $messages['messages'][0]['component']);
1651         $this->assertEquals('submission', $messages['messages'][0]['eventtype']);
1653         // Test warnings.
1654         $CFG->messaging = 0;
1656         $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0);
1657         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1658         $this->assertCount(1, $messages['warnings']);
1660         // Test exceptions.
1662         // Messaging disabled.
1663         try {
1664             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1665             $this->fail('Exception expected due messaging disabled.');
1666         } catch (moodle_exception $e) {
1667             $this->assertEquals('disabled', $e->errorcode);
1668         }
1670         $CFG->messaging = 1;
1672         // Invalid users.
1673         try {
1674             $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0);
1675             $this->fail('Exception expected due invalid users.');
1676         } catch (moodle_exception $e) {
1677             $this->assertEquals('accessdenied', $e->errorcode);
1678         }
1680         // Invalid user ids.
1681         try {
1682             $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0);
1683             $this->fail('Exception expected due invalid users.');
1684         } catch (moodle_exception $e) {
1685             $this->assertEquals('invaliduser', $e->errorcode);
1686         }
1688         // Invalid users (permissions).
1689         $this->setUser($user2);
1690         try {
1691             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1692             $this->fail('Exception expected due invalid user.');
1693         } catch (moodle_exception $e) {
1694             $this->assertEquals('accessdenied', $e->errorcode);
1695         }
1697     }
1699     /**
1700      * Test get_messages where we want all messages from a user, sent to any user.
1701      */
1702     public function test_get_messages_useridto_all() {
1703         $this->resetAfterTest(true);
1705         $user1 = self::getDataGenerator()->create_user();
1706         $user2 = self::getDataGenerator()->create_user();
1707         $user3 = self::getDataGenerator()->create_user();
1709         $this->setUser($user1);
1711         // Send a message from user 1 to two other users.
1712         $this->send_message($user1, $user2, 'some random text 1', 0, 1);
1713         $this->send_message($user1, $user3, 'some random text 2', 0, 2);
1715         // Get messages sent from user 1.
1716         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', false, false, 0, 0);
1717         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1719         // Confirm the data is correct.
1720         $messages = $messages['messages'];
1721         $this->assertCount(2, $messages);
1723         $message1 = array_shift($messages);
1724         $message2 = array_shift($messages);
1726         $this->assertEquals($user1->id, $message1['useridfrom']);
1727         $this->assertEquals($user2->id, $message1['useridto']);
1729         $this->assertEquals($user1->id, $message2['useridfrom']);
1730         $this->assertEquals($user3->id, $message2['useridto']);
1731     }
1733     /**
1734      * Test get_messages where we want all messages to a user, sent by any user.
1735      */
1736     public function test_get_messages_useridfrom_all() {
1737         $this->resetAfterTest();
1739         $user1 = self::getDataGenerator()->create_user();
1740         $user2 = self::getDataGenerator()->create_user();
1741         $user3 = self::getDataGenerator()->create_user();
1743         $this->setUser($user1);
1745         // Send a message to user 1 from two other users.
1746         $this->send_message($user2, $user1, 'some random text 1', 0, 1);
1747         $this->send_message($user3, $user1, 'some random text 2', 0, 2);
1749         // Get messages sent to user 1.
1750         $messages = core_message_external::get_messages($user1->id, 0, 'conversations', false, false, 0, 0);
1751         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1753         // Confirm the data is correct.
1754         $messages = $messages['messages'];
1755         $this->assertCount(2, $messages);
1757         $message1 = array_shift($messages);
1758         $message2 = array_shift($messages);
1760         $this->assertEquals($user2->id, $message1['useridfrom']);
1761         $this->assertEquals($user1->id, $message1['useridto']);
1763         $this->assertEquals($user3->id, $message2['useridfrom']);
1764         $this->assertEquals($user1->id, $message2['useridto']);
1765     }
1767     /**
1768      * Test get_blocked_users.
1769      */
1770     public function test_get_blocked_users() {
1771         $this->resetAfterTest(true);
1773         $user1 = self::getDataGenerator()->create_user();
1774         $userstranger = self::getDataGenerator()->create_user();
1775         $useroffline1 = self::getDataGenerator()->create_user();
1776         $useroffline2 = self::getDataGenerator()->create_user();
1777         $userblocked = self::getDataGenerator()->create_user();
1779         // Login as user1.
1780         $this->setUser($user1);
1782         \core_message\api::add_contact($user1->id, $useroffline1->id);
1783         \core_message\api::add_contact($user1->id, $useroffline2->id);
1785         // The userstranger sends a couple of messages to user1.
1786         $this->send_message($userstranger, $user1, 'Hello there!');
1787         $this->send_message($userstranger, $user1, 'How you goin?');
1789         // The userblocked sends a message to user1.
1790         // Note that this user is not blocked at this point.
1791         $this->send_message($userblocked, $user1, 'Here, have some spam.');
1793         // Retrieve the list of blocked users.
1794         $this->setUser($user1);
1795         $blockedusers = core_message_external::get_blocked_users($user1->id);
1796         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1797         $this->assertCount(0, $blockedusers['users']);
1799         // Block the $userblocked and retrieve again the list.
1800         core_message_external::block_contacts(array($userblocked->id));
1801         $this->assertDebuggingCalled();
1802         $blockedusers = core_message_external::get_blocked_users($user1->id);
1803         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1804         $this->assertCount(1, $blockedusers['users']);
1806         // Remove the $userblocked and check that the list now is empty.
1807         delete_user($userblocked);
1808         $blockedusers = core_message_external::get_blocked_users($user1->id);
1809         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1810         $this->assertCount(0, $blockedusers['users']);
1811     }
1813     /**
1814      * Test mark_message_read.
1815      */
1816     public function test_mark_message_read() {
1817         $this->resetAfterTest(true);
1819         $user1 = self::getDataGenerator()->create_user();
1820         $user2 = self::getDataGenerator()->create_user();
1821         $user3 = self::getDataGenerator()->create_user();
1823         // Login as user1.
1824         $this->setUser($user1);
1825         \core_message\api::add_contact($user1->id, $user2->id);
1826         \core_message\api::add_contact($user1->id, $user3->id);
1828         // The user2 sends a couple of messages to user1.
1829         $this->send_message($user2, $user1, 'Hello there!');
1830         $this->send_message($user2, $user1, 'How you goin?');
1831         $this->send_message($user3, $user1, 'How you goin?');
1832         $this->send_message($user3, $user2, 'How you goin?');
1834         // Retrieve all messages sent by user2 (they are currently unread).
1835         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1837         $messageids = array();
1838         foreach ($lastmessages as $m) {
1839             $messageid = core_message_external::mark_message_read($m->id, time());
1840             $messageids[] = external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid);
1841         }
1843         // Retrieve all messages sent (they are currently read).
1844         $lastmessages = message_get_messages($user1->id, $user2->id, 0, true);
1845         $this->assertCount(2, $lastmessages);
1846         $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages);
1847         $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages);
1849         // Retrieve all messages sent by any user (that are currently unread).
1850         $lastmessages = message_get_messages($user1->id, 0, 0, false);
1851         $this->assertCount(1, $lastmessages);
1853         // Invalid message ids.
1854         try {
1855             $messageid = core_message_external::mark_message_read(1337, time());
1856             $this->fail('Exception expected due invalid messageid.');
1857         } catch (dml_missing_record_exception $e) {
1858             $this->assertEquals('invalidrecordunknown', $e->errorcode);
1859         }
1861         // A message to a different user.
1862         $lastmessages = message_get_messages($user2->id, $user3->id, 0, false);
1863         $messageid = array_pop($lastmessages)->id;
1864         try {
1865             $messageid = core_message_external::mark_message_read($messageid, time());
1866             $this->fail('Exception expected due invalid messageid.');
1867         } catch (invalid_parameter_exception $e) {
1868             $this->assertEquals('invalidparameter', $e->errorcode);
1869         }
1870     }
1872     /**
1873      * Test mark_notification_read.
1874      */
1875     public function test_mark_notification_read() {
1876         $this->resetAfterTest(true);
1878         $user1 = self::getDataGenerator()->create_user();
1879         $user2 = self::getDataGenerator()->create_user();
1880         $user3 = self::getDataGenerator()->create_user();
1882         // Login as user1.
1883         $this->setUser($user1);
1884         \core_message\api::add_contact($user1->id, $user2->id);
1885         \core_message\api::add_contact($user1->id, $user3->id);
1887         // The user2 sends a couple of notifications to user1.
1888         $this->send_message($user2, $user1, 'Hello there!', 1);
1889         $this->send_message($user2, $user1, 'How you goin?', 1);
1890         $this->send_message($user3, $user1, 'How you goin?', 1);
1891         $this->send_message($user3, $user2, 'How you goin?', 1);
1893         // Retrieve all notifications sent by user2 (they are currently unread).
1894         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, false);
1896         $notificationids = array();
1897         foreach ($lastnotifications as $n) {
1898             $notificationid = core_message_external::mark_notification_read($n->id, time());
1899             $notificationids[] = external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(),
1900                 $notificationid);
1901         }
1903         // Retrieve all notifications sent (they are currently read).
1904         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, true);
1905         $this->assertCount(2, $lastnotifications);
1906         $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications);
1907         $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications);
1909         // Retrieve all notifications sent by any user (that are currently unread).
1910         $lastnotifications = message_get_messages($user1->id, 0, 1, false);
1911         $this->assertCount(1, $lastnotifications);
1913         // Invalid notification ids.
1914         try {
1915             $notificationid = core_message_external::mark_notification_read(1337, time());
1916             $this->fail('Exception expected due invalid notificationid.');
1917         } catch (dml_missing_record_exception $e) {
1918             $this->assertEquals('invalidrecord', $e->errorcode);
1919         }
1921         // A notification to a different user.
1922         $lastnotifications = message_get_messages($user2->id, $user3->id, 1, false);
1923         $notificationid = array_pop($lastnotifications)->id;
1924         try {
1925             $notificationid = core_message_external::mark_notification_read($notificationid, time());
1926             $this->fail('Exception expected due invalid notificationid.');
1927         } catch (invalid_parameter_exception $e) {
1928             $this->assertEquals('invalidparameter', $e->errorcode);
1929         }
1930     }
1932     /**
1933      * Test delete_message.
1934      */
1935     public function test_delete_message() {
1936         global $DB;
1937         $this->resetAfterTest(true);
1939         $user1 = self::getDataGenerator()->create_user();
1940         $user2 = self::getDataGenerator()->create_user();
1941         $user3 = self::getDataGenerator()->create_user();
1942         $user4 = self::getDataGenerator()->create_user();
1944         // Login as user1.
1945         $this->setUser($user1);
1946         \core_message\api::add_contact($user1->id, $user2->id);
1947         \core_message\api::add_contact($user1->id, $user3->id);
1949         // User user1 does not interchange messages with user3.
1950         $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1951         $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1952         $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1953         $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE);
1955         // Retrieve all messages sent by user2 (they are currently unread).
1956         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1958         // Delete a message not read, as a user from.
1959         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1960         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1961         $this->assertTrue($result['status']);
1962         $this->assertCount(0, $result['warnings']);
1963         $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id));
1964         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action);
1966         // Try to delete the same message again.
1967         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1968         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1969         $this->assertFalse($result['status']);
1971         // Try to delete a message that does not belong to me.
1972         try {
1973             $messageid = core_message_external::delete_message($m2to3, $user3->id, false);
1974             $this->fail('Exception expected due invalid messageid.');
1975         } catch (moodle_exception $e) {
1976             $this->assertEquals('You do not have permission to delete this message', $e->errorcode);
1977         }
1979         $this->setUser($user3);
1980         // Delete a message not read, as a user to.
1981         $result = core_message_external::delete_message($m2to3, $user3->id, false);
1982         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1983         $this->assertTrue($result['status']);
1984         $this->assertCount(0, $result['warnings']);
1985         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id,
1986             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1988         // Delete a message read.
1989         $message = $DB->get_record('messages', ['id' => $m3to2]);
1990         \core_message\api::mark_message_as_read($user3->id, $message, time());
1991         $result = core_message_external::delete_message($m3to2, $user3->id);
1992         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1993         $this->assertTrue($result['status']);
1994         $this->assertCount(0, $result['warnings']);
1995         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id,
1996             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1998         // Invalid message ids.
1999         try {
2000             $result = core_message_external::delete_message(-1, $user1->id);
2001             $this->fail('Exception expected due invalid messageid.');
2002         } catch (dml_missing_record_exception $e) {
2003             $this->assertEquals('invalidrecord', $e->errorcode);
2004         }
2006         // Invalid user.
2007         try {
2008             $result = core_message_external::delete_message($m1to2, -1, false);
2009             $this->fail('Exception expected due invalid user.');
2010         } catch (moodle_exception $e) {
2011             $this->assertEquals('invaliduser', $e->errorcode);
2012         }
2014         // Not active user.
2015         delete_user($user2);
2016         try {
2017             $result = core_message_external::delete_message($m1to2, $user2->id, false);
2018             $this->fail('Exception expected due invalid user.');
2019         } catch (moodle_exception $e) {
2020             $this->assertEquals('userdeleted', $e->errorcode);
2021         }
2023         // Now, as an admin, try to delete any message.
2024         $this->setAdminUser();
2025         $result = core_message_external::delete_message($m3to4, $user4->id, false);
2026         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
2027         $this->assertTrue($result['status']);
2028         $this->assertCount(0, $result['warnings']);
2029         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id,
2030             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
2032     }
2034     public function test_mark_all_notifications_as_read_invalid_user_exception() {
2035         $this->resetAfterTest(true);
2037         $this->expectException('moodle_exception');
2038         core_message_external::mark_all_notifications_as_read(-2132131, 0);
2039     }
2041     public function test_mark_all_notifications_as_read_access_denied_exception() {
2042         $this->resetAfterTest(true);
2044         $sender = $this->getDataGenerator()->create_user();
2045         $user = $this->getDataGenerator()->create_user();
2047         $this->setUser($user);
2048         $this->expectException('moodle_exception');
2049         core_message_external::mark_all_notifications_as_read($sender->id, 0);
2050     }
2052     public function test_mark_all_notifications_as_read_missing_from_user_exception() {
2053         $this->resetAfterTest(true);
2055         $sender = $this->getDataGenerator()->create_user();
2057         $this->setUser($sender);
2058         $this->expectException('moodle_exception');
2059         core_message_external::mark_all_notifications_as_read($sender->id, 99999);
2060     }
2062     public function test_mark_all_notifications_as_read() {
2063         global $DB;
2065         $this->resetAfterTest(true);
2067         $sender1 = $this->getDataGenerator()->create_user();
2068         $sender2 = $this->getDataGenerator()->create_user();
2069         $sender3 = $this->getDataGenerator()->create_user();
2070         $recipient = $this->getDataGenerator()->create_user();
2072         $this->setUser($recipient);
2074         $this->send_message($sender1, $recipient, 'Notification', 1);
2075         $this->send_message($sender1, $recipient, 'Notification', 1);
2076         $this->send_message($sender2, $recipient, 'Notification', 1);
2077         $this->send_message($sender2, $recipient, 'Notification', 1);
2078         $this->send_message($sender3, $recipient, 'Notification', 1);
2079         $this->send_message($sender3, $recipient, 'Notification', 1);
2081         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id);
2082         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
2083         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
2085         $this->assertCount(2, $readnotifications);
2086         $this->assertCount(4, $unreadnotifications);
2088         core_message_external::mark_all_notifications_as_read($recipient->id, 0);
2089         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
2090         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
2092         $this->assertCount(6, $readnotifications);
2093         $this->assertCount(0, $unreadnotifications);
2094     }
2096     /**
2097      * Test get_user_notification_preferences
2098      */
2099     public function test_get_user_notification_preferences() {
2100         $this->resetAfterTest(true);
2102         $user = self::getDataGenerator()->create_user();
2103         $this->setUser($user);
2105         // Set a couple of preferences to test.
2106         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
2107         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
2109         $prefs = core_message_external::get_user_notification_preferences();
2110         $prefs = external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs);
2111         // Check processors.
2112         $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors']));
2113         $this->assertEquals($user->id, $prefs['preferences']['userid']);
2115         // Check components.
2116         $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components']));
2118         // Check some preferences that we previously set.
2119         $found = 0;
2120         foreach ($prefs['preferences']['components'] as $component) {
2121             foreach ($component['notifications'] as $prefdata) {
2122                 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') {
2123                     continue;
2124                 }
2125                 foreach ($prefdata['processors'] as $processor) {
2126                     if ($processor['name'] == 'popup') {
2127                         $this->assertTrue($processor['loggedin']['checked']);
2128                         $found++;
2129                     } else if ($processor['name'] == 'email') {
2130                         $this->assertTrue($processor['loggedoff']['checked']);
2131                         $found++;
2132                     }
2133                 }
2134             }
2135         }
2136         $this->assertEquals(2, $found);
2137     }
2139     /**
2140      * Test get_user_notification_preferences permissions
2141      */
2142     public function test_get_user_notification_preferences_permissions() {
2143         $this->resetAfterTest(true);
2145         $user = self::getDataGenerator()->create_user();
2146         $otheruser = self::getDataGenerator()->create_user();
2147         $this->setUser($user);
2149         $this->expectException('moodle_exception');
2150         $prefs = core_message_external::get_user_notification_preferences($otheruser->id);
2151     }
2153     /**
2154      * Tests searching users in a course.
2155      */
2156     public function test_data_for_messagearea_search_users_in_course() {
2157         $this->resetAfterTest(true);
2159         // Create some users.
2160         $user1 = new stdClass();
2161         $user1->firstname = 'User';
2162         $user1->lastname = 'One';
2163         $user1 = self::getDataGenerator()->create_user($user1);
2165         // The person doing the search.
2166         $this->setUser($user1);
2168         // Set the second user's status to online by setting their last access to now.
2169         $user2 = new stdClass();
2170         $user2->firstname = 'User';
2171         $user2->lastname = 'Two';
2172         $user2->lastaccess = time();
2173         $user2 = self::getDataGenerator()->create_user($user2);
2175         // Block the second user.
2176         \core_message\api::block_user($user1->id, $user2->id);
2178         $user3 = new stdClass();
2179         $user3->firstname = 'User';
2180         $user3->lastname = 'Three';
2181         $user3 = self::getDataGenerator()->create_user($user3);
2183         // Create a course.
2184         $course1 = new stdClass();
2185         $course1->fullname = 'Course';
2186         $course1->shortname = 'One';
2187         $course1 = $this->getDataGenerator()->create_course();
2189         // Enrol the user we are doing the search for and one user in the course.
2190         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
2191         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
2193         // Perform a search.
2194         $result = core_message_external::data_for_messagearea_search_users_in_course($user1->id, $course1->id, 'User');
2196         // We need to execute the return values cleaning process to simulate the web service.
2197         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_in_course_returns(),
2198             $result);
2200         // Check that we only retrieved a user that was enrolled, and that the user performing the search was not returned.
2201         $users = $result['contacts'];
2202         $this->assertCount(1, $users);
2204         $user = $users[0];
2205         $this->assertEquals($user2->id, $user['userid']);
2206         $this->assertEquals(fullname($user2), $user['fullname']);
2207         $this->assertFalse($user['ismessaging']);
2208         $this->assertFalse($user['sentfromcurrentuser']);
2209         $this->assertNull($user['lastmessage']);
2210         $this->assertNull($user['messageid']);
2211         $this->assertNull($user['isonline']);
2212         $this->assertFalse($user['isread']);
2213         $this->assertTrue($user['isblocked']);
2214         $this->assertNull($user['unreadcount']);
2215     }
2217     /**
2218      * Tests searching users in course as another user.
2219      */
2220     public function test_data_for_messagearea_search_users_in_course_as_other_user() {
2221         $this->resetAfterTest(true);
2223         // The person doing the search for another user.
2224         $this->setAdminUser();
2226         // Create some users.
2227         $user1 = new stdClass();
2228         $user1->firstname = 'User';
2229         $user1->lastname = 'One';
2230         $user1 = self::getDataGenerator()->create_user($user1);
2232         $user2 = new stdClass();
2233         $user2->firstname = 'User';
2234         $user2->lastname = 'Two';
2235         $user2 = self::getDataGenerator()->create_user($user2);
2237         $user3 = new stdClass();
2238         $user3->firstname = 'User';
2239         $user3->lastname = 'Three';
2240         $user3 = self::getDataGenerator()->create_user($user3);
2242         // Create a course.
2243         $course1 = new stdClass();
2244         $course1->fullname = 'Course';
2245         $course1->shortname = 'One';
2246         $course1 = $this->getDataGenerator()->create_course();
2248         // Enrol the user we are doing the search for and one user in the course.
2249         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
2250         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
2252         // Perform a search.
2253         $result = core_message_external::data_for_messagearea_search_users_in_course($user1->id, $course1->id, 'User');
2255         // We need to execute the return values cleaning process to simulate the web service server.
2256         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_in_course_returns(),
2257             $result);
2259         // Check that we got the user enrolled, and that the user we are performing the search on behalf of was not returned.
2260         $users = $result['contacts'];
2261         $this->assertCount(1, $users);
2263         $user = $users[0];
2264         $this->assertEquals($user2->id, $user['userid']);
2265         $this->assertEquals(fullname($user2), $user['fullname']);
2266         $this->assertFalse($user['ismessaging']);
2267         $this->assertFalse($user['sentfromcurrentuser']);
2268         $this->assertNull($user['lastmessage']);
2269         $this->assertNull($user['messageid']);
2270         $this->assertFalse($user['isonline']);
2271         $this->assertFalse($user['isread']);
2272         $this->assertFalse($user['isblocked']);
2273         $this->assertNull($user['unreadcount']);
2274     }
2276     /**
2277      * Tests searching users in course as another user without the proper capabilities.
2278      */
2279     public function test_data_for_messagearea_search_users_in_course_as_other_user_without_cap() {
2280         $this->resetAfterTest(true);
2282         // Create some users.
2283         $user1 = self::getDataGenerator()->create_user();
2284         $user2 = self::getDataGenerator()->create_user();
2286         // The person doing the search for another user.
2287         $this->setUser($user1);
2289         // Create a course.
2290         $course = $this->getDataGenerator()->create_course();
2292         // Ensure an exception is thrown.
2293         $this->expectException('moodle_exception');
2294         core_message_external::data_for_messagearea_search_users_in_course($user2->id, $course->id, 'User');
2295         $this->assertDebuggingCalled();
2296     }
2298     /**
2299      * Tests searching users in course with messaging disabled.
2300      */
2301     public function test_data_for_messagearea_search_users_in_course_messaging_disabled() {
2302         global $CFG;
2304         $this->resetAfterTest(true);
2306         // Create some skeleton data just so we can call the WS..
2307         $user = self::getDataGenerator()->create_user();
2308         $course = $this->getDataGenerator()->create_course();
2310         // The person doing the search for another user.
2311         $this->setUser($user);
2313         // Disable messaging.
2314         $CFG->messaging = 0;
2316         // Ensure an exception is thrown.
2317         $this->expectException('moodle_exception');
2318         core_message_external::data_for_messagearea_search_users_in_course($user->id, $course->id, 'User');
2319         $this->assertDebuggingCalled();
2320     }
2322     /**
2323      * Tests searching users.
2324      */
2325     public function test_data_for_messagearea_search_users() {
2326         $this->resetAfterTest(true);
2328         // Create some users.
2329         $user1 = new stdClass();
2330         $user1->firstname = 'User';
2331         $user1->lastname = 'One';
2332         $user1 = self::getDataGenerator()->create_user($user1);
2334         // Set as the user performing the search.
2335         $this->setUser($user1);
2337         $user2 = new stdClass();
2338         $user2->firstname = 'User search';
2339         $user2->lastname = 'Two';
2340         $user2 = self::getDataGenerator()->create_user($user2);
2342         $user3 = new stdClass();
2343         $user3->firstname = 'User search';
2344         $user3->lastname = 'Three';
2345         $user3 = self::getDataGenerator()->create_user($user3);
2347         $user4 = new stdClass();
2348         $user4->firstname = 'User';
2349         $user4->lastname = 'Four';
2350         $user4 = self::getDataGenerator()->create_user($user4);
2352         $user5 = new stdClass();
2353         $user5->firstname = 'User search';
2354         $user5->lastname = 'Five';
2355         $user5 = self::getDataGenerator()->create_user($user5);
2357         $user6 = new stdClass();
2358         $user6->firstname = 'User';
2359         $user6->lastname = 'Six';
2360         $user6 = self::getDataGenerator()->create_user($user6);
2362         // Create some courses.
2363         $course1 = new stdClass();
2364         $course1->fullname = 'Course search';
2365         $course1->shortname = 'One';
2366         $course1 = $this->getDataGenerator()->create_course($course1);
2368         $course2 = new stdClass();
2369         $course2->fullname = 'Course';
2370         $course2->shortname = 'Two';
2371         $course2 = $this->getDataGenerator()->create_course($course2);
2373         $course3 = new stdClass();
2374         $course3->fullname = 'Course';
2375         $course3->shortname = 'Three search';
2376         $course3 = $this->getDataGenerator()->create_course($course3);
2378         $course4 = new stdClass();
2379         $course4->fullname = 'Course Four';
2380         $course4->shortname = 'CF100';
2381         $course4 = $this->getDataGenerator()->create_course($course4);
2383         $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
2384         $this->getDataGenerator()->enrol_user($user1->id, $course2->id, 'student');
2385         $this->getDataGenerator()->enrol_user($user1->id, $course3->id, 'student');
2387         // Add some users as contacts.
2388         \core_message\api::add_contact($user1->id, $user2->id);
2389         \core_message\api::add_contact($user1->id, $user3->id);
2390         \core_message\api::add_contact($user1->id, $user4->id);
2392         // Perform a search $CFG->messagingallusers setting enabled.
2393         set_config('messagingallusers', 1);
2394         $result = core_message_external::data_for_messagearea_search_users($user1->id, 'search');
2396         // We need to execute the return values cleaning process to simulate the web service server.
2397         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_returns(),
2398             $result);
2400         // Confirm that we returns contacts, courses and non-contacts.
2401         $contacts = $result['contacts'];
2402         $courses = $result['courses'];
2403         $noncontacts = $result['noncontacts'];
2405         // Check that we retrieved the correct contacts.
2406         $this->assertCount(2, $contacts);
2407         $this->assertEquals($user3->id, $contacts[0]['userid']);
2408         $this->assertEquals($user2->id, $contacts[1]['userid']);
2410         // Check that we retrieved the correct courses.
2411         $this->assertCount(2, $courses);
2412         $this->assertEquals($course3->id, $courses[0]['id']);
2413         $this->assertEquals($course1->id, $courses[1]['id']);
2415         // Check that we retrieved the correct non-contacts.
2416         $this->assertCount(1, $noncontacts);
2417         $this->assertEquals($user5->id, $noncontacts[0]['userid']);
2418     }
2420     /**
2421      * Tests searching users as another user.
2422      */
2423     public function test_data_for_messagearea_search_users_as_other_user() {
2424         $this->resetAfterTest(true);
2426         // The person doing the search.
2427         $this->setAdminUser();
2429         // Create some users.
2430         $user1 = new stdClass();
2431         $user1->firstname = 'User';
2432         $user1->lastname = 'One';
2433         $user1 = self::getDataGenerator()->create_user($user1);
2435         $user2 = new stdClass();
2436         $user2->firstname = 'User search';
2437         $user2->lastname = 'Two';
2438         $user2 = self::getDataGenerator()->create_user($user2);
2440         $user3 = new stdClass();
2441         $user3->firstname = 'User search';
2442         $user3->lastname = 'Three';
2443         $user3 = self::getDataGenerator()->create_user($user3);
2445         $user4 = new stdClass();
2446         $user4->firstname = 'User';
2447         $user4->lastname = 'Four';
2448         $user4 = self::getDataGenerator()->create_user($user4);
2450         $user5 = new stdClass();
2451         $user5->firstname = 'User search';
2452         $user5->lastname = 'Five';
2453         $user5 = self::getDataGenerator()->create_user($user5);
2455         $user6 = new stdClass();
2456         $user6->firstname = 'User';
2457         $user6->lastname = 'Six';
2458         $user6 = self::getDataGenerator()->create_user($user6);
2460         // Create some courses.
2461         $course1 = new stdClass();
2462         $course1->fullname = 'Course search';
2463         $course1->shortname = 'One';
2464         $course1 = $this->getDataGenerator()->create_course($course1);
2466         $course2 = new stdClass();
2467         $course2->fullname = 'Course';
2468         $course2->shortname = 'Two';
2469         $course2 = $this->getDataGenerator()->create_course($course2);
2471         $course3 = new stdClass();
2472         $course3->fullname = 'Course';
2473         $course3->shortname = 'Three search';
2474         $course3 = $this->getDataGenerator()->create_course($course3);
2476         // Add some users as contacts.
2477         \core_message\api::add_contact($user1->id, $user2->id);
2478         \core_message\api::add_contact($user1->id, $user3->id);
2479         \core_message\api::add_contact($user1->id, $user4->id);
2481         // Perform a search $CFG->messagingallusers setting enabled.
2482         set_config('messagingallusers', 1);
2483         $result = core_message_external::data_for_messagearea_search_users($user1->id, 'search');
2485         // We need to execute the return values cleaning process to simulate the web service server.
2486         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_returns(),
2487             $result);
2489         // Confirm that we returns contacts, courses and non-contacts.
2490         $contacts = $result['contacts'];
2491         $courses = $result['courses'];
2492         $noncontacts = $result['noncontacts'];
2494         // Check that we retrieved the correct contacts.
2495         $this->assertCount(2, $contacts);
2496         $this->assertEquals($user3->id, $contacts[0]['userid']);
2497         $this->assertEquals($user2->id, $contacts[1]['userid']);
2499         // Check that we retrieved the correct courses.
2500         $this->assertCount(0, $courses);
2502         // Check that we retrieved the correct non-contacts.
2503         $this->assertCount(1, $noncontacts);
2504         $this->assertEquals($user5->id, $noncontacts[0]['userid']);
2505     }
2507     /**
2508      * Tests searching users as another user without the proper capabilities.
2509      */
2510     public function test_data_for_messagearea_search_users_as_other_user_without_cap() {
2511         $this->resetAfterTest(true);
2513         // Create some users.
2514         $user1 = self::getDataGenerator()->create_user();
2515         $user2 = self::getDataGenerator()->create_user();
2517         // The person doing the search for another user.
2518         $this->setUser($user1);
2520         // Ensure an exception is thrown.
2521         $this->expectException('moodle_exception');
2522         core_message_external::data_for_messagearea_search_users($user2->id, 'User');
2523         $this->assertDebuggingCalled();
2524     }
2526     /**
2527      * Tests searching users with messaging disabled.
2528      */
2529     public function test_data_for_messagearea_search_users_messaging_disabled() {
2530         global $CFG;
2532         $this->resetAfterTest(true);
2534         // Create some skeleton data just so we can call the WS.
2535         $user = self::getDataGenerator()->create_user();
2537         // The person doing the search.
2538         $this->setUser($user);
2540         // Disable messaging.
2541         $CFG->messaging = 0;
2543         // Ensure an exception is thrown.
2544         $this->expectException('moodle_exception');
2545         core_message_external::data_for_messagearea_search_users($user->id, 'User');
2546         $this->assertDebuggingCalled();
2547     }
2549     /**
2550      * Tests searching for users when site-wide messaging is disabled.
2551      *
2552      * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
2553      * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
2554      * profile.
2555      */
2556     public function test_message_search_users_messagingallusers_disabled() {
2557         global $DB;
2558         $this->resetAfterTest();
2560         // Create some users.
2561         $users = [];
2562         foreach (range(1, 8) as $i) {
2563             $user = new stdClass();
2564             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2565             $user->lastname = $i;
2566             $user = $this->getDataGenerator()->create_user($user);
2567             $users[$i] = $user;
2568         }
2570         // Enrol a few users in the same course, but leave them as non-contacts.
2571         $course1 = $this->getDataGenerator()->create_course();
2572         $course2 = $this->getDataGenerator()->create_course();
2574         $this->setAdminUser();
2575         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2576         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2577         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2579         // Add some other users as contacts.
2580         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2581         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2582         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2584         // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
2585         $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher');
2586         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
2587         set_config('coursecontact', $teacherrole->id);
2589         // Create individual conversations between some users, one contact and one non-contact.
2590         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2591             [$users[1]->id, $users[2]->id]);
2592         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2593             [$users[6]->id, $users[1]->id]);
2595         // Create a group conversation between 4 users, including a contact and a non-contact.
2596         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2597             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
2599         // Set as the user performing the search.
2600         $this->setUser($users[1]);
2602         // Perform a search with $CFG->messagingallusers disabled.
2603         set_config('messagingallusers', 0);
2604         $result = core_message_external::message_search_users($users[1]->id, 'search');
2605         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2607         // Confirm that we returns contacts and non-contacts.
2608         $this->assertArrayHasKey('contacts', $result);
2609         $this->assertArrayHasKey('noncontacts', $result);
2610         $contacts = $result['contacts'];
2611         $noncontacts = $result['noncontacts'];
2613         // Check that we retrieved the correct contacts.
2614         $this->assertCount(2, $contacts);
2615         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2616         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2618         // Verify the correct conversations were returned for the contacts.
2619         $this->assertCount(2, $contacts[0]['conversations']);
2620         // We can't rely on the ordering of conversations within the results, so sort by id first.
2621         usort($contacts[0]['conversations'], function($a, $b) {
2622             return $a['id'] < $b['id'];
2623         });
2624         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2625         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2627         $this->assertCount(0, $contacts[1]['conversations']);
2629         // Check that we retrieved the correct non-contacts.
2630         // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles
2631         // are visible in that course. This excludes users like course contacts.
2632         $this->assertCount(2, $noncontacts);
2633         $this->assertEquals($users[6]->id, $noncontacts[0]['id']);
2634         $this->assertEquals($users[7]->id, $noncontacts[1]['id']);
2636         // Verify the correct conversations were returned for the non-contacts.
2637         $this->assertCount(1, $noncontacts[0]['conversations']);
2638         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[0]['conversations'][0]['type']);
2640         $this->assertCount(1, $noncontacts[1]['conversations']);
2641         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[1]['conversations'][0]['type']);
2642     }
2644     /**
2645      * Tests searching for users when site-wide messaging is enabled.
2646      *
2647      * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user
2648      * can view their respective profile.
2649      */
2650     public function test_message_search_users_messagingallusers_enabled() {
2651         global $DB;
2652         $this->resetAfterTest();
2654         // Create some users.
2655         $users = [];
2656         foreach (range(1, 9) as $i) {
2657             $user = new stdClass();
2658             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2659             $user->lastname = $i;
2660             $user = $this->getDataGenerator()->create_user($user);
2661             $users[$i] = $user;
2662         }
2664         // Enrol a few users in the same course, but leave them as non-contacts.
2665         $course1 = $this->getDataGenerator()->create_course();
2666         $course2 = $this->getDataGenerator()->create_course();
2668         $this->setAdminUser();
2669         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2670         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2671         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2673         // Add some other users as contacts.
2674         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2675         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2676         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2678         // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
2679         $this->getDataGenerator()->enrol_user($users[9]->id, $course2->id, 'editingteacher');
2680         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
2681         set_config('coursecontact', $teacherrole->id);
2683         // Create individual conversations between some users, one contact and one non-contact.
2684         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2685             [$users[1]->id, $users[2]->id]);
2686         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2687             [$users[6]->id, $users[1]->id]);
2689         // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
2690         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2691             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
2693         // Set as the user performing the search.
2694         $this->setUser($users[1]);
2696         // Perform a search with $CFG->messagingallusers enabled.
2697         set_config('messagingallusers', 1);
2698         $result = core_message_external::message_search_users($users[1]->id, 'search');
2699         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2701         // Confirm that we returns contacts and non-contacts.
2702         $this->assertArrayHasKey('contacts', $result);
2703         $this->assertArrayHasKey('noncontacts', $result);
2704         $contacts = $result['contacts'];
2705         $noncontacts = $result['noncontacts'];
2707         // Check that we retrieved the correct contacts.
2708         $this->assertCount(2, $contacts);
2709         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2710         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2712         // Verify the correct conversations were returned for the contacts.
2713         $this->assertCount(2, $contacts[0]['conversations']);
2714         // We can't rely on the ordering of conversations within the results, so sort by id first.
2715         usort($contacts[0]['conversations'], function($a, $b) {
2716             return $a['id'] < $b['id'];
2717         });
2718         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2719         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2721         $this->assertCount(0, $contacts[1]['conversations']);
2723         // Check that we retrieved the correct non-contacts.
2724         // If site wide messaging is enabled, we expect to be able to search for any users whose profiles we can view.
2725         // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1.
2726         $this->assertCount(3, $noncontacts);
2727         $this->assertEquals($users[6]->id, $noncontacts[0]['id']);
2728         $this->assertEquals($users[7]->id, $noncontacts[1]['id']);
2729         $this->assertEquals($users[9]->id, $noncontacts[2]['id']);
2731         // Verify the correct conversations were returned for the non-contacts.
2732         $this->assertCount(1, $noncontacts[0]['conversations']);
2733         $this->assertCount(1, $noncontacts[1]['conversations']);
2734         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[0]['conversations'][0]['type']);
2735         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[1]['conversations'][0]['type']);
2736         $this->assertCount(0, $noncontacts[2]['conversations']);
2737     }
2739     /**
2740      * Verify searching for users find themselves when they have self-conversations.
2741      */
2742     public function test_message_search_users_self_conversations() {
2743         $this->resetAfterTest();
2745         // Create some users.
2746         $user1 = new stdClass();
2747         $user1->firstname = 'User';
2748         $user1->lastname = 'One';
2749         $user1 = $this->getDataGenerator()->create_user($user1);
2750         $user2 = new stdClass();
2751         $user2->firstname = 'User';
2752         $user2->lastname = 'Two';
2753         $user2 = $this->getDataGenerator()->create_user($user2);
2755         // Create self-conversation for user1.
2756         $sc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2757         testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
2759         // Perform a search as user1.
2760         $this->setUser($user1);
2761         $result = core_message_external::message_search_users($user1->id, 'One');
2762         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2764         // Check results are empty.
2765         $this->assertCount(0, $result['contacts']);
2766         $this->assertCount(1, $result['noncontacts']);
2767     }
2769     /**
2770      * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
2771      */
2772     public function test_message_search_users_with_empty_result() {
2773         $this->resetAfterTest();
2775         // Create some users, but make sure neither will match the search term.
2776         $user1 = new stdClass();
2777         $user1->firstname = 'User';
2778         $user1->lastname = 'One';
2779         $user1 = $this->getDataGenerator()->create_user($user1);
2780         $user2 = new stdClass();
2781         $user2->firstname = 'User';
2782         $user2->lastname = 'Two';
2783         $user2 = $this->getDataGenerator()->create_user($user2);
2785         // Perform a search as user1.
2786         $this->setUser($user1);
2787         $result = core_message_external::message_search_users($user1->id, 'search');
2788         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2790         // Check results are empty.
2791         $this->assertCount(0, $result['contacts']);
2792         $this->assertCount(0, $result['noncontacts']);
2793     }
2795     /**
2796      * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
2797      */
2798     public function test_message_search_users_limit_offset() {
2799         $this->resetAfterTest();
2801         // Create 20 users.
2802         $users = [];
2803         foreach (range(1, 20) as $i) {
2804             $user = new stdClass();
2805             $user->firstname = "User search";
2806             $user->lastname = $i;
2807             $user = $this->getDataGenerator()->create_user($user);
2808             $users[$i] = $user;
2809         }
2811         // Enrol the first 9 users in the same course, but leave them as non-contacts.
2812         $this->setAdminUser();
2813         $course1 = $this->getDataGenerator()->create_course();
2814         foreach (range(1, 9) as $i) {
2815             $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
2816         }
2818         // Add 5 users, starting at the 11th user, as contacts for user1.
2819         foreach (range(11, 15) as $i) {
2820             \core_message\api::add_contact($users[1]->id, $users[$i]->id);
2821         }
2823         // Set as the user performing the search.
2824         $this->setUser($users[1]);
2826         // Search using a limit of 3.
2827         // This tests the case where we have more results than the limit for both contacts and non-contacts.
2828         $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3);
2829         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2830         $contacts = $result['contacts'];
2831         $noncontacts = $result['noncontacts'];
2833         // Check that we retrieved the correct contacts.
2834         $this->assertCount(3, $contacts);
2835         $this->assertEquals($users[11]->id, $contacts[0]['id']);
2836         $this->assertEquals($users[12]->id, $contacts[1]['id']);
2837         $this->assertEquals($users[13]->id, $contacts[2]['id']);
2839         // Check that we retrieved the correct non-contacts.
2840         $this->assertCount(3, $noncontacts);
2841         $this->assertEquals($users[2]->id, $noncontacts[0]['id']);
2842         $this->assertEquals($users[3]->id, $noncontacts[1]['id']);
2843         $this->assertEquals($users[4]->id, $noncontacts[2]['id']);
2845         // Now, offset to get the next batch of results.
2846         // We expect to see 2 contacts, and 3 non-contacts.
2847         $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3);
2848         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2849         $contacts = $result['contacts'];
2850         $noncontacts = $result['noncontacts'];
2851         $this->assertCount(2, $contacts);
2852         $this->assertEquals($users[14]->id, $contacts[0]['id']);
2853         $this->assertEquals($users[15]->id, $contacts[1]['id']);
2855         $this->assertCount(3, $noncontacts);
2856         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2857         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2858         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2860         // Now, offset to get the next batch of results.
2861         // We expect to see 0 contacts, and 2 non-contacts.
2862         $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3);
2863         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2864         $contacts = $result['contacts'];
2865         $noncontacts = $result['noncontacts'];
2866         $this->assertCount(0, $contacts);
2868         $this->assertCount(2, $noncontacts);
2869         $this->assertEquals($users[8]->id, $noncontacts[0]['id']);
2870         $this->assertEquals($users[9]->id, $noncontacts[1]['id']);
2871     }
2873     /**
2874      * Tests searching users as another user having the 'moodle/user:viewdetails' capability.
2875      */
2876     public function test_message_search_users_with_cap() {
2877         $this->resetAfterTest();
2878         global $DB;
2880         // Create some users.
2881         $users = [];
2882         foreach (range(1, 8) as $i) {
2883             $user = new stdClass();
2884             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2885             $user->lastname = $i;
2886             $user = $this->getDataGenerator()->create_user($user);
2887             $users[$i] = $user;
2888         }
2890         // Enrol a few users in the same course, but leave them as non-contacts.
2891         $course1 = $this->getDataGenerator()->create_course();
2892         $this->setAdminUser();
2893         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2894         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2895         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2897         // Add some other users as contacts.
2898         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2899         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2900         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2902         // Set as the user performing the search.
2903         $this->setUser($users[1]);
2905         // Grant the authenticated user role the capability 'user:viewdetails' at site context.
2906         $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
2907         assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
2909         // Perform a search with $CFG->messagingallusers disabled.
2910         set_config('messagingallusers', 0);
2911         $result = core_message_external::message_search_users($users[1]->id, 'search');
2912         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2913         $contacts = $result['contacts'];
2914         $noncontacts = $result['noncontacts'];
2916         // Check that we retrieved the correct contacts.
2917         $this->assertCount(2, $contacts);
2918         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2919         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2921         // Check that we retrieved the correct non-contacts.
2922         // Site-wide messaging is disabled, so we expect to be able to search for any users whose profile we can view.
2923         $this->assertCount(2, $noncontacts);
2924         $this->assertEquals($users[6]->id, $noncontacts[0]['id']);
2925         $this->assertEquals($users[7]->id, $noncontacts[1]['id']);
2926     }
2928     /**
2929      * Tests searching users as another user without the 'moodle/user:viewdetails' capability.
2930      */
2931     public function test_message_search_users_without_cap() {
2932         $this->resetAfterTest();
2934         // Create some users.
2935         $user1 = $this->getDataGenerator()->create_user();
2936         $user2 = $this->getDataGenerator()->create_user();
2938         // The person doing the search for another user.
2939         $this->setUser($user1);
2941         // Ensure an exception is thrown.
2942         $this->expectException('moodle_exception');
2943         core_message_external::message_search_users($user2->id, 'User');
2944         $this->assertDebuggingCalled();
2945     }
2947     /**
2948      * Tests searching users with messaging disabled.
2949      */
2950     public function test_message_search_users_messaging_disabled() {
2951         $this->resetAfterTest();
2953         // Create some skeleton data just so we can call the WS.
2954         $user = $this->getDataGenerator()->create_user();
2956         // The person doing the search.
2957         $this->setUser($user);
2959         // Disable messaging.
2960         set_config('messaging', 0);
2962         // Ensure an exception is thrown.
2963         $this->expectException('moodle_exception');
2964         core_message_external::message_search_users($user->id, 'User');
2965     }
2967     /**
2968      * Tests searching messages.
2969      */
2970     public function test_messagearea_search_messages() {
2971         $this->resetAfterTest(true);
2973         // Create some users.
2974         $user1 = self::getDataGenerator()->create_user();
2975         $user2 = self::getDataGenerator()->create_user();
2977         // The person doing the search.
2978         $this->setUser($user1);
2980         // Send some messages back and forth.
2981         $time = time();
2982         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2983         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2984         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2985         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2986         $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2988         // Perform a search.
2989         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2991         // We need to execute the return values cleaning process to simulate the web service server.
2992         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result);
2994         // Confirm the data is correct.
2995         $messages = $result['contacts'];
2996         $this->assertCount(2, $messages);
2998         $message1 = $messages[0];
2999         $message2 = $messages[1];
3001         $this->assertEquals($user2->id, $message1['userid']);
3002         $this->assertEquals(fullname($user2), $message1['fullname']);
3003         $this->assertTrue($message1['ismessaging']);
3004         $this->assertFalse($message1['sentfromcurrentuser']);
3005         $this->assertEquals('Word.', $message1['lastmessage']);
3006         $this->assertNotEmpty($message1['messageid']);
3007         $this->assertNull($message1['isonline']);
3008         $this->assertFalse($message1['isread']);
3009         $this->assertFalse($message1['isblocked']);
3010         $this->assertNull($message1['unreadcount']);
3011         $this->assertEquals($convid, $message1['conversationid']);
3013         $this->assertEquals($user2->id, $message2['userid']);
3014         $this->assertEquals(fullname($user2), $message2['fullname']);
3015         $this->assertTrue($message2['ismessaging']);
3016         $this->assertTrue($message2['sentfromcurrentuser']);
3017         $this->assertEquals('Yo!', $message2['lastmessage']);
3018         $this->assertNotEmpty($message2['messageid']);
3019         $this->assertNull($message2['isonline']);
3020         $this->assertTrue($message2['isread']);
3021         $this->assertFalse($message2['isblocked']);
3022         $this->assertNull($message2['unreadcount']);
3023         $this->assertEquals($convid, $message2['conversationid']);
3024     }
3026     /**
3027      * Tests searching messages as another user.
3028      */
3029     public function test_messagearea_search_messages_as_other_user() {
3030         $this->resetAfterTest(true);
3032         // The person doing the search.
3033         $this->setAdminUser();
3035         // Create some users.
3036         $user1 = self::getDataGenerator()->create_user();
3037         $user2 = self::getDataGenerator()->create_user();
3039         // Send some messages back and forth.
3040         $time = time();
3041         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3042         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3043         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3044         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3046         // Perform a search.
3047         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
3049         // We need to execute the return values cleaning process to simulate the web service server.
3050         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(),
3051             $result);
3053         // Confirm the data is correct.
3054         $messages = $result['contacts'];
3055         $this->assertCount(2, $messages);
3057         $message1 = $messages[0];
3058         $message2 = $messages[1];
3060         $this->assertEquals($user2->id, $message1['userid']);
3061         $this->assertEquals(fullname($user2), $message1['fullname']);
3062         $this->assertTrue($message1['ismessaging']);
3063         $this->assertFalse($message1['sentfromcurrentuser']);
3064         $this->assertEquals('Word.', $message1['lastmessage']);
3065         $this->assertNotEmpty($message1['messageid']);
3066         $this->assertFalse($message1['isonline']);
3067         $this->assertFalse($message1['isread']);
3068         $this->assertFalse($message1['isblocked']);
3069         $this->assertNull($message1['unreadcount']);
3071         $this->assertEquals($user2->id, $message2['userid']);
3072         $this->assertEquals(fullname($user2), $message2['fullname']);
3073         $this->assertTrue($message2['ismessaging']);
3074         $this->assertTrue($message2['sentfromcurrentuser']);
3075         $this->assertEquals('Yo!', $message2['lastmessage']);
3076         $this->assertNotEmpty($message2['messageid']);
3077         $this->assertFalse($message2['isonline']);
3078         $this->assertTrue($message2['isread']);
3079         $this->assertFalse($message2['isblocked']);
3080         $this->assertNull($message2['unreadcount']);
3081     }
3083     /**
3084      * Tests searching messages as another user without the proper capabilities.
3085      */
3086     public function test_messagearea_search_messages_as_other_user_without_cap() {
3087         $this->resetAfterTest(true);
3089         // Create some users.
3090         $user1 = self::getDataGenerator()->create_user();
3091         $user2 = self::getDataGenerator()->create_user();
3093         // The person doing the search for another user.
3094         $this->setUser($user1);
3096         // Ensure an exception is thrown.
3097         $this->expectException('moodle_exception');
3098         core_message_external::data_for_messagearea_search_messages($user2->id, 'Search');
3099     }
3101     /**
3102      * Tests searching messages with messaging disabled
3103      */
3104     public function test_messagearea_search_messages_messaging_disabled() {
3105         global $CFG;
3107         $this->resetAfterTest(true);
3109         // Create some skeleton data just so we can call the WS.
3110         $user = self::getDataGenerator()->create_user();
3112         // The person doing the search .
3113         $this->setUser($user);
3115         // Disable messaging.
3116         $CFG->messaging = 0;
3118         // Ensure an exception is thrown.
3119         $this->expectException('moodle_exception');
3120         core_message_external::data_for_messagearea_search_messages($user->id, 'Search');
3121     }
3123     /**
3124      * Tests retrieving conversations.
3125      */
3126     public function test_messagearea_conversations() {
3127         $this->resetAfterTest(true);
3129         // Create some users.
3130         $user1 = self::getDataGenerator()->create_user();
3131         $user2 = self::getDataGenerator()->create_user();
3132         $user3 = self::getDataGenerator()->create_user();
3133         $user4 = self::getDataGenerator()->create_user();
3135         // The person retrieving the conversations.
3136         $this->setUser($user1);
3138         // Send some messages back and forth, have some different conversations with different users.
3139         $time = time();
3140         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3141         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3142         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3143         $messageid1 = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3145         $this->send_message($user1, $user3, 'Booyah', 0, $time + 4);
3146         $this->send_message($user3, $user1, 'Whaaat?', 0, $time + 5);
3147         $this->send_message($user1, $user3, 'Nothing.', 0, $time + 6);
3148         $messageid2 = $this->send_message($user3, $user1, 'Cool.', 0, $time + 7);
3150         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 8);
3151         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 9);
3152         $messageid3 = $this->send_message($user1, $user4, 'Dope.', 0, $time + 10);
3154         // Retrieve the conversations.
3155         $result = core_message_external::data_for_messagearea_conversations($user1->id);
3157         // We need to execute the return values cleaning process to simulate the web service server.
3158         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_conversations_returns(),
3159             $result);
3161         // Confirm the data is correct.
3162         $messages = $result['contacts'];
3163         $this->assertCount(3, $messages);
3165         $message1 = $messages[0];
3166         $message2 = $messages[1];
3167         $message3 = $messages[2];
3169         $this->assertEquals($user4->id, $message1['userid']);
3170         $this->assertTrue($message1['ismessaging']);
3171         $this->assertTrue($message1['sentfromcurrentuser']);
3172         $this->assertEquals('Dope.', $message1['lastmessage']);
3173         $this->assertEquals($messageid3, $message1['messageid']);
3174         $this->assertNull($message1['isonline']);
3175         $this->assertFalse($message1['isread']);
3176         $this->assertFalse($message1['isblocked']);
3177         $this->assertEquals(1, $message1['unreadcount']);
3179         $this->assertEquals($user3->id, $message2['userid']);
3180         $this->assertTrue($message2['ismessaging']);
3181         $this->assertFalse($message2['sentfromcurrentuser']);
3182         $this->assertEquals('Cool.', $message2['lastmessage']);
3183         $this->assertEquals($messageid2, $message2['messageid']);
3184         $this->assertNull($message2['isonline']);
3185         $this->assertFalse($message2['isread']);
3186         $this->assertFalse($message2['isblocked']);
3187         $this->assertEquals(2, $message2['unreadcount']);
3189         $this->assertEquals($user2->id, $message3['userid']);
3190         $this->assertTrue($message3['ismessaging']);
3191         $this->assertFalse($message3['sentfromcurrentuser']);
3192         $this->assertEquals('Word.', $message3['lastmessage']);
3193         $this->assertEquals($messageid1, $message3['messageid']);
3194         $this->assertNull($message3['isonline']);
3195         $this->assertFalse($message3['isread']);
3196         $this->assertFalse($message3['isblocked']);
3197         $this->assertEquals(2, $message3['unreadcount']);
3198     }
3200     /**
3201      * Tests retrieving conversations as another user.
3202      */
3203     public function test_messagearea_conversations_as_other_user() {
3204         $this->resetAfterTest(true);
3206         // Set as admin.
3207         $this->setAdminUser();
3209         // Create some users.
3210         $user1 = self::getDataGenerator()->create_user();
3211         $user2 = self::getDataGenerator()->create_user();
3212         $user3 = self::getDataGenerator()->create_user();
3213         $user4 = self::getDataGenerator()->create_user();
3215         // Send some messages back and forth, have some different conversations with different users.
3216         $time = time();
3217         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3218         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3219         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3220         $messageid1 = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3222         $this->send_message($user1, $user3, 'Booyah', 0, $time + 4);
3223         $this->send_message($user3, $user1, 'Whaaat?', 0, $time + 5);
3224         $this->send_message($user1, $user3, 'Nothing.', 0, $time + 6);
3225         $messageid2 = $this->send_message($user3, $user1, 'Cool.', 0, $time + 7);
3227         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 8);
3228         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 9);
3229         $messageid3 = $this->send_message($user1, $user4, 'Dope.', 0, $time + 10);
3231         // Retrieve the conversations.
3232         $result = core_message_external::data_for_messagearea_conversations($user1->id);
3234         // We need to execute the return values cleaning process to simulate the web service server.
3235         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_conversations_returns(),
3236             $result);
3238         // Confirm the data is correct.
3239         $messages = $result['contacts'];
3240         $this->assertCount(3, $messages);
3242         $message1 = $messages[0];
3243         $message2 = $messages[1];
3244         $message3 = $messages[2];
3246         $this->assertEquals($user4->id, $message1['userid']);
3247         $this->assertTrue($message1['ismessaging']);
3248         $this->assertTrue($message1['sentfromcurrentuser']);
3249         $this->assertEquals('Dope.', $message1['lastmessage']);
3250         $this->assertEquals($messageid3, $message1['messageid']);
3251         $this->assertFalse($message1['isonline']);
3252         $this->assertFalse($message1['isread']);
3253         $this->assertFalse($message1['isblocked']);
3254         $this->assertEquals(1, $message1['unreadcount']);
3256         $this->assertEquals($user3->id, $message2['userid']);
3257         $this->assertTrue($message2['ismessaging']);
3258         $this->assertFalse($message2['sentfromcurrentuser']);
3259         $this->assertEquals('Cool.', $message2['lastmessage']);
3260         $this->assertEquals($messageid2, $message2['messageid']);
3261         $this->assertFalse($message2['isonline']);
3262         $this->assertFalse($message2['isread']);
3263         $this->assertFalse($message2['isblocked']);
3264         $this->assertEquals(2, $message2['unreadcount']);
3266         $this->assertEquals($user2->id, $message3['userid']);
3267         $this->assertTrue($message3['ismessaging']);
3268         $this->assertFalse($message3['sentfromcurrentuser']);
3269         $this->assertEquals('Word.', $message3['lastmessage']);
3270         $this->assertEquals($messageid1, $message3['messageid']);
3271         $this->assertFalse($message3['isonline']);
3272         $this->assertFalse($message3['isread']);
3273         $this->assertFalse($message3['isblocked']);
3274         $this->assertEquals(2, $message3['unreadcount']);
3275     }
3277     /**
3278      * Tests retrieving conversations as another user without the proper capabilities.
3279      */
3280     public function test_messagearea_conversations_as_other_user_without_cap() {
3281         $this->resetAfterTest(true);
3283         // Create some users.
3284         $user1 = self::getDataGenerator()->create_user();
3285         $user2 = self::getDataGenerator()->create_user();
3287         // The person retrieving the conversations for another user.
3288         $this->setUser($user1);
3290         // Ensure an exception is thrown.
3291         $this->expectException('moodle_exception');
3292         core_message_external::data_for_messagearea_conversations($user2->id);
3293     }
3295     /**
3296      * Tests retrieving conversations with messaging disabled.
3297      */
3298     public function test_messagearea_conversations_messaging_disabled() {
3299         global $CFG;
3301         $this->resetAfterTest(true);
3303         // Create some skeleton data just so we can call the WS.
3304         $user = self::getDataGenerator()->create_user();
3306         // The person retrieving the conversations.
3307         $this->setUser($user);
3309         // Disable messaging.
3310         $CFG->messaging = 0;
3312         // Ensure an exception is thrown.
3313         $this->expectException('moodle_exception');
3314         core_message_external::data_for_messagearea_conversations($user->id);
3315     }
3317     /**
3318      * Tests retrieving contacts.
3319      */
3320     public function test_messagearea_contacts() {
3321         $this->resetAfterTest(true);
3323         // Create some users.
3324         $user1 = self::getDataGenerator()->create_user();
3326         // Set as the user.
3327         $this->setUser($user1);
3329         $user2 = new stdClass();
3330         $user2->firstname = 'User';
3331         $user2->lastname = 'A';
3332         $user2 = self::getDataGenerator()->create_user($user2);
3334         $user3 = new stdClass();
3335         $user3->firstname = 'User';
3336         $user3->lastname = 'B';
3337         $user3 = self::getDataGenerator()->create_user($user3);
3339         $user4 = new stdClass();
3340         $user4->firstname = 'User';
3341         $user4->lastname = 'C';
3342         $user4 = self::getDataGenerator()->create_user($user4);
3344         $user5 = new stdClass();
3345         $user5->firstname = 'User';
3346         $user5->lastname = 'D';
3347         $user5 = self::getDataGenerator()->create_user($user5);
3349         // Add some users as contacts.
3350         \core_message\api::add_contact($user1->id, $user2->id);
3351         \core_message\api::add_contact($user1->id, $user3->id);
3352         \core_message\api::add_contact($user1->id, $user4->id);
3354         // Retrieve the contacts.
3355         $result = core_message_external::data_for_messagearea_contacts($user1->id);
3357         // We need to execute the return values cleaning process to simulate the web service server.
3358         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_contacts_returns(),
3359             $result);
3361         // Confirm the data is correct.
3362         $contacts = $result['contacts'];
3363         usort($contacts, ['static', 'sort_contacts']);
3364         $this->assertCount(3, $contacts);
3366         $contact1 = $contacts[0];
3367         $contact2 = $contacts[1];
3368         $contact3 = $contacts[2];
3370         $this->assertEquals($user2->id, $contact1['userid']);
3371         $this->assertFalse($contact1['ismessaging']);
3372         $this->assertFalse($contact1['sentfromcurrentuser']);
3373         $this->assertNull($contact1['lastmessage']);
3374         $this->assertNull($contact1['messageid']);
3375         $this->assertNull($contact1['isonline']);
3376         $this->assertFalse($contact1['isread']);
3377         $this->assertFalse($contact1['isblocked']);
3378         $this->assertNull($contact1['unreadcount']);
3380         $this->assertEquals($user3->id, $contact2['userid']);
3381         $this->assertFalse($contact2['ismessaging']);