Merge branch 'MDL-67460-master_profile_secure' of https://github.com/beenet-dev/moodle
[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(): void {
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 delete_contacts.
343      */
344     public function test_delete_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         $user6 = self::getDataGenerator()->create_user();
353         $this->setUser($user1);
355         \core_message\api::add_contact($user1->id, $user3->id);
356         \core_message\api::add_contact($user1->id, $user4->id);
357         \core_message\api::add_contact($user1->id, $user5->id);
358         \core_message\api::add_contact($user1->id, $user6->id);
360         // Removing a non-contact.
361         $return = core_message_external::delete_contacts(array($user2->id));
362         $this->assertNull($return);
364         // Removing one contact.
365         $return = core_message_external::delete_contacts(array($user3->id));
366         $this->assertNull($return);
368         // Removing multiple contacts.
369         $return = core_message_external::delete_contacts(array($user4->id, $user5->id));
370         $this->assertNull($return);
372         // Removing contact from unexisting user.
373         $return = core_message_external::delete_contacts(array(99999));
374         $this->assertNull($return);
376         // Removing mixed valid and invalid data.
377         $return = core_message_external::delete_contacts(array($user6->id, 99999));
378         $this->assertNull($return);
380         // Try to delete a contact of another user contact list, should throw an exception.
381         // All assertions must be added before this point.
382         $this->expectException('required_capability_exception');
383         core_message_external::delete_contacts(array($user2->id), $user3->id);
384     }
386     /**
387      * Test getting contact requests.
388      */
389     public function test_get_contact_requests() {
390         global $PAGE;
392         $this->resetAfterTest();
394         $user1 = self::getDataGenerator()->create_user();
395         $user2 = self::getDataGenerator()->create_user();
396         $user3 = self::getDataGenerator()->create_user();
398         $this->setUser($user1);
400         // Block one user, their request should not show up.
401         \core_message\api::block_user($user1->id, $user3->id);
403         \core_message\api::create_contact_request($user2->id, $user1->id);
404         \core_message\api::create_contact_request($user3->id, $user1->id);
406         $requests = core_message_external::get_contact_requests($user1->id);
407         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
409         $this->assertCount(1, $requests);
411         $request = reset($requests);
412         $userpicture = new \user_picture($user2);
413         $profileimageurl = $userpicture->get_url($PAGE)->out(false);
415         $this->assertEquals($user2->id, $request['id']);
416         $this->assertEquals(fullname($user2), $request['fullname']);
417         $this->assertArrayHasKey('profileimageurl', $request);
418         $this->assertArrayHasKey('profileimageurlsmall', $request);
419         $this->assertArrayHasKey('isonline', $request);
420         $this->assertArrayHasKey('showonlinestatus', $request);
421         $this->assertArrayHasKey('isblocked', $request);
422         $this->assertArrayHasKey('iscontact', $request);
423     }
425     /**
426      * Test the get_contact_requests() function when the user has blocked the sender of the request.
427      */
428     public function test_get_contact_requests_blocked_sender() {
429         $this->resetAfterTest();
430         $user1 = self::getDataGenerator()->create_user();
431         $user2 = self::getDataGenerator()->create_user();
433         // User1 blocks User2.
434         \core_message\api::block_user($user1->id, $user2->id);
436         // User2 tries to add User1 as a contact.
437         \core_message\api::create_contact_request($user2->id, $user1->id);
439         // Verify we don't see the contact request from the blocked user User2 in the requests for User1.
440         $this->setUser($user1);
441         $requests = core_message_external::get_contact_requests($user1->id);
442         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
444         $this->assertCount(0, $requests);
445     }
447     /**
448      * Test getting contact requests when there are none.
449      */
450     public function test_get_contact_requests_no_requests() {
451         $this->resetAfterTest();
453         $user1 = self::getDataGenerator()->create_user();
455         $this->setUser($user1);
457         $requests = core_message_external::get_contact_requests($user1->id);
458         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
460         $this->assertEmpty($requests);
461     }
463     /**
464      * Test getting contact requests with limits.
465      */
466     public function test_get_contact_requests_with_limits() {
467         $this->resetAfterTest();
469         $user1 = self::getDataGenerator()->create_user();
470         $user2 = self::getDataGenerator()->create_user();
471         $user3 = self::getDataGenerator()->create_user();
473         $this->setUser($user1);
475         \core_message\api::create_contact_request($user2->id, $user1->id);
476         \core_message\api::create_contact_request($user3->id, $user1->id);
478         $requests = core_message_external::get_contact_requests($user1->id, 0, 1);
479         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
481         $this->assertCount(1, $requests);
482     }
484     /**
485      * Test getting contact requests with messaging disabled.
486      */
487     public function test_get_contact_requests_messaging_disabled() {
488         global $CFG;
490         $this->resetAfterTest();
492         // Create some skeleton data just so we can call the WS.
493         $user1 = self::getDataGenerator()->create_user();
495         $this->setUser($user1);
497         // Disable messaging.
498         $CFG->messaging = 0;
500         // Ensure an exception is thrown.
501         $this->expectException('moodle_exception');
502         core_message_external::get_contact_requests($user1->id);
503     }
505     /**
506      * Test getting contact requests with no permission.
507      */
508     public function test_get_contact_requests_no_permission() {
509         $this->resetAfterTest();
511         // Create some skeleton data just so we can call the WS.
512         $user1 = self::getDataGenerator()->create_user();
513         $user2 = self::getDataGenerator()->create_user();
514         $user3 = self::getDataGenerator()->create_user();
516         $this->setUser($user3);
518         // Ensure an exception is thrown.
519         $this->expectException('required_capability_exception');
520         core_message_external::create_contact_request($user1->id, $user2->id);
521     }
523     /**
524      * Test getting the number of received contact requests.
525      */
526     public function test_get_received_contact_requests_count() {
527         $this->resetAfterTest();
529         $user1 = self::getDataGenerator()->create_user();
530         $user2 = self::getDataGenerator()->create_user();
531         $user3 = self::getDataGenerator()->create_user();
532         $user4 = self::getDataGenerator()->create_user();
534         $this->setUser($user1);
536         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
537         $contactrequestnumber = external_api::clean_returnvalue(
538             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
539         $this->assertEquals(0, $contactrequestnumber);
541         \core_message\api::create_contact_request($user2->id, $user1->id);
543         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
544         $contactrequestnumber = external_api::clean_returnvalue(
545             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
546         $this->assertEquals(1, $contactrequestnumber);
548         \core_message\api::create_contact_request($user3->id, $user1->id);
550         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
551         $contactrequestnumber = external_api::clean_returnvalue(
552             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
553         $this->assertEquals(2, $contactrequestnumber);
555         \core_message\api::create_contact_request($user1->id, $user4->id);
557         // Web service should ignore sent requests.
558         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
559         $contactrequestnumber = external_api::clean_returnvalue(
560             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
561         $this->assertEquals(2, $contactrequestnumber);
562     }
564     /**
565      * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request.
566      */
567     public function test_get_received_contact_requests_count_blocked_sender() {
568         $this->resetAfterTest();
569         $user1 = self::getDataGenerator()->create_user();
570         $user2 = self::getDataGenerator()->create_user();
572         // User1 blocks User2.
573         \core_message\api::block_user($user1->id, $user2->id);
575         // User2 tries to add User1 as a contact.
576         \core_message\api::create_contact_request($user2->id, $user1->id);
578         // Verify we don't see the contact request from the blocked user User2 in the count for User1.
579         $this->setUser($user1);
580         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
581         $contactrequestnumber = external_api::clean_returnvalue(
582             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
583         $this->assertEquals(0, $contactrequestnumber);
584     }
586     /**
587      * Test getting the number of received contact requests with no permissions.
588      */
589     public function test_get_received_contact_requests_count_no_permission() {
590         $this->resetAfterTest();
592         // Create some skeleton data just so we can call the WS.
593         $user1 = self::getDataGenerator()->create_user();
594         $user2 = self::getDataGenerator()->create_user();
596         $this->setUser($user2);
598         // Ensure an exception is thrown.
599         $this->expectException('required_capability_exception');
600         core_message_external::get_received_contact_requests_count($user1->id);
601     }
603     /**
604      * Test getting the number of received contact requests with messaging disabled.
605      */
606     public function test_get_received_contact_requests_count_messaging_disabled() {
607         global $CFG;
609         $this->resetAfterTest();
611         // Create some skeleton data just so we can call the WS.
612         $user1 = self::getDataGenerator()->create_user();
614         $this->setUser($user1);
616         // Disable messaging.
617         $CFG->messaging = 0;
619         // Ensure an exception is thrown.
620         $this->expectException('moodle_exception');
621         core_message_external::get_received_contact_requests_count($user1->id);
622     }
624     /**
625      * Test creating a contact request.
626      */
627     public function test_create_contact_request() {
628         global $CFG, $DB;
630         $this->resetAfterTest();
632         $user1 = self::getDataGenerator()->create_user();
633         $user2 = self::getDataGenerator()->create_user();
635         $this->setUser($user1);
637         // Allow users to message anyone site-wide.
638         $CFG->messagingallusers = 1;
640         $return = core_message_external::create_contact_request($user1->id, $user2->id);
641         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
642         $this->assertEquals([], $return['warnings']);
644         $request = $DB->get_records('message_contact_requests');
646         $this->assertCount(1, $request);
648         $request = reset($request);
650         $this->assertEquals($request->id, $return['request']['id']);
651         $this->assertEquals($request->userid, $return['request']['userid']);
652         $this->assertEquals($request->requesteduserid, $return['request']['requesteduserid']);
653         $this->assertEquals($request->timecreated, $return['request']['timecreated']);
654     }
656     /**
657      * Test creating a contact request when not allowed.
658      */
659     public function test_create_contact_request_not_allowed() {
660         global $CFG;
662         $this->resetAfterTest();
664         $user1 = self::getDataGenerator()->create_user();
665         $user2 = self::getDataGenerator()->create_user();
667         $this->setUser($user1);
669         $CFG->messagingallusers = 0;
671         $return = core_message_external::create_contact_request($user1->id, $user2->id);
672         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
674         $warning = reset($return['warnings']);
676         $this->assertEquals('user', $warning['item']);
677         $this->assertEquals($user2->id, $warning['itemid']);
678         $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']);
679         $this->assertEquals('You are unable to create a contact request for this user', $warning['message']);
680     }
682     /**
683      * Test creating a contact request with messaging disabled.
684      */
685     public function test_create_contact_request_messaging_disabled() {
686         global $CFG;
688         $this->resetAfterTest();
690         // Create some skeleton data just so we can call the WS.
691         $user1 = self::getDataGenerator()->create_user();
692         $user2 = self::getDataGenerator()->create_user();
694         $this->setUser($user1);
696         // Disable messaging.
697         $CFG->messaging = 0;
699         // Ensure an exception is thrown.
700         $this->expectException('moodle_exception');
701         core_message_external::create_contact_request($user1->id, $user2->id);
702     }
704     /**
705      * Test creating a contact request with no permission.
706      */
707     public function test_create_contact_request_no_permission() {
708         $this->resetAfterTest();
710         // Create some skeleton data just so we can call the WS.
711         $user1 = self::getDataGenerator()->create_user();
712         $user2 = self::getDataGenerator()->create_user();
713         $user3 = self::getDataGenerator()->create_user();
715         $this->setUser($user3);
717         // Ensure an exception is thrown.
718         $this->expectException('required_capability_exception');
719         core_message_external::create_contact_request($user1->id, $user2->id);
720     }
722     /**
723      * Test confirming a contact request.
724      */
725     public function test_confirm_contact_request() {
726         global $DB;
728         $this->resetAfterTest();
730         $user1 = self::getDataGenerator()->create_user();
731         $user2 = self::getDataGenerator()->create_user();
733         $this->setUser($user1);
735         \core_message\api::create_contact_request($user1->id, $user2->id);
737         $this->setUser($user2);
739         $return = core_message_external::confirm_contact_request($user1->id, $user2->id);
740         $return = external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return);
741         $this->assertEquals(array(), $return);
743         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
745         $contact = $DB->get_records('message_contacts');
747         $this->assertCount(1, $contact);
749         $contact = reset($contact);
751         $this->assertEquals($user1->id, $contact->userid);
752         $this->assertEquals($user2->id, $contact->contactid);
753     }
755     /**
756      * Test confirming a contact request with messaging disabled.
757      */
758     public function test_confirm_contact_request_messaging_disabled() {
759         global $CFG;
761         $this->resetAfterTest();
763         // Create some skeleton data just so we can call the WS.
764         $user1 = self::getDataGenerator()->create_user();
765         $user2 = self::getDataGenerator()->create_user();
767         $this->setUser($user1);
769         // Disable messaging.
770         $CFG->messaging = 0;
772         // Ensure an exception is thrown.
773         $this->expectException('moodle_exception');
774         core_message_external::confirm_contact_request($user1->id, $user2->id);
775     }
777     /**
778      * Test confirming a contact request with no permission.
779      */
780     public function test_confirm_contact_request_no_permission() {
781         $this->resetAfterTest();
783         // Create some skeleton data just so we can call the WS.
784         $user1 = self::getDataGenerator()->create_user();
785         $user2 = self::getDataGenerator()->create_user();
786         $user3 = self::getDataGenerator()->create_user();
788         $this->setUser($user3);
790         // Ensure an exception is thrown.
791         $this->expectException('required_capability_exception');
792         core_message_external::confirm_contact_request($user1->id, $user2->id);
793     }
795     /**
796      * Test declining a contact request.
797      */
798     public function test_decline_contact_request() {
799         global $DB;
801         $this->resetAfterTest();
803         $user1 = self::getDataGenerator()->create_user();
804         $user2 = self::getDataGenerator()->create_user();
806         $this->setUser($user1);
808         \core_message\api::create_contact_request($user1->id, $user2->id);
810         $this->setUser($user2);
812         $return = core_message_external::decline_contact_request($user1->id, $user2->id);
813         $return = external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return);
814         $this->assertEquals(array(), $return);
816         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
817         $this->assertEquals(0, $DB->count_records('message_contacts'));
818     }
820     /**
821      * Test declining a contact request with messaging disabled.
822      */
823     public function test_decline_contact_request_messaging_disabled() {
824         global $CFG;
826         $this->resetAfterTest();
828         // Create some skeleton data just so we can call the WS.
829         $user1 = self::getDataGenerator()->create_user();
830         $user2 = self::getDataGenerator()->create_user();
832         $this->setUser($user1);
834         // Disable messaging.
835         $CFG->messaging = 0;
837         // Ensure an exception is thrown.
838         $this->expectException('moodle_exception');
839         core_message_external::decline_contact_request($user1->id, $user2->id);
840     }
842     /**
843      * Test declining a contact request with no permission.
844      */
845     public function test_decline_contact_request_no_permission() {
846         $this->resetAfterTest();
848         // Create some skeleton data just so we can call the WS.
849         $user1 = self::getDataGenerator()->create_user();
850         $user2 = self::getDataGenerator()->create_user();
851         $user3 = self::getDataGenerator()->create_user();
853         $this->setUser($user3);
855         // Ensure an exception is thrown.
856         $this->expectException('required_capability_exception');
857         core_message_external::decline_contact_request($user1->id, $user2->id);
858     }
860     /**
861      * Test muting conversations.
862      */
863     public function test_mute_conversations() {
864         global $DB;
866         $this->resetAfterTest(true);
868         $user1 = self::getDataGenerator()->create_user();
869         $user2 = self::getDataGenerator()->create_user();
871         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
872             [$user1->id, $user2->id]);
874         $this->setUser($user1);
876         // Muting a conversation.
877         $return = core_message_external::mute_conversations($user1->id, [$conversation->id]);
878         $return = external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return);
879         $this->assertEquals(array(), $return);
881         // Get list of muted conversations.
882         $mca = $DB->get_record('message_conversation_actions', []);
884         $this->assertEquals($user1->id, $mca->userid);
885         $this->assertEquals($conversation->id, $mca->conversationid);
886         $this->assertEquals(\core_message\api::CONVERSATION_ACTION_MUTED, $mca->action);
888         // Muting a conversation that is already muted.
889         $return = core_message_external::mute_conversations($user1->id, [$conversation->id]);
890         $return = external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return);
891         $this->assertEquals(array(), $return);
893         $this->assertEquals(1, $DB->count_records('message_conversation_actions'));
894     }
896     /**
897      * Test muting a conversation with messaging disabled.
898      */
899     public function test_mute_conversations_messaging_disabled() {
900         global $CFG;
902         $this->resetAfterTest();
904         // Create some skeleton data just so we can call the WS.
905         $user1 = self::getDataGenerator()->create_user();
906         $user2 = self::getDataGenerator()->create_user();
908         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
909             [$user1->id, $user2->id]);
911         $this->setUser($user1);
913         // Disable messaging.
914         $CFG->messaging = 0;
916         // Ensure an exception is thrown.
917         $this->expectException('moodle_exception');
918         core_message_external::mute_conversations($user1->id, [$conversation->id]);
919     }
921     /**
922      * Test muting a conversation with no permission.
923      */
924     public function test_mute_conversations_no_permission() {
925         $this->resetAfterTest();
927         // Create some skeleton data just so we can call the WS.
928         $user1 = self::getDataGenerator()->create_user();
929         $user2 = self::getDataGenerator()->create_user();
930         $user3 = self::getDataGenerator()->create_user();
932         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
933             [$user1->id, $user2->id]);
935         $this->setUser($user3);
937         // Ensure an exception is thrown.
938         $this->expectException('required_capability_exception');
939         core_message_external::mute_conversations($user1->id, [$conversation->id]);
940     }
942     /**
943      * Test unmuting conversations.
944      */
945     public function test_unmute_conversations() {
946         global $DB;
948         $this->resetAfterTest(true);
950         $user1 = self::getDataGenerator()->create_user();
951         $user2 = self::getDataGenerator()->create_user();
953         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
954             [$user1->id, $user2->id]);
956         $this->setUser($user1);
958         // Mute the conversation.
959         \core_message\api::mute_conversation($user1->id, $conversation->id);
961         // Unmuting a conversation.
962         $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]);
963         $return = external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return);
964         $this->assertEquals(array(), $return);
966         $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
968         // Unmuting a conversation which is already unmuted.
969         $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]);
970         $return = external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return);
971         $this->assertEquals(array(), $return);
973         $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
974     }
976     /**
977      * Test unmuting a conversation with messaging disabled.
978      */
979     public function test_unmute_conversation_messaging_disabled() {
980         global $CFG;
982         $this->resetAfterTest();
984         // Create some skeleton data just so we can call the WS.
985         $user1 = self::getDataGenerator()->create_user();
986         $user2 = self::getDataGenerator()->create_user();
988         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
989             [$user1->id, $user2->id]);
991         $this->setUser($user1);
993         // Disable messaging.
994         $CFG->messaging = 0;
996         // Ensure an exception is thrown.
997         $this->expectException('moodle_exception');
998         core_message_external::unmute_conversations($user1->id, [$user2->id]);
999     }
1001     /**
1002      * Test unmuting a conversation with no permission.
1003      */
1004     public function test_unmute_conversation_no_permission() {
1005         $this->resetAfterTest();
1007         // Create some skeleton data just so we can call the WS.
1008         $user1 = self::getDataGenerator()->create_user();
1009         $user2 = self::getDataGenerator()->create_user();
1010         $user3 = self::getDataGenerator()->create_user();
1012         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1013             [$user1->id, $user2->id]);
1015         $this->setUser($user3);
1017         // Ensure an exception is thrown.
1018         $this->expectException('required_capability_exception');
1019         core_message_external::unmute_conversations($user1->id, [$conversation->id]);
1020     }
1022     /**
1023      * Test blocking a user.
1024      */
1025     public function test_block_user() {
1026         global $DB;
1028         $this->resetAfterTest(true);
1030         $user1 = self::getDataGenerator()->create_user();
1031         $user2 = self::getDataGenerator()->create_user();
1033         $this->setUser($user1);
1035         // Blocking a user.
1036         $return = core_message_external::block_user($user1->id, $user2->id);
1037         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1038         $this->assertEquals(array(), $return);
1040         // Get list of blocked users.
1041         $record = $DB->get_record('message_users_blocked', []);
1043         $this->assertEquals($user1->id, $record->userid);
1044         $this->assertEquals($user2->id, $record->blockeduserid);
1046         // Blocking a user who is already blocked.
1047         $return = core_message_external::block_user($user1->id, $user2->id);
1048         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1049         $this->assertEquals(array(), $return);
1051         $this->assertEquals(1, $DB->count_records('message_users_blocked'));
1052     }
1054     /**
1055      * Test blocking a user.
1056      */
1057     public function test_block_user_when_ineffective() {
1058         global $DB;
1060         $this->resetAfterTest(true);
1062         $user1 = self::getDataGenerator()->create_user();
1063         $user2 = self::getDataGenerator()->create_user();
1065         $this->setUser($user1);
1067         $authenticateduser = $DB->get_record('role', array('shortname' => 'user'));
1068         assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, context_system::instance(), true);
1070         // Blocking a user.
1071         $return = core_message_external::block_user($user1->id, $user2->id);
1072         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1073         $this->assertEquals(array(), $return);
1075         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1076     }
1078     /**
1079      * Test blocking a user with messaging disabled.
1080      */
1081     public function test_block_user_messaging_disabled() {
1082         global $CFG;
1084         $this->resetAfterTest();
1086         // Create some skeleton data just so we can call the WS.
1087         $user1 = self::getDataGenerator()->create_user();
1088         $user2 = self::getDataGenerator()->create_user();
1090         $this->setUser($user1);
1092         // Disable messaging.
1093         $CFG->messaging = 0;
1095         // Ensure an exception is thrown.
1096         $this->expectException('moodle_exception');
1097         core_message_external::block_user($user1->id, $user2->id);
1098     }
1100     /**
1101      * Test blocking a user with no permission.
1102      */
1103     public function test_block_user_no_permission() {
1104         $this->resetAfterTest();
1106         // Create some skeleton data just so we can call the WS.
1107         $user1 = self::getDataGenerator()->create_user();
1108         $user2 = self::getDataGenerator()->create_user();
1109         $user3 = self::getDataGenerator()->create_user();
1111         $this->setUser($user3);
1113         // Ensure an exception is thrown.
1114         $this->expectException('required_capability_exception');
1115         core_message_external::block_user($user1->id, $user2->id);
1116     }
1118     /**
1119      * Test unblocking a user.
1120      */
1121     public function test_unblock_user() {
1122         global $DB;
1124         $this->resetAfterTest(true);
1126         $user1 = self::getDataGenerator()->create_user();
1127         $user2 = self::getDataGenerator()->create_user();
1129         $this->setUser($user1);
1131         // Block the user.
1132         \core_message\api::block_user($user1->id, $user2->id);
1134         // Unblocking a user.
1135         $return = core_message_external::unblock_user($user1->id, $user2->id);
1136         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1137         $this->assertEquals(array(), $return);
1139         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1141         // Unblocking a user who is already unblocked.
1142         $return = core_message_external::unblock_user($user1->id, $user2->id);
1143         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1144         $this->assertEquals(array(), $return);
1146         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1147     }
1149     /**
1150      * Test unblocking a user with messaging disabled.
1151      */
1152     public function test_unblock_user_messaging_disabled() {
1153         global $CFG;
1155         $this->resetAfterTest();
1157         // Create some skeleton data just so we can call the WS.
1158         $user1 = self::getDataGenerator()->create_user();
1159         $user2 = self::getDataGenerator()->create_user();
1161         $this->setUser($user1);
1163         // Disable messaging.
1164         $CFG->messaging = 0;
1166         // Ensure an exception is thrown.
1167         $this->expectException('moodle_exception');
1168         core_message_external::unblock_user($user1->id, $user2->id);
1169     }
1171     /**
1172      * Test unblocking a user with no permission.
1173      */
1174     public function test_unblock_user_no_permission() {
1175         $this->resetAfterTest();
1177         // Create some skeleton data just so we can call the WS.
1178         $user1 = self::getDataGenerator()->create_user();
1179         $user2 = self::getDataGenerator()->create_user();
1180         $user3 = self::getDataGenerator()->create_user();
1182         $this->setUser($user3);
1184         // Ensure an exception is thrown.
1185         $this->expectException('required_capability_exception');
1186         core_message_external::unblock_user($user1->id, $user2->id);
1187     }
1189     /**
1190      * Test search_contacts.
1191      */
1192     public function test_search_contacts() {
1193         global $DB;
1194         $this->resetAfterTest(true);
1196         $course1 = $this->getDataGenerator()->create_course();
1197         $course2 = $this->getDataGenerator()->create_course();
1199         $user1 = new stdClass();
1200         $user1->firstname = 'X';
1201         $user1->lastname = 'X';
1202         $user1 = $this->getDataGenerator()->create_user($user1);
1203         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1204         $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1206         $user2 = new stdClass();
1207         $user2->firstname = 'Eric';
1208         $user2->lastname = 'Cartman';
1209         $user2 = self::getDataGenerator()->create_user($user2);
1210         $user3 = new stdClass();
1211         $user3->firstname = 'Stan';
1212         $user3->lastname = 'Marsh';
1213         $user3 = self::getDataGenerator()->create_user($user3);
1214         self::getDataGenerator()->enrol_user($user3->id, $course1->id);
1215         $user4 = new stdClass();
1216         $user4->firstname = 'Kyle';
1217         $user4->lastname = 'Broflovski';
1218         $user4 = self::getDataGenerator()->create_user($user4);
1219         $user5 = new stdClass();
1220         $user5->firstname = 'Kenny';
1221         $user5->lastname = 'McCormick';
1222         $user5 = self::getDataGenerator()->create_user($user5);
1223         self::getDataGenerator()->enrol_user($user5->id, $course2->id);
1225         $this->setUser($user1);
1227         $results = core_message_external::search_contacts('r');
1228         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1229         $this->assertCount(5, $results); // Users 2 through 5 + admin
1231         $results = core_message_external::search_contacts('r', true);
1232         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1233         $this->assertCount(2, $results);
1235         $results = core_message_external::search_contacts('Kyle', false);
1236         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1237         $this->assertCount(1, $results);
1238         $result = reset($results);
1239         $this->assertEquals($user4->id, $result['id']);
1241         $results = core_message_external::search_contacts('y', false);
1242         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1243         $this->assertCount(2, $results);
1245         $results = core_message_external::search_contacts('y', true);
1246         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1247         $this->assertCount(1, $results);
1248         $result = reset($results);
1249         $this->assertEquals($user5->id, $result['id']);
1251         // Empty query, will throw an exception.
1252         $this->expectException(moodle_exception::class);
1253         $results = core_message_external::search_contacts('');
1254     }
1256     /**
1257      * Test get_messages.
1258      */
1259     public function test_get_messages() {
1260         global $CFG, $DB;
1261         $this->resetAfterTest(true);
1263         $this->preventResetByRollback();
1264         // This mark the messages as read!.
1265         $sink = $this->redirectMessages();
1267         $user1 = self::getDataGenerator()->create_user();
1268         $user2 = self::getDataGenerator()->create_user();
1269         $user3 = self::getDataGenerator()->create_user();
1271         $course = self::getDataGenerator()->create_course();
1273         // Send a message from one user to another.
1274         message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1275         message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE);
1276         message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1277         message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1278         message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE);
1280         $this->setUser($user1);
1281         // Get read conversations from user1 to user2.
1282         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1283         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1284         $this->assertCount(1, $messages['messages']);
1286         // Delete the message.
1287         $message = array_shift($messages['messages']);
1288         \core_message\api::delete_message($user1->id, $message['id']);
1290         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1291         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1292         $this->assertCount(0, $messages['messages']);
1294         // Get unread conversations from user1 to user2.
1295         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0);
1296         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1297         $this->assertCount(0, $messages['messages']);
1299         // Get read messages send from user1.
1300         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1301         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1302         $this->assertCount(1, $messages['messages']);
1304         $this->setUser($user2);
1305         // Get read conversations from any user to user2.
1306         $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0);
1307         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1308         $this->assertCount(2, $messages['messages']);
1310         // Conversations from user3 to user2.
1311         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1312         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1313         $this->assertCount(1, $messages['messages']);
1315         // Delete the message.
1316         $message = array_shift($messages['messages']);
1317         \core_message\api::delete_message($user2->id, $message['id']);
1319         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1320         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1321         $this->assertCount(0, $messages['messages']);
1323         $this->setUser($user3);
1324         // Get read notifications received by user3.
1325         $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0);
1326         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1327         $this->assertCount(0, $messages['messages']);
1329         // Now, create some notifications...
1330         // We are creating fake notifications but based on real ones.
1332         // This one comes from a disabled plugin's provider and therefore is not sent.
1333         $eventdata = new \core\message\message();
1334         $eventdata->courseid          = $course->id;
1335         $eventdata->notification      = 1;
1336         $eventdata->modulename        = 'moodle';
1337         $eventdata->component         = 'enrol_paypal';
1338         $eventdata->name              = 'paypal_enrolment';
1339         $eventdata->userfrom          = get_admin();
1340         $eventdata->userto            = $user1;
1341         $eventdata->subject           = "Moodle: PayPal payment";
1342         $eventdata->fullmessage       = "Your PayPal payment is pending.";
1343         $eventdata->fullmessageformat = FORMAT_PLAIN;
1344         $eventdata->fullmessagehtml   = '';
1345         $eventdata->smallmessage      = '';
1346         message_send($eventdata);
1347         $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '.
1348             'that is inactive or not allowed for the user id='.$user1->id);
1350         // This one omits notification = 1.
1351         $message = new \core\message\message();
1352         $message->courseid          = $course->id;
1353         $message->component         = 'enrol_manual';
1354         $message->name              = 'expiry_notification';
1355         $message->userfrom          = $user2;
1356         $message->userto            = $user1;
1357         $message->subject           = 'Test: This is not a notification but otherwise is valid';
1358         $message->fullmessage       = 'Test: Full message';
1359         $message->fullmessageformat = FORMAT_MARKDOWN;
1360         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1361         $message->smallmessage      = $message->subject;
1362         $message->contexturlname    = $course->fullname;
1363         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1364         message_send($message);
1366         $message = new \core\message\message();
1367         $message->courseid          = $course->id;
1368         $message->notification      = 1;
1369         $message->component         = 'enrol_manual';
1370         $message->name              = 'expiry_notification';
1371         $message->userfrom          = $user2;
1372         $message->userto            = $user1;
1373         $message->subject           = 'Enrolment expired';
1374         $message->fullmessage       = 'Enrolment expired blah blah blah';
1375         $message->fullmessageformat = FORMAT_MARKDOWN;
1376         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1377         $message->smallmessage      = $message->subject;
1378         $message->contexturlname    = $course->fullname;
1379         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1380         message_send($message);
1382         $userfrom = core_user::get_noreply_user();
1383         $userfrom->maildisplay = true;
1384         $eventdata = new \core\message\message();
1385         $eventdata->courseid          = $course->id;
1386         $eventdata->component         = 'moodle';
1387         $eventdata->name              = 'badgecreatornotice';
1388         $eventdata->userfrom          = $userfrom;
1389         $eventdata->userto            = $user1;
1390         $eventdata->notification      = 1;
1391         $eventdata->subject           = 'New badge';
1392         $eventdata->fullmessage       = format_text_email($eventdata->subject, FORMAT_HTML);
1393         $eventdata->fullmessageformat = FORMAT_PLAIN;
1394         $eventdata->fullmessagehtml   = $eventdata->subject;
1395         $eventdata->smallmessage      = $eventdata->subject;
1396         message_send($eventdata);
1398         $eventdata = new \core\message\message();
1399         $eventdata->courseid         = $course->id;
1400         $eventdata->name             = 'submission';
1401         $eventdata->component        = 'mod_feedback';
1402         $eventdata->userfrom         = $user1;
1403         $eventdata->userto           = $user2;
1404         $eventdata->subject          = 'Feedback submitted';
1405         $eventdata->fullmessage      = 'Feedback submitted from an user';
1406         $eventdata->fullmessageformat = FORMAT_PLAIN;
1407         $eventdata->fullmessagehtml  = '<strong>Feedback submitted</strong>';
1408         $eventdata->smallmessage     = '';
1409         $eventdata->customdata         = ['datakey' => 'data'];
1410         message_send($eventdata);
1412         $this->setUser($user1);
1413         // Get read notifications from any user to user1.
1414         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0);
1415         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1416         $this->assertCount(3, $messages['messages']);
1418         // Get one read notifications from any user to user1.
1419         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1);
1420         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1421         $this->assertCount(1, $messages['messages']);
1423         // Get unread notifications from any user to user1.
1424         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0);
1425         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1426         $this->assertCount(0, $messages['messages']);
1428         // Get read both type of messages from any user to user1.
1429         $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0);
1430         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1431         $this->assertCount(4, $messages['messages']);
1433         // Get read notifications from no-reply-user to user1.
1434         $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0);
1435         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1436         $this->assertCount(1, $messages['messages']);
1438         // Get notifications send by user1 to any user.
1439         $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0);
1440         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1441         $this->assertCount(1, $messages['messages']);
1442         // Check we receive custom data as a unserialisable json.
1443         $this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata']));
1444         $this->assertEquals('mod_feedback', $messages['messages'][0]['component']);
1445         $this->assertEquals('submission', $messages['messages'][0]['eventtype']);
1447         // Test warnings.
1448         $CFG->messaging = 0;
1450         $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0);
1451         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1452         $this->assertCount(1, $messages['warnings']);
1454         // Test exceptions.
1456         // Messaging disabled.
1457         try {
1458             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1459             $this->fail('Exception expected due messaging disabled.');
1460         } catch (moodle_exception $e) {
1461             $this->assertEquals('disabled', $e->errorcode);
1462         }
1464         $CFG->messaging = 1;
1466         // Invalid users.
1467         try {
1468             $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0);
1469             $this->fail('Exception expected due invalid users.');
1470         } catch (moodle_exception $e) {
1471             $this->assertEquals('accessdenied', $e->errorcode);
1472         }
1474         // Invalid user ids.
1475         try {
1476             $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0);
1477             $this->fail('Exception expected due invalid users.');
1478         } catch (moodle_exception $e) {
1479             $this->assertEquals('invaliduser', $e->errorcode);
1480         }
1482         // Invalid users (permissions).
1483         $this->setUser($user2);
1484         try {
1485             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1486             $this->fail('Exception expected due invalid user.');
1487         } catch (moodle_exception $e) {
1488             $this->assertEquals('accessdenied', $e->errorcode);
1489         }
1491     }
1493     /**
1494      * Test get_messages where we want all messages from a user, sent to any user.
1495      */
1496     public function test_get_messages_useridto_all() {
1497         $this->resetAfterTest(true);
1499         $user1 = self::getDataGenerator()->create_user();
1500         $user2 = self::getDataGenerator()->create_user();
1501         $user3 = self::getDataGenerator()->create_user();
1503         $this->setUser($user1);
1505         // Send a message from user 1 to two other users.
1506         $this->send_message($user1, $user2, 'some random text 1', 0, 1);
1507         $this->send_message($user1, $user3, 'some random text 2', 0, 2);
1509         // Get messages sent from user 1.
1510         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', false, false, 0, 0);
1511         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1513         // Confirm the data is correct.
1514         $messages = $messages['messages'];
1515         $this->assertCount(2, $messages);
1517         $message1 = array_shift($messages);
1518         $message2 = array_shift($messages);
1520         $this->assertEquals($user1->id, $message1['useridfrom']);
1521         $this->assertEquals($user2->id, $message1['useridto']);
1523         $this->assertEquals($user1->id, $message2['useridfrom']);
1524         $this->assertEquals($user3->id, $message2['useridto']);
1525     }
1527     /**
1528      * Test get_messages where we want all messages to a user, sent by any user.
1529      */
1530     public function test_get_messages_useridfrom_all() {
1531         $this->resetAfterTest();
1533         $user1 = self::getDataGenerator()->create_user();
1534         $user2 = self::getDataGenerator()->create_user();
1535         $user3 = self::getDataGenerator()->create_user();
1537         $this->setUser($user1);
1539         // Send a message to user 1 from two other users.
1540         $this->send_message($user2, $user1, 'some random text 1', 0, 1);
1541         $this->send_message($user3, $user1, 'some random text 2', 0, 2);
1543         // Get messages sent to user 1.
1544         $messages = core_message_external::get_messages($user1->id, 0, 'conversations', false, false, 0, 0);
1545         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1547         // Confirm the data is correct.
1548         $messages = $messages['messages'];
1549         $this->assertCount(2, $messages);
1551         $message1 = array_shift($messages);
1552         $message2 = array_shift($messages);
1554         $this->assertEquals($user2->id, $message1['useridfrom']);
1555         $this->assertEquals($user1->id, $message1['useridto']);
1557         $this->assertEquals($user3->id, $message2['useridfrom']);
1558         $this->assertEquals($user1->id, $message2['useridto']);
1559     }
1561     /**
1562      * Test get_blocked_users.
1563      */
1564     public function test_get_blocked_users() {
1565         $this->resetAfterTest(true);
1567         $user1 = self::getDataGenerator()->create_user();
1568         $userstranger = self::getDataGenerator()->create_user();
1569         $useroffline1 = self::getDataGenerator()->create_user();
1570         $useroffline2 = self::getDataGenerator()->create_user();
1571         $userblocked = self::getDataGenerator()->create_user();
1573         // Login as user1.
1574         $this->setUser($user1);
1576         \core_message\api::add_contact($user1->id, $useroffline1->id);
1577         \core_message\api::add_contact($user1->id, $useroffline2->id);
1579         // The userstranger sends a couple of messages to user1.
1580         $this->send_message($userstranger, $user1, 'Hello there!');
1581         $this->send_message($userstranger, $user1, 'How you goin?');
1583         // The userblocked sends a message to user1.
1584         // Note that this user is not blocked at this point.
1585         $this->send_message($userblocked, $user1, 'Here, have some spam.');
1587         // Retrieve the list of blocked users.
1588         $this->setUser($user1);
1589         $blockedusers = core_message_external::get_blocked_users($user1->id);
1590         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1591         $this->assertCount(0, $blockedusers['users']);
1593         // Block the $userblocked and retrieve again the list.
1594         \core_message\api::block_user($user1->id, $userblocked->id);
1595         $blockedusers = core_message_external::get_blocked_users($user1->id);
1596         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1597         $this->assertCount(1, $blockedusers['users']);
1599         // Remove the $userblocked and check that the list now is empty.
1600         delete_user($userblocked);
1601         $blockedusers = core_message_external::get_blocked_users($user1->id);
1602         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1603         $this->assertCount(0, $blockedusers['users']);
1604     }
1606     /**
1607      * Test mark_message_read.
1608      */
1609     public function test_mark_message_read() {
1610         $this->resetAfterTest(true);
1612         $user1 = self::getDataGenerator()->create_user();
1613         $user2 = self::getDataGenerator()->create_user();
1614         $user3 = self::getDataGenerator()->create_user();
1616         // Login as user1.
1617         $this->setUser($user1);
1618         \core_message\api::add_contact($user1->id, $user2->id);
1619         \core_message\api::add_contact($user1->id, $user3->id);
1621         // The user2 sends a couple of messages to user1.
1622         $this->send_message($user2, $user1, 'Hello there!');
1623         $this->send_message($user2, $user1, 'How you goin?');
1624         $this->send_message($user3, $user1, 'How you goin?');
1625         $this->send_message($user3, $user2, 'How you goin?');
1627         // Retrieve all messages sent by user2 (they are currently unread).
1628         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1630         $messageids = array();
1631         foreach ($lastmessages as $m) {
1632             $messageid = core_message_external::mark_message_read($m->id, time());
1633             $messageids[] = external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid);
1634         }
1636         // Retrieve all messages sent (they are currently read).
1637         $lastmessages = message_get_messages($user1->id, $user2->id, 0, true);
1638         $this->assertCount(2, $lastmessages);
1639         $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages);
1640         $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages);
1642         // Retrieve all messages sent by any user (that are currently unread).
1643         $lastmessages = message_get_messages($user1->id, 0, 0, false);
1644         $this->assertCount(1, $lastmessages);
1646         // Invalid message ids.
1647         try {
1648             $messageid = core_message_external::mark_message_read(1337, time());
1649             $this->fail('Exception expected due invalid messageid.');
1650         } catch (dml_missing_record_exception $e) {
1651             $this->assertEquals('invalidrecordunknown', $e->errorcode);
1652         }
1654         // A message to a different user.
1655         $lastmessages = message_get_messages($user2->id, $user3->id, 0, false);
1656         $messageid = array_pop($lastmessages)->id;
1657         try {
1658             $messageid = core_message_external::mark_message_read($messageid, time());
1659             $this->fail('Exception expected due invalid messageid.');
1660         } catch (invalid_parameter_exception $e) {
1661             $this->assertEquals('invalidparameter', $e->errorcode);
1662         }
1663     }
1665     /**
1666      * Test mark_notification_read.
1667      */
1668     public function test_mark_notification_read() {
1669         $this->resetAfterTest(true);
1671         $user1 = self::getDataGenerator()->create_user();
1672         $user2 = self::getDataGenerator()->create_user();
1673         $user3 = self::getDataGenerator()->create_user();
1675         // Login as user1.
1676         $this->setUser($user1);
1677         \core_message\api::add_contact($user1->id, $user2->id);
1678         \core_message\api::add_contact($user1->id, $user3->id);
1680         // The user2 sends a couple of notifications to user1.
1681         $this->send_message($user2, $user1, 'Hello there!', 1);
1682         $this->send_message($user2, $user1, 'How you goin?', 1);
1683         $this->send_message($user3, $user1, 'How you goin?', 1);
1684         $this->send_message($user3, $user2, 'How you goin?', 1);
1686         // Retrieve all notifications sent by user2 (they are currently unread).
1687         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, false);
1689         $notificationids = array();
1690         foreach ($lastnotifications as $n) {
1691             $notificationid = core_message_external::mark_notification_read($n->id, time());
1692             $notificationids[] = external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(),
1693                 $notificationid);
1694         }
1696         // Retrieve all notifications sent (they are currently read).
1697         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, true);
1698         $this->assertCount(2, $lastnotifications);
1699         $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications);
1700         $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications);
1702         // Retrieve all notifications sent by any user (that are currently unread).
1703         $lastnotifications = message_get_messages($user1->id, 0, 1, false);
1704         $this->assertCount(1, $lastnotifications);
1706         // Invalid notification ids.
1707         try {
1708             $notificationid = core_message_external::mark_notification_read(1337, time());
1709             $this->fail('Exception expected due invalid notificationid.');
1710         } catch (dml_missing_record_exception $e) {
1711             $this->assertEquals('invalidrecord', $e->errorcode);
1712         }
1714         // A notification to a different user.
1715         $lastnotifications = message_get_messages($user2->id, $user3->id, 1, false);
1716         $notificationid = array_pop($lastnotifications)->id;
1717         try {
1718             $notificationid = core_message_external::mark_notification_read($notificationid, time());
1719             $this->fail('Exception expected due invalid notificationid.');
1720         } catch (invalid_parameter_exception $e) {
1721             $this->assertEquals('invalidparameter', $e->errorcode);
1722         }
1723     }
1725     /**
1726      * Test delete_message.
1727      */
1728     public function test_delete_message() {
1729         global $DB;
1730         $this->resetAfterTest(true);
1732         $user1 = self::getDataGenerator()->create_user();
1733         $user2 = self::getDataGenerator()->create_user();
1734         $user3 = self::getDataGenerator()->create_user();
1735         $user4 = self::getDataGenerator()->create_user();
1737         // Login as user1.
1738         $this->setUser($user1);
1739         \core_message\api::add_contact($user1->id, $user2->id);
1740         \core_message\api::add_contact($user1->id, $user3->id);
1742         // User user1 does not interchange messages with user3.
1743         $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1744         $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1745         $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1746         $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE);
1748         // Retrieve all messages sent by user2 (they are currently unread).
1749         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1751         // Delete a message not read, as a user from.
1752         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1753         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1754         $this->assertTrue($result['status']);
1755         $this->assertCount(0, $result['warnings']);
1756         $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id));
1757         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action);
1759         // Try to delete the same message again.
1760         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1761         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1762         $this->assertFalse($result['status']);
1764         // Try to delete a message that does not belong to me.
1765         try {
1766             $messageid = core_message_external::delete_message($m2to3, $user3->id, false);
1767             $this->fail('Exception expected due invalid messageid.');
1768         } catch (moodle_exception $e) {
1769             $this->assertEquals('You do not have permission to delete this message', $e->errorcode);
1770         }
1772         $this->setUser($user3);
1773         // Delete a message not read, as a user to.
1774         $result = core_message_external::delete_message($m2to3, $user3->id, false);
1775         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1776         $this->assertTrue($result['status']);
1777         $this->assertCount(0, $result['warnings']);
1778         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id,
1779             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1781         // Delete a message read.
1782         $message = $DB->get_record('messages', ['id' => $m3to2]);
1783         \core_message\api::mark_message_as_read($user3->id, $message, time());
1784         $result = core_message_external::delete_message($m3to2, $user3->id);
1785         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1786         $this->assertTrue($result['status']);
1787         $this->assertCount(0, $result['warnings']);
1788         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id,
1789             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1791         // Invalid message ids.
1792         try {
1793             $result = core_message_external::delete_message(-1, $user1->id);
1794             $this->fail('Exception expected due invalid messageid.');
1795         } catch (dml_missing_record_exception $e) {
1796             $this->assertEquals('invalidrecord', $e->errorcode);
1797         }
1799         // Invalid user.
1800         try {
1801             $result = core_message_external::delete_message($m1to2, -1, false);
1802             $this->fail('Exception expected due invalid user.');
1803         } catch (moodle_exception $e) {
1804             $this->assertEquals('invaliduser', $e->errorcode);
1805         }
1807         // Not active user.
1808         delete_user($user2);
1809         try {
1810             $result = core_message_external::delete_message($m1to2, $user2->id, false);
1811             $this->fail('Exception expected due invalid user.');
1812         } catch (moodle_exception $e) {
1813             $this->assertEquals('userdeleted', $e->errorcode);
1814         }
1816         // Now, as an admin, try to delete any message.
1817         $this->setAdminUser();
1818         $result = core_message_external::delete_message($m3to4, $user4->id, false);
1819         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1820         $this->assertTrue($result['status']);
1821         $this->assertCount(0, $result['warnings']);
1822         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id,
1823             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1825     }
1827     public function test_mark_all_notifications_as_read_invalid_user_exception() {
1828         $this->resetAfterTest(true);
1830         $this->expectException('moodle_exception');
1831         core_message_external::mark_all_notifications_as_read(-2132131, 0);
1832     }
1834     public function test_mark_all_notifications_as_read_access_denied_exception() {
1835         $this->resetAfterTest(true);
1837         $sender = $this->getDataGenerator()->create_user();
1838         $user = $this->getDataGenerator()->create_user();
1840         $this->setUser($user);
1841         $this->expectException('moodle_exception');
1842         core_message_external::mark_all_notifications_as_read($sender->id, 0);
1843     }
1845     public function test_mark_all_notifications_as_read_missing_from_user_exception() {
1846         $this->resetAfterTest(true);
1848         $sender = $this->getDataGenerator()->create_user();
1850         $this->setUser($sender);
1851         $this->expectException('moodle_exception');
1852         core_message_external::mark_all_notifications_as_read($sender->id, 99999);
1853     }
1855     public function test_mark_all_notifications_as_read() {
1856         global $DB;
1858         $this->resetAfterTest(true);
1860         $sender1 = $this->getDataGenerator()->create_user();
1861         $sender2 = $this->getDataGenerator()->create_user();
1862         $sender3 = $this->getDataGenerator()->create_user();
1863         $recipient = $this->getDataGenerator()->create_user();
1865         $this->setUser($recipient);
1867         $this->send_message($sender1, $recipient, 'Notification', 1);
1868         $this->send_message($sender1, $recipient, 'Notification', 1);
1869         $this->send_message($sender2, $recipient, 'Notification', 1);
1870         $this->send_message($sender2, $recipient, 'Notification', 1);
1871         $this->send_message($sender3, $recipient, 'Notification', 1);
1872         $this->send_message($sender3, $recipient, 'Notification', 1);
1874         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id);
1875         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1876         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1878         $this->assertCount(2, $readnotifications);
1879         $this->assertCount(4, $unreadnotifications);
1881         core_message_external::mark_all_notifications_as_read($recipient->id, 0);
1882         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1883         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1885         $this->assertCount(6, $readnotifications);
1886         $this->assertCount(0, $unreadnotifications);
1887     }
1889     public function test_mark_all_notifications_as_read_time_created_to() {
1890         global $DB;
1892         $this->resetAfterTest(true);
1894         $sender1 = $this->getDataGenerator()->create_user();
1895         $sender2 = $this->getDataGenerator()->create_user();
1897         $recipient = $this->getDataGenerator()->create_user();
1898         $this->setUser($recipient);
1900         // Record messages as sent on one second intervals.
1901         $time = time();
1903         $this->send_message($sender1, $recipient, 'Message 1', 1, $time);
1904         $this->send_message($sender2, $recipient, 'Message 2', 1, $time + 1);
1905         $this->send_message($sender1, $recipient, 'Message 3', 1, $time + 2);
1906         $this->send_message($sender2, $recipient, 'Message 4', 1, $time + 3);
1908         // Mark notifications sent from sender1 up until the second message; should only mark the first notification as read.
1909         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id, $time + 1);
1911         $params = [$recipient->id];
1913         $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params));
1914         $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params));
1916         // Mark all notifications as read from any sender up to the time the third message was sent.
1917         core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 2);
1919         $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params));
1920         $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params));
1922         // Mark all notifications as read from any sender with a time after all messages were sent.
1923         core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 10);
1925         $this->assertEquals(4, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params));
1926         $this->assertEquals(0, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params));
1927     }
1929     /**
1930      * Test get_user_notification_preferences
1931      */
1932     public function test_get_user_notification_preferences() {
1933         $this->resetAfterTest(true);
1935         $user = self::getDataGenerator()->create_user();
1936         $this->setUser($user);
1938         // Set a couple of preferences to test.
1939         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
1940         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
1942         $prefs = core_message_external::get_user_notification_preferences();
1943         $prefs = external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs);
1944         // Check processors.
1945         $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors']));
1946         $this->assertEquals($user->id, $prefs['preferences']['userid']);
1948         // Check components.
1949         $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components']));
1951         // Check some preferences that we previously set.
1952         $found = 0;
1953         foreach ($prefs['preferences']['components'] as $component) {
1954             foreach ($component['notifications'] as $prefdata) {
1955                 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') {
1956                     continue;
1957                 }
1958                 foreach ($prefdata['processors'] as $processor) {
1959                     if ($processor['name'] == 'popup') {
1960                         $this->assertTrue($processor['loggedin']['checked']);
1961                         $found++;
1962                     } else if ($processor['name'] == 'email') {
1963                         $this->assertTrue($processor['loggedoff']['checked']);
1964                         $found++;
1965                     }
1966                 }
1967             }
1968         }
1969         $this->assertEquals(2, $found);
1970     }
1972     /**
1973      * Test get_user_notification_preferences permissions
1974      */
1975     public function test_get_user_notification_preferences_permissions() {
1976         $this->resetAfterTest(true);
1978         $user = self::getDataGenerator()->create_user();
1979         $otheruser = self::getDataGenerator()->create_user();
1980         $this->setUser($user);
1982         $this->expectException('moodle_exception');
1983         $prefs = core_message_external::get_user_notification_preferences($otheruser->id);
1984     }
1986     /**
1987      * Tests searching for users when site-wide messaging is disabled.
1988      *
1989      * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
1990      * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
1991      * profile.
1992      */
1993     public function test_message_search_users_messagingallusers_disabled() {
1994         global $DB;
1995         $this->resetAfterTest();
1997         // Create some users.
1998         $users = [];
1999         foreach (range(1, 8) as $i) {
2000             $user = new stdClass();
2001             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2002             $user->lastname = $i;
2003             $user = $this->getDataGenerator()->create_user($user);
2004             $users[$i] = $user;
2005         }
2007         // Enrol a few users in the same course, but leave them as non-contacts.
2008         $course1 = $this->getDataGenerator()->create_course();
2009         $course2 = $this->getDataGenerator()->create_course();
2011         $this->setAdminUser();
2012         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2013         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2014         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2016         // Add some other users as contacts.
2017         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2018         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2019         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2021         // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
2022         $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher');
2023         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
2024         set_config('coursecontact', $teacherrole->id);
2026         // Create individual conversations between some users, one contact and one non-contact.
2027         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2028             [$users[1]->id, $users[2]->id]);
2029         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2030             [$users[6]->id, $users[1]->id]);
2032         // Create a group conversation between 4 users, including a contact and a non-contact.
2033         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2034             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
2036         // Set as the user performing the search.
2037         $this->setUser($users[1]);
2039         // Perform a search with $CFG->messagingallusers disabled.
2040         set_config('messagingallusers', 0);
2041         $result = core_message_external::message_search_users($users[1]->id, 'search');
2042         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2044         // Confirm that we returns contacts and non-contacts.
2045         $this->assertArrayHasKey('contacts', $result);
2046         $this->assertArrayHasKey('noncontacts', $result);
2047         $contacts = $result['contacts'];
2048         $noncontacts = $result['noncontacts'];
2050         // Check that we retrieved the correct contacts.
2051         $this->assertCount(2, $contacts);
2052         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2053         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2055         // Verify the correct conversations were returned for the contacts.
2056         $this->assertCount(2, $contacts[0]['conversations']);
2057         // We can't rely on the ordering of conversations within the results, so sort by id first.
2058         usort($contacts[0]['conversations'], function($a, $b) {
2059             return $a['id'] < $b['id'];
2060         });
2061         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2062         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2064         $this->assertCount(0, $contacts[1]['conversations']);
2066         // Check that we retrieved the correct non-contacts.
2067         // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles
2068         // are visible in that course. This excludes users like course contacts.
2069         $this->assertCount(3, $noncontacts);
2070         // Self-conversation first.
2071         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2072         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2073         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2075         // Verify the correct conversations were returned for the non-contacts.
2076         $this->assertCount(1, $noncontacts[1]['conversations']);
2077         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']);
2079         $this->assertCount(1, $noncontacts[2]['conversations']);
2080         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']);
2081     }
2083     /**
2084      * Tests searching for users when site-wide messaging is enabled.
2085      *
2086      * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user
2087      * can view their respective profile.
2088      */
2089     public function test_message_search_users_messagingallusers_enabled() {
2090         global $DB;
2091         $this->resetAfterTest();
2093         // Create some users.
2094         $users = [];
2095         foreach (range(1, 9) as $i) {
2096             $user = new stdClass();
2097             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2098             $user->lastname = $i;
2099             $user = $this->getDataGenerator()->create_user($user);
2100             $users[$i] = $user;
2101         }
2103         // Enrol a few users in the same course, but leave them as non-contacts.
2104         $course1 = $this->getDataGenerator()->create_course();
2105         $course2 = $this->getDataGenerator()->create_course();
2107         $this->setAdminUser();
2108         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2109         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2110         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2112         // Add some other users as contacts.
2113         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2114         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2115         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2117         // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
2118         $this->getDataGenerator()->enrol_user($users[9]->id, $course2->id, 'editingteacher');
2119         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
2120         set_config('coursecontact', $teacherrole->id);
2122         // Create individual conversations between some users, one contact and one non-contact.
2123         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2124             [$users[1]->id, $users[2]->id]);
2125         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2126             [$users[6]->id, $users[1]->id]);
2128         // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
2129         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2130             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
2132         // Set as the user performing the search.
2133         $this->setUser($users[1]);
2135         // Perform a search with $CFG->messagingallusers enabled.
2136         set_config('messagingallusers', 1);
2137         $result = core_message_external::message_search_users($users[1]->id, 'search');
2138         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2140         // Confirm that we returns contacts and non-contacts.
2141         $this->assertArrayHasKey('contacts', $result);
2142         $this->assertArrayHasKey('noncontacts', $result);
2143         $contacts = $result['contacts'];
2144         $noncontacts = $result['noncontacts'];
2146         // Check that we retrieved the correct contacts.
2147         $this->assertCount(2, $contacts);
2148         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2149         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2151         // Verify the correct conversations were returned for the contacts.
2152         $this->assertCount(2, $contacts[0]['conversations']);
2153         // We can't rely on the ordering of conversations within the results, so sort by id first.
2154         usort($contacts[0]['conversations'], function($a, $b) {
2155             return $a['id'] < $b['id'];
2156         });
2157         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2158         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2160         $this->assertCount(0, $contacts[1]['conversations']);
2162         // Check that we retrieved the correct non-contacts.
2163         // If site wide messaging is enabled, we expect to be able to search for any users whose profiles we can view.
2164         // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1.
2165         $this->assertCount(4, $noncontacts);
2166         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2167         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2168         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2169         $this->assertEquals($users[9]->id, $noncontacts[3]['id']);
2171         // Verify the correct conversations were returned for the non-contacts.
2172         $this->assertCount(1, $noncontacts[1]['conversations']);
2173         $this->assertCount(1, $noncontacts[2]['conversations']);
2174         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']);
2175         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']);
2176         $this->assertCount(0, $noncontacts[3]['conversations']);
2177     }
2179     /**
2180      * Verify searching for users find themselves when they have self-conversations.
2181      */
2182     public function test_message_search_users_self_conversations() {
2183         $this->resetAfterTest();
2185         // Create some users.
2186         $user1 = new stdClass();
2187         $user1->firstname = 'User';
2188         $user1->lastname = 'One';
2189         $user1 = $this->getDataGenerator()->create_user($user1);
2190         $user2 = new stdClass();
2191         $user2->firstname = 'User';
2192         $user2->lastname = 'Two';
2193         $user2 = $this->getDataGenerator()->create_user($user2);
2195         // Get self-conversation for user1.
2196         $sc1 = \core_message\api::get_self_conversation($user1->id);
2197         testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
2199         // Perform a search as user1.
2200         $this->setUser($user1);
2201         $result = core_message_external::message_search_users($user1->id, 'One');
2202         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2204         // Check results are empty.
2205         $this->assertCount(0, $result['contacts']);
2206         $this->assertCount(1, $result['noncontacts']);
2207     }
2209     /**
2210      * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
2211      */
2212     public function test_message_search_users_with_empty_result() {
2213         $this->resetAfterTest();
2215         // Create some users, but make sure neither will match the search term.
2216         $user1 = new stdClass();
2217         $user1->firstname = 'User';
2218         $user1->lastname = 'One';
2219         $user1 = $this->getDataGenerator()->create_user($user1);
2220         $user2 = new stdClass();
2221         $user2->firstname = 'User';
2222         $user2->lastname = 'Two';
2223         $user2 = $this->getDataGenerator()->create_user($user2);
2225         // Perform a search as user1.
2226         $this->setUser($user1);
2227         $result = core_message_external::message_search_users($user1->id, 'search');
2228         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2230         // Check results are empty.
2231         $this->assertCount(0, $result['contacts']);
2232         $this->assertCount(0, $result['noncontacts']);
2233     }
2235     /**
2236      * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
2237      */
2238     public function test_message_search_users_limit_offset() {
2239         $this->resetAfterTest();
2241         // Create 20 users.
2242         $users = [];
2243         foreach (range(1, 20) as $i) {
2244             $user = new stdClass();
2245             $user->firstname = "User search";
2246             $user->lastname = $i;
2247             $user = $this->getDataGenerator()->create_user($user);
2248             $users[$i] = $user;
2249         }
2251         // Enrol the first 8 users in the same course, but leave them as non-contacts.
2252         $this->setAdminUser();
2253         $course1 = $this->getDataGenerator()->create_course();
2254         foreach (range(1, 8) as $i) {
2255             $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
2256         }
2258         // Add 5 users, starting at the 11th user, as contacts for user1.
2259         foreach (range(11, 15) as $i) {
2260             \core_message\api::add_contact($users[1]->id, $users[$i]->id);
2261         }
2263         // Set as the user performing the search.
2264         $this->setUser($users[1]);
2266         // Search using a limit of 3.
2267         // This tests the case where we have more results than the limit for both contacts and non-contacts.
2268         $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3);
2269         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2270         $contacts = $result['contacts'];
2271         $noncontacts = $result['noncontacts'];
2273         // Check that we retrieved the correct contacts.
2274         $this->assertCount(3, $contacts);
2275         $this->assertEquals($users[11]->id, $contacts[0]['id']);
2276         $this->assertEquals($users[12]->id, $contacts[1]['id']);
2277         $this->assertEquals($users[13]->id, $contacts[2]['id']);
2279         // Check that we retrieved the correct non-contacts.
2280         // Consider first conversation is self-conversation.
2281         $this->assertCount(3, $noncontacts);
2282         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2283         $this->assertEquals($users[2]->id, $noncontacts[1]['id']);
2284         $this->assertEquals($users[3]->id, $noncontacts[2]['id']);
2286         // Now, offset to get the next batch of results.
2287         // We expect to see 2 contacts, and 3 non-contacts.
2288         $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3);
2289         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2290         $contacts = $result['contacts'];
2291         $noncontacts = $result['noncontacts'];
2292         $this->assertCount(2, $contacts);
2293         $this->assertEquals($users[14]->id, $contacts[0]['id']);
2294         $this->assertEquals($users[15]->id, $contacts[1]['id']);
2296         $this->assertCount(3, $noncontacts);
2297         $this->assertEquals($users[4]->id, $noncontacts[0]['id']);
2298         $this->assertEquals($users[5]->id, $noncontacts[1]['id']);
2299         $this->assertEquals($users[6]->id, $noncontacts[2]['id']);
2301         // Now, offset to get the next batch of results.
2302         // We expect to see 0 contacts, and 2 non-contacts.
2303         $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3);
2304         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2305         $contacts = $result['contacts'];
2306         $noncontacts = $result['noncontacts'];
2307         $this->assertCount(0, $contacts);
2309         $this->assertCount(2, $noncontacts);
2310         $this->assertEquals($users[7]->id, $noncontacts[0]['id']);
2311         $this->assertEquals($users[8]->id, $noncontacts[1]['id']);
2312     }
2314     /**
2315      * Tests searching users as another user having the 'moodle/user:viewdetails' capability.
2316      */
2317     public function test_message_search_users_with_cap() {
2318         $this->resetAfterTest();
2319         global $DB;
2321         // Create some users.
2322         $users = [];
2323         foreach (range(1, 8) as $i) {
2324             $user = new stdClass();
2325             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2326             $user->lastname = $i;
2327             $user = $this->getDataGenerator()->create_user($user);
2328             $users[$i] = $user;
2329         }
2331         // Enrol a few users in the same course, but leave them as non-contacts.
2332         $course1 = $this->getDataGenerator()->create_course();
2333         $this->setAdminUser();
2334         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2335         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2336         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2338         // Add some other users as contacts.
2339         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2340         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2341         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2343         // Set as the user performing the search.
2344         $this->setUser($users[1]);
2346         // Grant the authenticated user role the capability 'user:viewdetails' at site context.
2347         $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
2348         assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
2350         // Perform a search with $CFG->messagingallusers disabled.
2351         set_config('messagingallusers', 0);
2352         $result = core_message_external::message_search_users($users[1]->id, 'search');
2353         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2354         $contacts = $result['contacts'];
2355         $noncontacts = $result['noncontacts'];
2357         // Check that we retrieved the correct contacts.
2358         $this->assertCount(2, $contacts);
2359         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2360         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2362         // Check that we retrieved the correct non-contacts.
2363         // Site-wide messaging is disabled, so we expect to be able to search for any users whose profile we can view.
2364         // Consider first conversations is self-conversation.
2365         $this->assertCount(3, $noncontacts);
2366         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2367         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2368         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2369     }
2371     /**
2372      * Tests searching users as another user without the 'moodle/user:viewdetails' capability.
2373      */
2374     public function test_message_search_users_without_cap() {
2375         $this->resetAfterTest();
2377         // Create some users.
2378         $user1 = $this->getDataGenerator()->create_user();
2379         $user2 = $this->getDataGenerator()->create_user();
2381         // The person doing the search for another user.
2382         $this->setUser($user1);
2384         // Ensure an exception is thrown.
2385         $this->expectException('moodle_exception');
2386         core_message_external::message_search_users($user2->id, 'User');
2387         $this->assertDebuggingCalled();
2388     }
2390     /**
2391      * Tests searching users with messaging disabled.
2392      */
2393     public function test_message_search_users_messaging_disabled() {
2394         $this->resetAfterTest();
2396         // Create some skeleton data just so we can call the WS.
2397         $user = $this->getDataGenerator()->create_user();
2399         // The person doing the search.
2400         $this->setUser($user);
2402         // Disable messaging.
2403         set_config('messaging', 0);
2405         // Ensure an exception is thrown.
2406         $this->expectException('moodle_exception');
2407         core_message_external::message_search_users($user->id, 'User');
2408     }
2410     /**
2411      * Tests searching messages.
2412      */
2413     public function test_messagearea_search_messages() {
2414         $this->resetAfterTest(true);
2416         // Create some users.
2417         $user1 = self::getDataGenerator()->create_user();
2418         $user2 = self::getDataGenerator()->create_user();
2420         // The person doing the search.
2421         $this->setUser($user1);
2423         // Send some messages back and forth.
2424         $time = time();
2425         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2426         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2427         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2428         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2429         $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2431         // Perform a search.
2432         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2434         // We need to execute the return values cleaning process to simulate the web service server.
2435         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result);
2437         // Confirm the data is correct.
2438         $messages = $result['contacts'];
2439         $this->assertCount(2, $messages);
2441         $message1 = $messages[0];
2442         $message2 = $messages[1];
2444         $this->assertEquals($user2->id, $message1['userid']);
2445         $this->assertEquals(fullname($user2), $message1['fullname']);
2446         $this->assertTrue($message1['ismessaging']);
2447         $this->assertFalse($message1['sentfromcurrentuser']);
2448         $this->assertEquals('Word.', $message1['lastmessage']);
2449         $this->assertNotEmpty($message1['messageid']);
2450         $this->assertNull($message1['isonline']);
2451         $this->assertFalse($message1['isread']);
2452         $this->assertFalse($message1['isblocked']);
2453         $this->assertNull($message1['unreadcount']);
2454         $this->assertEquals($convid, $message1['conversationid']);
2456         $this->assertEquals($user2->id, $message2['userid']);
2457         $this->assertEquals(fullname($user2), $message2['fullname']);
2458         $this->assertTrue($message2['ismessaging']);
2459         $this->assertTrue($message2['sentfromcurrentuser']);
2460         $this->assertEquals('Yo!', $message2['lastmessage']);
2461         $this->assertNotEmpty($message2['messageid']);
2462         $this->assertNull($message2['isonline']);
2463         $this->assertTrue($message2['isread']);
2464         $this->assertFalse($message2['isblocked']);
2465         $this->assertNull($message2['unreadcount']);
2466         $this->assertEquals($convid, $message2['conversationid']);
2467     }
2469     /**
2470      * Tests searching messages as another user.
2471      */
2472     public function test_messagearea_search_messages_as_other_user() {
2473         $this->resetAfterTest(true);
2475         // The person doing the search.
2476         $this->setAdminUser();
2478         // Create some users.
2479         $user1 = self::getDataGenerator()->create_user();
2480         $user2 = self::getDataGenerator()->create_user();
2482         // Send some messages back and forth.
2483         $time = time();
2484         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2485         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2486         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2487         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2489         // Perform a search.
2490         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2492         // We need to execute the return values cleaning process to simulate the web service server.
2493         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(),
2494             $result);
2496         // Confirm the data is correct.
2497         $messages = $result['contacts'];
2498         $this->assertCount(2, $messages);
2500         $message1 = $messages[0];
2501         $message2 = $messages[1];
2503         $this->assertEquals($user2->id, $message1['userid']);
2504         $this->assertEquals(fullname($user2), $message1['fullname']);
2505         $this->assertTrue($message1['ismessaging']);
2506         $this->assertFalse($message1['sentfromcurrentuser']);
2507         $this->assertEquals('Word.', $message1['lastmessage']);
2508         $this->assertNotEmpty($message1['messageid']);
2509         $this->assertFalse($message1['isonline']);
2510         $this->assertFalse($message1['isread']);
2511         $this->assertFalse($message1['isblocked']);
2512         $this->assertNull($message1['unreadcount']);
2514         $this->assertEquals($user2->id, $message2['userid']);
2515         $this->assertEquals(fullname($user2), $message2['fullname']);
2516         $this->assertTrue($message2['ismessaging']);
2517         $this->assertTrue($message2['sentfromcurrentuser']);
2518         $this->assertEquals('Yo!', $message2['lastmessage']);
2519         $this->assertNotEmpty($message2['messageid']);
2520         $this->assertFalse($message2['isonline']);
2521         $this->assertTrue($message2['isread']);
2522         $this->assertFalse($message2['isblocked']);
2523         $this->assertNull($message2['unreadcount']);
2524     }
2526     /**
2527      * Tests searching messages as another user without the proper capabilities.
2528      */
2529     public function test_messagearea_search_messages_as_other_user_without_cap() {
2530         $this->resetAfterTest(true);
2532         // Create some users.
2533         $user1 = self::getDataGenerator()->create_user();
2534         $user2 = self::getDataGenerator()->create_user();
2536         // The person doing the search for another user.
2537         $this->setUser($user1);
2539         // Ensure an exception is thrown.
2540         $this->expectException('moodle_exception');
2541         core_message_external::data_for_messagearea_search_messages($user2->id, 'Search');
2542     }
2544     /**
2545      * Tests searching messages with messaging disabled
2546      */
2547     public function test_messagearea_search_messages_messaging_disabled() {
2548         global $CFG;
2550         $this->resetAfterTest(true);
2552         // Create some skeleton data just so we can call the WS.
2553         $user = self::getDataGenerator()->create_user();
2555         // The person doing the search .
2556         $this->setUser($user);
2558         // Disable messaging.
2559         $CFG->messaging = 0;
2561         // Ensure an exception is thrown.
2562         $this->expectException('moodle_exception');
2563         core_message_external::data_for_messagearea_search_messages($user->id, 'Search');
2564     }
2566     /**
2567      * Tests retrieving contacts.
2568      */
2569     public function test_get_user_contacts() {
2570         $this->resetAfterTest(true);
2572         // Create some users.
2573         $user1 = self::getDataGenerator()->create_user();
2575         // Set as the user.
2576         $this->setUser($user1);
2578         $user2 = new stdClass();
2579         $user2->firstname = 'User';
2580         $user2->lastname = 'A';
2581         $user2 = self::getDataGenerator()->create_user($user2);
2583         $user3 = new stdClass();
2584         $user3->firstname = 'User';
2585         $user3->lastname = 'B';
2586         $user3 = self::getDataGenerator()->create_user($user3);
2588         $user4 = new stdClass();
2589         $user4->firstname = 'User';
2590         $user4->lastname = 'C';
2591         $user4 = self::getDataGenerator()->create_user($user4);
2593         $user5 = new stdClass();
2594         $user5->firstname = 'User';
2595         $user5->lastname = 'D';
2596         $user5 = self::getDataGenerator()->create_user($user5);
2598         // Add some users as contacts.
2599         \core_message\api::add_contact($user1->id, $user2->id);
2600         \core_message\api::add_contact($user1->id, $user3->id);
2601         \core_message\api::add_contact($user1->id, $user4->id);
2603         // Retrieve the contacts.
2604         $result = core_message_external::get_user_contacts($user1->id);
2606         // We need to execute the return values cleaning process to simulate the web service server.
2607         $result = external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(),
2608             $result);
2610         // Confirm the data is correct.
2611         $contacts = $result;
2612         usort($contacts, ['static', 'sort_contacts_id']);
2613         $this->assertCount(3, $contacts);
2615         $contact1 = array_shift($contacts);
2616         $contact2 = array_shift($contacts);
2617         $contact3 = array_shift($contacts);
2619         $this->assertEquals($user2->id, $contact1['id']);
2620         $this->assertEquals(fullname($user2), $contact1['fullname']);
2621         $this->assertTrue($contact1['iscontact']);
2623         $this->assertEquals($user3->id, $contact2['id']);
2624         $this->assertEquals(fullname($user3), $contact2['fullname']);
2625         $this->assertTrue($contact2['iscontact']);
2627         $this->assertEquals($user4->id, $contact3['id']);
2628         $this->assertEquals(fullname($user4), $contact3['fullname']);
2629         $this->assertTrue($contact3['iscontact']);
2630     }
2632     /**
2633      * Tests retrieving contacts as another user.
2634      */
2635     public function test_get_user_contacts_as_other_user() {
2636         $this->resetAfterTest(true);
2638         $this->setAdminUser();
2640         // Create some users.
2641         $user1 = self::getDataGenerator()->create_user();
2643         $user2 = new stdClass();
2644         $user2->firstname = 'User';
2645         $user2->lastname = 'A';
2646         $user2 = self::getDataGenerator()->create_user($user2);
2648         $user3 = new stdClass();
2649         $user3->firstname = 'User';
2650         $user3->lastname = 'B';
2651         $user3 = self::getDataGenerator()->create_user($user3);
2653         $user4 = new stdClass();
2654         $user4->firstname = 'User';
2655         $user4->lastname = 'C';
2656         $user4 = self::getDataGenerator()->create_user($user4);
2658         $user5 = new stdClass();
2659         $user5->firstname = 'User';
2660         $user5->lastname = 'D';
2661         $user5 = self::getDataGenerator()->create_user($user5);
2663         // Add some users as contacts.
2664         \core_message\api::add_contact($user1->id, $user2->id);
2665         \core_message\api::add_contact($user1->id, $user3->id);
2666         \core_message\api::add_contact($user1->id, $user4->id);
2668         // Retrieve the contacts.
2669         $result = core_message_external::get_user_contacts($user1->id);
2671         // We need to execute the return values cleaning process to simulate the web service server.
2672         $result = external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(),
2673             $result);
2675         // Confirm the data is correct.
2676         $contacts = $result;
2677         usort($contacts, ['static', 'sort_contacts_id']);
2678         $this->assertCount(3, $contacts);
2680         $contact1 = array_shift($contacts);
2681         $contact2 = array_shift($contacts);
2682         $contact3 = array_shift($contacts);
2684         $this->assertEquals($user2->id, $contact1['id']);
2685         $this->assertEquals(fullname($user2), $contact1['fullname']);
2686         $this->assertTrue($contact1['iscontact']);
2688         $this->assertEquals($user3->id, $contact2['id']);
2689         $this->assertEquals(fullname($user3), $contact2['fullname']);
2690         $this->assertTrue($contact2['iscontact']);
2692         $this->assertEquals($user4->id, $contact3['id']);
2693         $this->assertEquals(fullname($user4), $contact3['fullname']);
2694         $this->assertTrue($contact3['iscontact']);
2695     }
2697     /**
2698      * Tests retrieving contacts as another user without the proper capabilities.
2699      */
2700     public function test_get_user_contacts_as_other_user_without_cap() {
2701         $this->resetAfterTest(true);
2703         // Create some users.
2704         $user1 = self::getDataGenerator()->create_user();
2705         $user2 = self::getDataGenerator()->create_user();
2707         // The person retrieving the contacts for another user.
2708         $this->setUser($user1);
2710         // Perform the WS call and ensure an exception is thrown.
2711         $this->expectException('moodle_exception');
2712         core_message_external::get_user_contacts($user2->id);
2713     }
2715     /**
2716      * Tests retrieving contacts with messaging disabled.
2717      */
2718     public function test_get_user_contacts_messaging_disabled() {
2719         global $CFG;
2721         $this->resetAfterTest(true);
2723         // Create some skeleton data just so we can call the WS.
2724         $user = self::getDataGenerator()->create_user();
2726         // The person retrieving the contacts.
2727         $this->setUser($user);
2729         // Disable messaging.
2730         $CFG->messaging = 0;
2732         // Perform the WS call and ensure we are shown that it is disabled.
2733         $this->expectException('moodle_exception');
2734         core_message_external::get_user_contacts($user->id);
2735     }
2737     /**
2738      * Test getting contacts when there are no results.
2739      */
2740     public function test_get_user_contacts_no_results() {
2741         $this->resetAfterTest();
2743         $user1 = self::getDataGenerator()->create_user();
2745         $this->setUser($user1);
2747         $requests = core_message_external::get_user_contacts($user1->id);
2748         $requests = external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), $requests);
2750         $this->assertEmpty($requests);
2751     }
2753     /**
2754      * Tests get_conversation_messages for retrieving messages.
2755      */
2756     public function test_get_conversation_messages() {
2757         $this->resetAfterTest(true);
2759         // Create some users.
2760         $user1 = self::getDataGenerator()->create_user();
2761         $user2 = self::getDataGenerator()->create_user();
2762         $user3 = self::getDataGenerator()->create_user();
2763         $user4 = self::getDataGenerator()->create_user();
2764         $user5 = self::getDataGenerator()->create_user();
2766         // Create group conversation.
2767         $conversation = \core_message\api::create_conversation(
2768             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2769             [$user1->id, $user2->id, $user3->id, $user4->id]
2770         );
2772         // The person asking for the messages.
2773         $this->setUser($user1);
2775         // Send some messages back and forth.
2776         $time = time();
2777         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time);
2778         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1);
2779         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2);
2780         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3);
2782         // Retrieve the messages.
2783         $result = core_message_external::get_conversation_messages($user1->id, $conversation->id);
2785         // We need to execute the return values cleaning process to simulate the web service server.
2786         $result = external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(),
2787             $result);
2789         // Check the results are correct.
2790         $this->assertEquals($conversation->id, $result['id']);
2792         // Confirm the members data is correct.
2793         $members = $result['members'];
2794         $this->assertCount(3, $members);
2795         $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']];
2796         $this->assertContains($user1->id, $membersid);
2797         $this->assertContains($user2->id, $membersid);
2798         $this->assertContains($user3->id, $membersid);
2800         $membersfullnames = [$members[0]['fullname'], $members[1]['fullname'], $members[2]['fullname']];
2801         $this->assertContains(fullname($user1), $membersfullnames);
2802         $this->assertContains(fullname($user2), $membersfullnames);
2803         $this->assertContains(fullname($user3), $membersfullnames);
2805         // Confirm the messages data is correct.
2806         $messages = $result['messages'];
2807         $this->assertCount(4, $messages);
2809         $message1 = $messages[0];
2810         $message2 = $messages[1];
2811         $message3 = $messages[2];
2812         $message4 = $messages[3];
2814         $this->assertEquals($user1->id, $message1['useridfrom']);
2815         $this->assertStringContainsString('Yo!', $message1['text']);
2817         $this->assertEquals($user3->id, $message2['useridfrom']);
2818         $this->assertStringContainsString('Sup mang?', $message2['text']);
2820         $this->assertEquals($user2->id, $message3['useridfrom']);
2821         $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']);
2823         $this->assertEquals($user1->id, $message4['useridfrom']);
2824         $this->assertStringContainsString('Word.', $message4['text']);
2825     }
2827     /**
2828      * Tests get_conversation_messages for retrieving messages using timefrom parameter.
2829      */
2830     public function test_get_conversation_messages_timefrom() {
2831         $this->resetAfterTest(true);
2833         // Create some users.
2834         $user1 = self::getDataGenerator()->create_user();
2835         $user2 = self::getDataGenerator()->create_user();
2836         $user3 = self::getDataGenerator()->create_user();
2837         $user4 = self::getDataGenerator()->create_user();
2839         // Create group conversation.
2840         $conversation = \core_message\api::create_conversation(
2841             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2842             [$user1->id, $user2->id, $user3->id]
2843         );
2845         // The person asking for the messages.
2846         $this->setUser($user1);
2848         // Send some messages back and forth.
2849         $time = time();
2850         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time - 4);
2851         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time - 3);
2852         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 3', $time - 2);
2853         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 4', $time - 1);
2855         // Retrieve the messages from $time - 3, which should be the 3 most recent messages.
2856         $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, false, $time - 3);
2858         // We need to execute the return values cleaning process to simulate the web service server.
2859         $result = external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(),
2860             $result);
2862         // Check the results are correct.
2863         $this->assertEquals($conversation->id, $result['id']);
2865         // Confirm the messages data is correct.
2866         $messages = $result['messages'];
2867         $this->assertCount(3, $messages);
2869         $message1 = $messages[0];
2870         $message2 = $messages[1];
2871         $message3 = $messages[2];
2873         $this->assertStringContainsString('Message 2', $message1['text']);
2874         $this->assertStringContainsString('Message 3', $message2['text']);
2875         $this->assertStringContainsString('Message 4', $message3['text']);
2877         // Confirm the members data is correct.
2878         $members = $result['members'];
2879         $this->assertCount(1, $members);
2880         $this->assertEquals($user2->id, $members[0]['id']);
2881     }
2883     /**
2884      * Tests get_conversation_messages for retrieving messages as another user.
2885      */
2886     public function test_get_conversation_messages_as_other_user() {
2887         $this->resetAfterTest(true);
2889         // Set as admin.
2890         $this->setAdminUser();
2892         // Create some users.
2893         $user1 = self::getDataGenerator()->create_user();
2894         $user2 = self::getDataGenerator()->create_user();
2895         $user3 = self::getDataGenerator()->create_user();
2896         $user4 = self::getDataGenerator()->create_user();
2898         // Create group conversation.
2899         $conversation = \core_message\api::create_conversation(
2900             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2901             [$user1->id, $user2->id, $user3->id, $user4->id]
2902         );
2904         // Send some messages back and forth.
2905         $time = time();
2906         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time);
2907         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1);
2908         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2);
2909         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3);
2911         // Retrieve the messages.
2912         $result = core_message_external::get_conversation_messages($user1->id, $conversation->id);
2914         // We need to execute the return values cleaning process to simulate the web service server.
2915         $result = external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(),
2916             $result);
2918         // Check the results are correct.
2919         $this->assertEquals($conversation->id, $result['id']);
2921         // Confirm the members data is correct.
2922         $members = $result['members'];
2923         $this->assertCount(3, $members);
2924         $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']];
2925         $this->assertContains($user1->id, $membersid);
2926         $this->assertContains($user2->id, $membersid);
2927         $this->assertContains($user3->id, $membersid);
2929         // Confirm the message data is correct.
2930         $messages = $result['messages'];
2931         $this->assertCount(4, $messages);
2933         $message1 = $messages[0];
2934         $message2 = $messages[1];
2935         $message3 = $messages[2];
2936         $message4 = $messages[3];
2938         $this->assertEquals($user1->id, $message1['useridfrom']);
2939         $this->assertStringContainsString('Yo!', $message1['text']);
2941         $this->assertEquals($user3->id, $message2['useridfrom']);
2942         $this->assertStringContainsString('Sup mang?', $message2['text']);
2944         $this->assertEquals($user2->id, $message3['useridfrom']);
2945         $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']);
2947         $this->assertEquals($user1->id, $message4['useridfrom']);
2948         $this->assertStringContainsString('Word.', $message4['text']);
2949     }
2951     /**
2952      * Tests get_conversation_messages for retrieving messages as another user without the proper capabilities.
2953      */
2954     public function test_get_conversation_messages_as_other_user_without_cap() {
2955         $this->resetAfterTest(true);
2957         // Create some users.
2958         $user1 = self::getDataGenerator()->create_user();
2959         $user2 = self::getDataGenerator()->create_user();
2960         $user3 = self::getDataGenerator()->create_user();
2961         $user4 = self::getDataGenerator()->create_user();
2963         // Create group conversation.
2964         $conversation = \core_message\api::create_conversation(
2965             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2966             [$user1->id, $user2->id, $user3->id, $user4->id]
2967         );
2969         // The person asking for the messages for another user.
2970         $this->setUser($user1);
2972         // Ensure an exception is thrown.
2973         $this->expectException('moodle_exception');
2974         core_message_external::get_conversation_messages($user2->id, $conversation->id);
2975     }
2977     /**
2978      * Tests get_conversation_messages for retrieving messages as another user not in the conversation.
2979      */
2980     public function test_get_conversation_messages_as_user_not_in_conversation() {
2981         $this->resetAfterTest(true);
2983         // Create some users.
2984         $user1 = self::getDataGenerator()->create_user();
2985         $user2 = self::getDataGenerator()->create_user();
2986         $user3 = self::getDataGenerator()->create_user(); // Not in group.
2988         // Create group conversation.
2989         $conversation = \core_message\api::create_conversation(
2990             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2991             [$user1->id, $user2->id]
2992         );
2994         // The person asking for the messages for a conversation he does not belong to.
2995         $this->setUser($user3);
2997         // Ensure an exception is thrown.
2998         $this->expectExceptionMessage('User is not part of conversation.');
2999         core_message_external::get_conversation_messages($user3->id, $conversation->id);
3000     }
3002     /**
3003      * Tests get_conversation_messages for retrieving messages with messaging disabled.
3004      */
3005     public function test_get_conversation_messages_messaging_disabled() {
3006         $this->resetAfterTest(true);
3008         // Create some skeleton data just so we can call the WS.
3009         $user1 = self::getDataGenerator()->create_user();
3010         $user2 = self::getDataGenerator()->create_user();
3011         $user3 = self::getDataGenerator()->create_user();
3012         $user4 = self::getDataGenerator()->create_user();
3014         // Create group conversation.
3015         $conversation = \core_message\api::create_conversation(
3016             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3017             [$user1->id, $user2->id, $user3->id, $user4->id]
3018         );
3020         // The person asking for the messages for another user.
3021         $this->setUser($user1);
3023         // Disable messaging.
3024         set_config('messaging', 0);
3026         // Ensure an exception is thrown.
3027         $this->expectException('moodle_exception');
3028         core_message_external::get_conversation_messages($user1->id, $conversation->id);
3029     }
3031     /**
3032      * Test marking all conversation messages as read with an invalid user.
3033      */
3034     public function test_mark_all_conversation_messages_as_read_invalid_user_exception() {
3035         $this->resetAfterTest(true);
3037         $user1 = self::getDataGenerator()->create_user();
3038         $user2 = self::getDataGenerator()->create_user();
3040         // Send some messages back and forth.
3041         $time = time();
3042         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3043         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3044         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3045         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3047         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3049         $this->expectException('moodle_exception');
3050         core_message_external::mark_all_conversation_messages_as_read(-2132131, $conversationid);
3051     }
3053     /**
3054      * Test marking all conversation messages as read without proper access.
3055      */
3056     public function test_mark_all_conversation_messages_as_read_access_denied_exception() {
3057         $this->resetAfterTest(true);
3059         $user1 = self::getDataGenerator()->create_user();
3060         $user2 = self::getDataGenerator()->create_user();
3061         $user3 = self::getDataGenerator()->create_user();
3063         // Send some messages back and forth.
3064         $time = time();
3065         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3066         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3067         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3068         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3070         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3072         // User 3 is not in the conversation.
3073         $this->expectException('moodle_exception');
3074         core_message_external::mark_all_conversation_messages_as_read($user3->id, $conversationid);
3075     }
3077     /**
3078      * Test marking all conversation messages as read for another user.
3079      */
3080     public function test_mark_all_conversation_messages_as_read_wrong_user() {
3081         $this->resetAfterTest(true);
3083         $user1 = self::getDataGenerator()->create_user();
3084         $user2 = self::getDataGenerator()->create_user();
3086         // Send some messages back and forth.
3087         $time = time();
3088         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3089         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3090         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3091         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3093         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3095         // Can't mark the messages as read for user 2.
3096         $this->setUser($user1);
3097         $this->expectException('moodle_exception');
3098         core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid);
3099     }
3101     /**
3102      * Test marking all conversation messages as admin.
3103      */
3104     public function test_mark_all_conversation_messages_as_admin() {
3105         global $DB;
3107         $this->resetAfterTest(true);
3109         $user1 = self::getDataGenerator()->create_user();
3110         $user2 = self::getDataGenerator()->create_user();
3112         // Send some messages back and forth.
3113         $time = time();
3114         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3115         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3116         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3117         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3119         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3121         // Admin can do anything.
3122         $this->setAdminUser();
3123         core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid);
3124         $this->assertEquals(2, $DB->count_records('message_user_actions'));
3125     }
3127     /**
3128      * Test marking all conversation messages.
3129      */
3130     public function test_mark_all_conversation_messages_as_read() {
3131         global $DB;
3133         $this->resetAfterTest(true);
3135         $user1 = self::getDataGenerator()->create_user();
3136         $user2 = self::getDataGenerator()->create_user();
3138         // Send some messages back and forth.
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         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3145         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3147         // We are the user we want to mark the messages for and we are in the conversation, all good.
3148         $this->setUser($user1);
3149         core_message_external::mark_all_conversation_messages_as_read($user1->id, $conversationid);
3150         $this->assertEquals(2, $DB->count_records('message_user_actions'));
3151     }
3153     /**
3154      * Test getting unread conversation count.
3155      */
3156     public function test_get_unread_conversations_count() {
3157         $this->resetAfterTest(true);
3159         // Create some users.
3160         $user1 = self::getDataGenerator()->create_user();
3161         $user2 = self::getDataGenerator()->create_user();
3162         $user3 = self::getDataGenerator()->create_user();
3163         $user4 = self::getDataGenerator()->create_user();
3165         // The person wanting the conversation count.
3166         $this->setUser($user1);
3168         // Send some messages back and forth, have some different conversations with different users.
3169         $this->send_message($user1, $user2, 'Yo!');
3170         $this->send_message($user2, $user1, 'Sup mang?');
3171         $this->send_message($user1, $user2, 'Writing PHPUnit tests!');
3172         $this->send_message($user2, $user1, 'Word.');
3174         $this->send_message($user1, $user3, 'Booyah');
3175         $this->send_message($user3, $user1, 'Whaaat?');
3176         $this->send_message($user1, $user3, 'Nothing.');
3177         $this->send_message($user3, $user1, 'Cool.');
3179         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3180         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3181         $this->send_message($user1, $user4, 'Dope.');
3183         // Get the unread conversation count.
3184         $result = core_message_external::get_unread_conversations_count($user1->id);
3186         // We need to execute the return values cleaning process to simulate the web service server.
3187         $result = external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(),
3188             $result);
3190         $this->assertEquals(3, $result);
3191     }
3193     /**
3194      * Test getting unread conversation count as other user.
3195      */
3196     public function test_get_unread_conversations_count_as_other_user() {
3197         $this->resetAfterTest(true);
3199         // The person wanting the conversation count.
3200         $this->setAdminUser();
3202         // Create some users.
3203         $user1 = self::getDataGenerator()->create_user();
3204         $user2 = self::getDataGenerator()->create_user();
3205         $user3 = self::getDataGenerator()->create_user();
3206         $user4 = self::getDataGenerator()->create_user();
3208         // Send some messages back and forth, have some different conversations with different users.
3209         $this->send_message($user1, $user2, 'Yo!');
3210         $this->send_message($user2, $user1, 'Sup mang?');
3211         $this->send_message($user1, $user2, 'Writing PHPUnit tests!');
3212         $this->send_message($user2, $user1, 'Word.');
3214         $this->send_message($user1, $user3, 'Booyah');
3215         $this->send_message($user3, $user1, 'Whaaat?');
3216         $this->send_message($user1, $user3, 'Nothing.');
3217         $this->send_message($user3, $user1, 'Cool.');
3219         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3220         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3221         $this->send_message($user1, $user4, 'Dope.');
3223         // Get the unread conversation count.
3224         $result = core_message_external::get_unread_conversations_count($user1->id);
3226         // We need to execute the return values cleaning process to simulate the web service server.
3227         $result = external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(),
3228             $result);
3230         $this->assertEquals(3, $result);
3231     }
3233     /**
3234      * Test getting unread conversation count as other user without proper capability.
3235      */
3236     public function test_get_unread_conversations_count_as_other_user_without_cap() {
3237         $this->resetAfterTest(true);
3239         // Create some users.
3240         $user1 = self::getDataGenerator()->create_user();
3241         $user2 = self::getDataGenerator()->create_user();
3243         // The person wanting the conversation count.
3244         $this->setUser($user1);
3246         // Ensure an exception is thrown.
3247         $this->expectException('moodle_exception');
3248         core_message_external::get_unread_conversations_count($user2->id);
3249     }
3251     /**
3252      * Test deleting conversations.
3253      */
3254     public function test_delete_conversations_by_id() {
3255         global $DB;
3257         $this->resetAfterTest(true);
3259         // Create some users.
3260         $user1 = self::getDataGenerator()->create_user();
3261         $user2 = self::getDataGenerator()->create_user();
3263         // The person wanting to delete the conversation.
3264         $this->setUser($user1);
3266         // Send some messages back and forth.
3267         $time = time();
3268         $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time);
3269         $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3270         $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3271         $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3273         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3275         // Delete the conversation.
3276         core_message_external::delete_conversations_by_id($user1->id, [$conversationid]);
3278         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3279         $this->assertCount(4, $muas);
3280         // Sort by id.
3281         ksort($muas);
3283         $mua1 = array_shift($muas);
3284         $mua2 = array_shift($muas);
3285         $mua3 = array_shift($muas);
3286         $mua4 = array_shift($muas);
3288         $this->assertEquals($user1->id, $mua1->userid);
3289         $this->assertEquals($m1id, $mua1->messageid);
3290         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3292         $this->assertEquals($user1->id, $mua2->userid);
3293         $this->assertEquals($m2id, $mua2->messageid);
3294         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
3296         $this->assertEquals($user1->id, $mua3->userid);
3297         $this->assertEquals($m3id, $mua3->messageid);
3298         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
3300         $this->assertEquals($user1->id, $mua4->userid);
3301         $this->assertEquals($m4id, $mua4->messageid);
3302         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
3303     }
3305     /**
3306      * Test deleting conversations as other user.
3307      */
3308     public function test_delete_conversations_by_id_as_other_user() {
3309         global $DB;
3311         $this->resetAfterTest(true);
3313         $this->setAdminUser();
3315         // Create some users.
3316         $user1 = self::getDataGenerator()->create_user();
3317         $user2 = self::getDataGenerator()->create_user();
3319         // Send some messages back and forth.
3320         $time = time();
3321         $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time);
3322         $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3323         $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3324         $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3326         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3328         // Delete the conversation.
3329         core_message_external::delete_conversations_by_id($user1->id, [$conversationid]);
3331         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3332         $this->assertCount(4, $muas);
3333         // Sort by id.
3334         ksort($muas);
3336         $mua1 = array_shift($muas);
3337         $mua2 = array_shift($muas);
3338         $mua3 = array_shift($muas);
3339         $mua4 = array_shift($muas);
3341         $this->assertEquals($user1->id, $mua1->userid);
3342         $this->assertEquals($m1id, $mua1->messageid);
3343         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3345         $this->assertEquals($user1->id, $mua2->userid);
3346         $this->assertEquals($m2id, $mua2->messageid);
3347         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
3349         $this->assertEquals($user1->id, $mua3->userid);
3350         $this->assertEquals($m3id, $mua3->messageid);
3351         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
3353         $this->assertEquals($user1->id, $mua4->userid);
3354         $this->assertEquals($m4id, $mua4->messageid);
3355         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
3356     }
3358     /**
3359      * Test deleting conversations as other user without proper capability.
3360      */
3361     public function test_delete_conversations_by_id_as_other_user_without_cap() {
3362         $this->resetAfterTest(true);
3364         // Create some users.
3365         $user1 = self::getDataGenerator()->create_user();
3366         $user2 = self::getDataGenerator()->create_user();
3367         $user3 = self::getDataGenerator()->create_user();
3369         // Send some messages back and forth.
3370         $time = time();
3371         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3372         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3373         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3374         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3376         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3378         // The person wanting to delete the conversation.
3379         $this->setUser($user3);
3381         // Ensure an exception is thrown.
3382         $this->expectException('moodle_exception');
3383         core_message_external::delete_conversations_by_id($user1->id, [$conversationid]);
3384     }
3386     /**
3387      * Test deleting conversations with messaging disabled.
3388      */
3389     public function test_delete_conversations_by_id_messaging_disabled() {
<