Merge branch 'MDL-72585-master' of git://github.com/dpalou/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 with a message text longer than permitted.
160      */
161     public function test_send_instant_messages_long_text() {
162         global $CFG;
164         $this->resetAfterTest(true);
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         // Create test message data.
175         $message1 = [
176             'touserid' => $user2->id,
177             'text' => str_repeat("M", \core_message\api::MESSAGE_MAX_LENGTH + 100),
178             'clientmsgid' => 4,
179         ];
180         $messages = [$message1];
182         // Add the user1 as a contact.
183         \core_message\api::add_contact($user1->id, $user2->id);
185         $sentmessages = core_message_external::send_instant_messages($messages);
186         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
187         $this->assertEquals(
188             get_string('errormessagetoolong', 'message'),
189             array_pop($sentmessages)['errormessage']
190         );
191     }
193     /**
194      * Test send_instant_messages to a user who has blocked you.
195      */
196     public function test_send_instant_messages_blocked_user() {
197         global $DB;
199         $this->resetAfterTest();
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         \core_message\api::block_user($user2->id, $user1->id);
211         // Create test message data.
212         $message1 = array();
213         $message1['touserid'] = $user2->id;
214         $message1['text'] = 'the message.';
215         $message1['clientmsgid'] = 4;
216         $messages = array($message1);
218         $sentmessages = core_message_external::send_instant_messages($messages);
219         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
221         $sentmessage = reset($sentmessages);
223         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
225         $this->assertEquals(0, $DB->count_records('messages'));
226     }
228     /**
229      * Test send_instant_messages when sending a message to a non-contact who has blocked non-contacts.
230      */
231     public function test_send_instant_messages_block_non_contacts() {
232         global $DB;
234         $this->resetAfterTest(true);
236         // Transactions used in tests, tell phpunit use alternative reset method.
237         $this->preventResetByRollback();
239         $user1 = self::getDataGenerator()->create_user();
240         $user2 = self::getDataGenerator()->create_user();
242         $this->setUser($user1);
244         // Set the user preference so user 2 does not accept messages from non-contacts.
245         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
247         // Create test message data.
248         $message1 = array();
249         $message1['touserid'] = $user2->id;
250         $message1['text'] = 'the message.';
251         $message1['clientmsgid'] = 4;
252         $messages = array($message1);
254         $sentmessages = core_message_external::send_instant_messages($messages);
255         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
257         $sentmessage = reset($sentmessages);
259         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
261         $this->assertEquals(0, $DB->count_records('messages'));
262     }
264     /**
265      * Test send_instant_messages when sending a message to a contact who has blocked non-contacts.
266      */
267     public function test_send_instant_messages_block_non_contacts_but_am_contact() {
268         global $DB, $USER;
270         $this->resetAfterTest(true);
272         // Transactions used in tests, tell phpunit use alternative reset method.
273         $this->preventResetByRollback();
275         $user1 = self::getDataGenerator()->create_user();
276         $user2 = self::getDataGenerator()->create_user();
278         $this->setUser($user1);
280         // Set the user preference so user 2 does not accept messages from non-contacts.
281         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
283         \core_message\api::add_contact($user1->id, $user2->id);
285         // Create test message data.
286         $message1 = array();
287         $message1['touserid'] = $user2->id;
288         $message1['text'] = 'the message.';
289         $message1['clientmsgid'] = 4;
290         $messages = array($message1);
292         $sentmessages = core_message_external::send_instant_messages($messages);
293         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
295         $sentmessage = reset($sentmessages);
297         $sql = "SELECT m.*, mcm.userid as useridto
298                  FROM {messages} m
299            INNER JOIN {message_conversations} mc
300                    ON m.conversationid = mc.id
301            INNER JOIN {message_conversation_members} mcm
302                    ON mcm.conversationid = mc.id
303                 WHERE mcm.userid != ?
304                   AND m.id = ?";
305         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
307         // Confirm that the message was inserted correctly.
308         $this->assertEquals($themessage->useridfrom, $user1->id);
309         $this->assertEquals($themessage->useridto, $message1['touserid']);
310         $this->assertEquals($themessage->smallmessage, $message1['text']);
311         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
312     }
314     /**
315      * Test send_instant_messages with no capabilities
316      */
317     public function test_send_instant_messages_no_capability() {
318         global $DB;
320         $this->resetAfterTest(true);
322         // Transactions used in tests, tell phpunit use alternative reset method.
323         $this->preventResetByRollback();
325         $user1 = self::getDataGenerator()->create_user();
326         $user2 = self::getDataGenerator()->create_user();
328         $this->setUser($user1);
330         // Unset the required capabilities by the external function.
331         $contextid = context_system::instance()->id;
332         $userrole = $DB->get_record('role', array('shortname' => 'user'));
333         $this->unassignUserCapability('moodle/site:sendmessage', $contextid, $userrole->id);
335         // Create test message data.
336         $message1 = array();
337         $message1['touserid'] = $user2->id;
338         $message1['text'] = 'the message.';
339         $message1['clientmsgid'] = 4;
340         $messages = array($message1);
342         $this->expectException('required_capability_exception');
343         core_message_external::send_instant_messages($messages);
344     }
346     /**
347      * Test send_instant_messages when messaging is disabled.
348      */
349     public function test_send_instant_messages_messaging_disabled() {
350         global $CFG;
352         $this->resetAfterTest(true);
354         // Transactions used in tests, tell phpunit use alternative reset method.
355         $this->preventResetByRollback();
357         $user1 = self::getDataGenerator()->create_user();
358         $user2 = self::getDataGenerator()->create_user();
360         $this->setUser($user1);
362         // Disable messaging.
363         $CFG->messaging = 0;
365         // Create test message data.
366         $message1 = array();
367         $message1['touserid'] = $user2->id;
368         $message1['text'] = 'the message.';
369         $message1['clientmsgid'] = 4;
370         $messages = array($message1);
372         $this->expectException('moodle_exception');
373         core_message_external::send_instant_messages($messages);
374     }
376     /**
377      * Test delete_contacts.
378      */
379     public function test_delete_contacts() {
380         $this->resetAfterTest(true);
382         $user1 = self::getDataGenerator()->create_user();
383         $user2 = self::getDataGenerator()->create_user();
384         $user3 = self::getDataGenerator()->create_user();
385         $user4 = self::getDataGenerator()->create_user();
386         $user5 = self::getDataGenerator()->create_user();
387         $user6 = self::getDataGenerator()->create_user();
388         $this->setUser($user1);
390         \core_message\api::add_contact($user1->id, $user3->id);
391         \core_message\api::add_contact($user1->id, $user4->id);
392         \core_message\api::add_contact($user1->id, $user5->id);
393         \core_message\api::add_contact($user1->id, $user6->id);
395         // Removing a non-contact.
396         $return = core_message_external::delete_contacts(array($user2->id));
397         $this->assertNull($return);
399         // Removing one contact.
400         $return = core_message_external::delete_contacts(array($user3->id));
401         $this->assertNull($return);
403         // Removing multiple contacts.
404         $return = core_message_external::delete_contacts(array($user4->id, $user5->id));
405         $this->assertNull($return);
407         // Removing contact from unexisting user.
408         $return = core_message_external::delete_contacts(array(99999));
409         $this->assertNull($return);
411         // Removing mixed valid and invalid data.
412         $return = core_message_external::delete_contacts(array($user6->id, 99999));
413         $this->assertNull($return);
415         // Try to delete a contact of another user contact list, should throw an exception.
416         // All assertions must be added before this point.
417         $this->expectException('required_capability_exception');
418         core_message_external::delete_contacts(array($user2->id), $user3->id);
419     }
421     /**
422      * Test getting contact requests.
423      */
424     public function test_get_contact_requests() {
425         global $PAGE;
427         $this->resetAfterTest();
429         $user1 = self::getDataGenerator()->create_user();
430         $user2 = self::getDataGenerator()->create_user();
431         $user3 = self::getDataGenerator()->create_user();
433         $this->setUser($user1);
435         // Block one user, their request should not show up.
436         \core_message\api::block_user($user1->id, $user3->id);
438         \core_message\api::create_contact_request($user2->id, $user1->id);
439         \core_message\api::create_contact_request($user3->id, $user1->id);
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(1, $requests);
446         $request = reset($requests);
447         $userpicture = new \user_picture($user2);
448         $profileimageurl = $userpicture->get_url($PAGE)->out(false);
450         $this->assertEquals($user2->id, $request['id']);
451         $this->assertEquals(fullname($user2), $request['fullname']);
452         $this->assertArrayHasKey('profileimageurl', $request);
453         $this->assertArrayHasKey('profileimageurlsmall', $request);
454         $this->assertArrayHasKey('isonline', $request);
455         $this->assertArrayHasKey('showonlinestatus', $request);
456         $this->assertArrayHasKey('isblocked', $request);
457         $this->assertArrayHasKey('iscontact', $request);
458     }
460     /**
461      * Test the get_contact_requests() function when the user has blocked the sender of the request.
462      */
463     public function test_get_contact_requests_blocked_sender() {
464         $this->resetAfterTest();
465         $user1 = self::getDataGenerator()->create_user();
466         $user2 = self::getDataGenerator()->create_user();
468         // User1 blocks User2.
469         \core_message\api::block_user($user1->id, $user2->id);
471         // User2 tries to add User1 as a contact.
472         \core_message\api::create_contact_request($user2->id, $user1->id);
474         // Verify we don't see the contact request from the blocked user User2 in the requests for User1.
475         $this->setUser($user1);
476         $requests = core_message_external::get_contact_requests($user1->id);
477         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
479         $this->assertCount(0, $requests);
480     }
482     /**
483      * Test getting contact requests when there are none.
484      */
485     public function test_get_contact_requests_no_requests() {
486         $this->resetAfterTest();
488         $user1 = self::getDataGenerator()->create_user();
490         $this->setUser($user1);
492         $requests = core_message_external::get_contact_requests($user1->id);
493         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
495         $this->assertEmpty($requests);
496     }
498     /**
499      * Test getting contact requests with limits.
500      */
501     public function test_get_contact_requests_with_limits() {
502         $this->resetAfterTest();
504         $user1 = self::getDataGenerator()->create_user();
505         $user2 = self::getDataGenerator()->create_user();
506         $user3 = self::getDataGenerator()->create_user();
508         $this->setUser($user1);
510         \core_message\api::create_contact_request($user2->id, $user1->id);
511         \core_message\api::create_contact_request($user3->id, $user1->id);
513         $requests = core_message_external::get_contact_requests($user1->id, 0, 1);
514         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
516         $this->assertCount(1, $requests);
517     }
519     /**
520      * Test getting contact requests with messaging disabled.
521      */
522     public function test_get_contact_requests_messaging_disabled() {
523         global $CFG;
525         $this->resetAfterTest();
527         // Create some skeleton data just so we can call the WS.
528         $user1 = self::getDataGenerator()->create_user();
530         $this->setUser($user1);
532         // Disable messaging.
533         $CFG->messaging = 0;
535         // Ensure an exception is thrown.
536         $this->expectException('moodle_exception');
537         core_message_external::get_contact_requests($user1->id);
538     }
540     /**
541      * Test getting contact requests with no permission.
542      */
543     public function test_get_contact_requests_no_permission() {
544         $this->resetAfterTest();
546         // Create some skeleton data just so we can call the WS.
547         $user1 = self::getDataGenerator()->create_user();
548         $user2 = self::getDataGenerator()->create_user();
549         $user3 = self::getDataGenerator()->create_user();
551         $this->setUser($user3);
553         // Ensure an exception is thrown.
554         $this->expectException('required_capability_exception');
555         core_message_external::create_contact_request($user1->id, $user2->id);
556     }
558     /**
559      * Test getting the number of received contact requests.
560      */
561     public function test_get_received_contact_requests_count() {
562         $this->resetAfterTest();
564         $user1 = self::getDataGenerator()->create_user();
565         $user2 = self::getDataGenerator()->create_user();
566         $user3 = self::getDataGenerator()->create_user();
567         $user4 = self::getDataGenerator()->create_user();
569         $this->setUser($user1);
571         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
572         $contactrequestnumber = external_api::clean_returnvalue(
573             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
574         $this->assertEquals(0, $contactrequestnumber);
576         \core_message\api::create_contact_request($user2->id, $user1->id);
578         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
579         $contactrequestnumber = external_api::clean_returnvalue(
580             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
581         $this->assertEquals(1, $contactrequestnumber);
583         \core_message\api::create_contact_request($user3->id, $user1->id);
585         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
586         $contactrequestnumber = external_api::clean_returnvalue(
587             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
588         $this->assertEquals(2, $contactrequestnumber);
590         \core_message\api::create_contact_request($user1->id, $user4->id);
592         // Web service should ignore sent requests.
593         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
594         $contactrequestnumber = external_api::clean_returnvalue(
595             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
596         $this->assertEquals(2, $contactrequestnumber);
597     }
599     /**
600      * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request.
601      */
602     public function test_get_received_contact_requests_count_blocked_sender() {
603         $this->resetAfterTest();
604         $user1 = self::getDataGenerator()->create_user();
605         $user2 = self::getDataGenerator()->create_user();
607         // User1 blocks User2.
608         \core_message\api::block_user($user1->id, $user2->id);
610         // User2 tries to add User1 as a contact.
611         \core_message\api::create_contact_request($user2->id, $user1->id);
613         // Verify we don't see the contact request from the blocked user User2 in the count for User1.
614         $this->setUser($user1);
615         $contactrequestnumber = core_message_external::get_received_contact_requests_count($user1->id);
616         $contactrequestnumber = external_api::clean_returnvalue(
617             core_message_external::get_received_contact_requests_count_returns(), $contactrequestnumber);
618         $this->assertEquals(0, $contactrequestnumber);
619     }
621     /**
622      * Test getting the number of received contact requests with no permissions.
623      */
624     public function test_get_received_contact_requests_count_no_permission() {
625         $this->resetAfterTest();
627         // Create some skeleton data just so we can call the WS.
628         $user1 = self::getDataGenerator()->create_user();
629         $user2 = self::getDataGenerator()->create_user();
631         $this->setUser($user2);
633         // Ensure an exception is thrown.
634         $this->expectException('required_capability_exception');
635         core_message_external::get_received_contact_requests_count($user1->id);
636     }
638     /**
639      * Test getting the number of received contact requests with messaging disabled.
640      */
641     public function test_get_received_contact_requests_count_messaging_disabled() {
642         global $CFG;
644         $this->resetAfterTest();
646         // Create some skeleton data just so we can call the WS.
647         $user1 = self::getDataGenerator()->create_user();
649         $this->setUser($user1);
651         // Disable messaging.
652         $CFG->messaging = 0;
654         // Ensure an exception is thrown.
655         $this->expectException('moodle_exception');
656         core_message_external::get_received_contact_requests_count($user1->id);
657     }
659     /**
660      * Test creating a contact request.
661      */
662     public function test_create_contact_request() {
663         global $CFG, $DB;
665         $this->resetAfterTest();
667         $user1 = self::getDataGenerator()->create_user();
668         $user2 = self::getDataGenerator()->create_user();
670         $this->setUser($user1);
672         // Allow users to message anyone site-wide.
673         $CFG->messagingallusers = 1;
675         $return = core_message_external::create_contact_request($user1->id, $user2->id);
676         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
677         $this->assertEquals([], $return['warnings']);
679         $request = $DB->get_records('message_contact_requests');
681         $this->assertCount(1, $request);
683         $request = reset($request);
685         $this->assertEquals($request->id, $return['request']['id']);
686         $this->assertEquals($request->userid, $return['request']['userid']);
687         $this->assertEquals($request->requesteduserid, $return['request']['requesteduserid']);
688         $this->assertEquals($request->timecreated, $return['request']['timecreated']);
689     }
691     /**
692      * Test creating a contact request when not allowed.
693      */
694     public function test_create_contact_request_not_allowed() {
695         global $CFG;
697         $this->resetAfterTest();
699         $user1 = self::getDataGenerator()->create_user();
700         $user2 = self::getDataGenerator()->create_user();
702         $this->setUser($user1);
704         $CFG->messagingallusers = 0;
706         $return = core_message_external::create_contact_request($user1->id, $user2->id);
707         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
709         $warning = reset($return['warnings']);
711         $this->assertEquals('user', $warning['item']);
712         $this->assertEquals($user2->id, $warning['itemid']);
713         $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']);
714         $this->assertEquals('You are unable to create a contact request for this user', $warning['message']);
715     }
717     /**
718      * Test creating a contact request with messaging disabled.
719      */
720     public function test_create_contact_request_messaging_disabled() {
721         global $CFG;
723         $this->resetAfterTest();
725         // Create some skeleton data just so we can call the WS.
726         $user1 = self::getDataGenerator()->create_user();
727         $user2 = self::getDataGenerator()->create_user();
729         $this->setUser($user1);
731         // Disable messaging.
732         $CFG->messaging = 0;
734         // Ensure an exception is thrown.
735         $this->expectException('moodle_exception');
736         core_message_external::create_contact_request($user1->id, $user2->id);
737     }
739     /**
740      * Test creating a contact request with no permission.
741      */
742     public function test_create_contact_request_no_permission() {
743         $this->resetAfterTest();
745         // Create some skeleton data just so we can call the WS.
746         $user1 = self::getDataGenerator()->create_user();
747         $user2 = self::getDataGenerator()->create_user();
748         $user3 = self::getDataGenerator()->create_user();
750         $this->setUser($user3);
752         // Ensure an exception is thrown.
753         $this->expectException('required_capability_exception');
754         core_message_external::create_contact_request($user1->id, $user2->id);
755     }
757     /**
758      * Test confirming a contact request.
759      */
760     public function test_confirm_contact_request() {
761         global $DB;
763         $this->resetAfterTest();
765         $user1 = self::getDataGenerator()->create_user();
766         $user2 = self::getDataGenerator()->create_user();
768         $this->setUser($user1);
770         \core_message\api::create_contact_request($user1->id, $user2->id);
772         $this->setUser($user2);
774         $return = core_message_external::confirm_contact_request($user1->id, $user2->id);
775         $return = external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return);
776         $this->assertEquals(array(), $return);
778         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
780         $contact = $DB->get_records('message_contacts');
782         $this->assertCount(1, $contact);
784         $contact = reset($contact);
786         $this->assertEquals($user1->id, $contact->userid);
787         $this->assertEquals($user2->id, $contact->contactid);
788     }
790     /**
791      * Test confirming a contact request with messaging disabled.
792      */
793     public function test_confirm_contact_request_messaging_disabled() {
794         global $CFG;
796         $this->resetAfterTest();
798         // Create some skeleton data just so we can call the WS.
799         $user1 = self::getDataGenerator()->create_user();
800         $user2 = self::getDataGenerator()->create_user();
802         $this->setUser($user1);
804         // Disable messaging.
805         $CFG->messaging = 0;
807         // Ensure an exception is thrown.
808         $this->expectException('moodle_exception');
809         core_message_external::confirm_contact_request($user1->id, $user2->id);
810     }
812     /**
813      * Test confirming a contact request with no permission.
814      */
815     public function test_confirm_contact_request_no_permission() {
816         $this->resetAfterTest();
818         // Create some skeleton data just so we can call the WS.
819         $user1 = self::getDataGenerator()->create_user();
820         $user2 = self::getDataGenerator()->create_user();
821         $user3 = self::getDataGenerator()->create_user();
823         $this->setUser($user3);
825         // Ensure an exception is thrown.
826         $this->expectException('required_capability_exception');
827         core_message_external::confirm_contact_request($user1->id, $user2->id);
828     }
830     /**
831      * Test declining a contact request.
832      */
833     public function test_decline_contact_request() {
834         global $DB;
836         $this->resetAfterTest();
838         $user1 = self::getDataGenerator()->create_user();
839         $user2 = self::getDataGenerator()->create_user();
841         $this->setUser($user1);
843         \core_message\api::create_contact_request($user1->id, $user2->id);
845         $this->setUser($user2);
847         $return = core_message_external::decline_contact_request($user1->id, $user2->id);
848         $return = external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return);
849         $this->assertEquals(array(), $return);
851         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
852         $this->assertEquals(0, $DB->count_records('message_contacts'));
853     }
855     /**
856      * Test declining a contact request with messaging disabled.
857      */
858     public function test_decline_contact_request_messaging_disabled() {
859         global $CFG;
861         $this->resetAfterTest();
863         // Create some skeleton data just so we can call the WS.
864         $user1 = self::getDataGenerator()->create_user();
865         $user2 = self::getDataGenerator()->create_user();
867         $this->setUser($user1);
869         // Disable messaging.
870         $CFG->messaging = 0;
872         // Ensure an exception is thrown.
873         $this->expectException('moodle_exception');
874         core_message_external::decline_contact_request($user1->id, $user2->id);
875     }
877     /**
878      * Test declining a contact request with no permission.
879      */
880     public function test_decline_contact_request_no_permission() {
881         $this->resetAfterTest();
883         // Create some skeleton data just so we can call the WS.
884         $user1 = self::getDataGenerator()->create_user();
885         $user2 = self::getDataGenerator()->create_user();
886         $user3 = self::getDataGenerator()->create_user();
888         $this->setUser($user3);
890         // Ensure an exception is thrown.
891         $this->expectException('required_capability_exception');
892         core_message_external::decline_contact_request($user1->id, $user2->id);
893     }
895     /**
896      * Test muting conversations.
897      */
898     public function test_mute_conversations() {
899         global $DB;
901         $this->resetAfterTest(true);
903         $user1 = self::getDataGenerator()->create_user();
904         $user2 = self::getDataGenerator()->create_user();
906         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
907             [$user1->id, $user2->id]);
909         $this->setUser($user1);
911         // Muting a conversation.
912         $return = core_message_external::mute_conversations($user1->id, [$conversation->id]);
913         $return = external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return);
914         $this->assertEquals(array(), $return);
916         // Get list of muted conversations.
917         $mca = $DB->get_record('message_conversation_actions', []);
919         $this->assertEquals($user1->id, $mca->userid);
920         $this->assertEquals($conversation->id, $mca->conversationid);
921         $this->assertEquals(\core_message\api::CONVERSATION_ACTION_MUTED, $mca->action);
923         // Muting a conversation that is already muted.
924         $return = core_message_external::mute_conversations($user1->id, [$conversation->id]);
925         $return = external_api::clean_returnvalue(core_message_external::mute_conversations_returns(), $return);
926         $this->assertEquals(array(), $return);
928         $this->assertEquals(1, $DB->count_records('message_conversation_actions'));
929     }
931     /**
932      * Test muting a conversation with messaging disabled.
933      */
934     public function test_mute_conversations_messaging_disabled() {
935         global $CFG;
937         $this->resetAfterTest();
939         // Create some skeleton data just so we can call the WS.
940         $user1 = self::getDataGenerator()->create_user();
941         $user2 = self::getDataGenerator()->create_user();
943         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
944             [$user1->id, $user2->id]);
946         $this->setUser($user1);
948         // Disable messaging.
949         $CFG->messaging = 0;
951         // Ensure an exception is thrown.
952         $this->expectException('moodle_exception');
953         core_message_external::mute_conversations($user1->id, [$conversation->id]);
954     }
956     /**
957      * Test muting a conversation with no permission.
958      */
959     public function test_mute_conversations_no_permission() {
960         $this->resetAfterTest();
962         // Create some skeleton data just so we can call the WS.
963         $user1 = self::getDataGenerator()->create_user();
964         $user2 = self::getDataGenerator()->create_user();
965         $user3 = self::getDataGenerator()->create_user();
967         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
968             [$user1->id, $user2->id]);
970         $this->setUser($user3);
972         // Ensure an exception is thrown.
973         $this->expectException('required_capability_exception');
974         core_message_external::mute_conversations($user1->id, [$conversation->id]);
975     }
977     /**
978      * Test unmuting conversations.
979      */
980     public function test_unmute_conversations() {
981         global $DB;
983         $this->resetAfterTest(true);
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         // Mute the conversation.
994         \core_message\api::mute_conversation($user1->id, $conversation->id);
996         // Unmuting a conversation.
997         $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]);
998         $return = external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return);
999         $this->assertEquals(array(), $return);
1001         $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
1003         // Unmuting a conversation which is already unmuted.
1004         $return = core_message_external::unmute_conversations($user1->id, [$conversation->id]);
1005         $return = external_api::clean_returnvalue(core_message_external::unmute_conversations_returns(), $return);
1006         $this->assertEquals(array(), $return);
1008         $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
1009     }
1011     /**
1012      * Test unmuting a conversation with messaging disabled.
1013      */
1014     public function test_unmute_conversation_messaging_disabled() {
1015         global $CFG;
1017         $this->resetAfterTest();
1019         // Create some skeleton data just so we can call the WS.
1020         $user1 = self::getDataGenerator()->create_user();
1021         $user2 = self::getDataGenerator()->create_user();
1023         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1024             [$user1->id, $user2->id]);
1026         $this->setUser($user1);
1028         // Disable messaging.
1029         $CFG->messaging = 0;
1031         // Ensure an exception is thrown.
1032         $this->expectException('moodle_exception');
1033         core_message_external::unmute_conversations($user1->id, [$user2->id]);
1034     }
1036     /**
1037      * Test unmuting a conversation with no permission.
1038      */
1039     public function test_unmute_conversation_no_permission() {
1040         $this->resetAfterTest();
1042         // Create some skeleton data just so we can call the WS.
1043         $user1 = self::getDataGenerator()->create_user();
1044         $user2 = self::getDataGenerator()->create_user();
1045         $user3 = self::getDataGenerator()->create_user();
1047         $conversation = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1048             [$user1->id, $user2->id]);
1050         $this->setUser($user3);
1052         // Ensure an exception is thrown.
1053         $this->expectException('required_capability_exception');
1054         core_message_external::unmute_conversations($user1->id, [$conversation->id]);
1055     }
1057     /**
1058      * Test blocking a user.
1059      */
1060     public function test_block_user() {
1061         global $DB;
1063         $this->resetAfterTest(true);
1065         $user1 = self::getDataGenerator()->create_user();
1066         $user2 = self::getDataGenerator()->create_user();
1068         $this->setUser($user1);
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         // Get list of blocked users.
1076         $record = $DB->get_record('message_users_blocked', []);
1078         $this->assertEquals($user1->id, $record->userid);
1079         $this->assertEquals($user2->id, $record->blockeduserid);
1081         // Blocking a user who is already blocked.
1082         $return = core_message_external::block_user($user1->id, $user2->id);
1083         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1084         $this->assertEquals(array(), $return);
1086         $this->assertEquals(1, $DB->count_records('message_users_blocked'));
1087     }
1089     /**
1090      * Test blocking a user.
1091      */
1092     public function test_block_user_when_ineffective() {
1093         global $DB;
1095         $this->resetAfterTest(true);
1097         $user1 = self::getDataGenerator()->create_user();
1098         $user2 = self::getDataGenerator()->create_user();
1100         $this->setUser($user1);
1102         $authenticateduser = $DB->get_record('role', array('shortname' => 'user'));
1103         assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, context_system::instance(), true);
1105         // Blocking a user.
1106         $return = core_message_external::block_user($user1->id, $user2->id);
1107         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
1108         $this->assertEquals(array(), $return);
1110         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1111     }
1113     /**
1114      * Test blocking a user with messaging disabled.
1115      */
1116     public function test_block_user_messaging_disabled() {
1117         global $CFG;
1119         $this->resetAfterTest();
1121         // Create some skeleton data just so we can call the WS.
1122         $user1 = self::getDataGenerator()->create_user();
1123         $user2 = self::getDataGenerator()->create_user();
1125         $this->setUser($user1);
1127         // Disable messaging.
1128         $CFG->messaging = 0;
1130         // Ensure an exception is thrown.
1131         $this->expectException('moodle_exception');
1132         core_message_external::block_user($user1->id, $user2->id);
1133     }
1135     /**
1136      * Test blocking a user with no permission.
1137      */
1138     public function test_block_user_no_permission() {
1139         $this->resetAfterTest();
1141         // Create some skeleton data just so we can call the WS.
1142         $user1 = self::getDataGenerator()->create_user();
1143         $user2 = self::getDataGenerator()->create_user();
1144         $user3 = self::getDataGenerator()->create_user();
1146         $this->setUser($user3);
1148         // Ensure an exception is thrown.
1149         $this->expectException('required_capability_exception');
1150         core_message_external::block_user($user1->id, $user2->id);
1151     }
1153     /**
1154      * Test unblocking a user.
1155      */
1156     public function test_unblock_user() {
1157         global $DB;
1159         $this->resetAfterTest(true);
1161         $user1 = self::getDataGenerator()->create_user();
1162         $user2 = self::getDataGenerator()->create_user();
1164         $this->setUser($user1);
1166         // Block the user.
1167         \core_message\api::block_user($user1->id, $user2->id);
1169         // Unblocking a user.
1170         $return = core_message_external::unblock_user($user1->id, $user2->id);
1171         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1172         $this->assertEquals(array(), $return);
1174         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1176         // Unblocking a user who is already unblocked.
1177         $return = core_message_external::unblock_user($user1->id, $user2->id);
1178         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1179         $this->assertEquals(array(), $return);
1181         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1182     }
1184     /**
1185      * Test unblocking a user with messaging disabled.
1186      */
1187     public function test_unblock_user_messaging_disabled() {
1188         global $CFG;
1190         $this->resetAfterTest();
1192         // Create some skeleton data just so we can call the WS.
1193         $user1 = self::getDataGenerator()->create_user();
1194         $user2 = self::getDataGenerator()->create_user();
1196         $this->setUser($user1);
1198         // Disable messaging.
1199         $CFG->messaging = 0;
1201         // Ensure an exception is thrown.
1202         $this->expectException('moodle_exception');
1203         core_message_external::unblock_user($user1->id, $user2->id);
1204     }
1206     /**
1207      * Test unblocking a user with no permission.
1208      */
1209     public function test_unblock_user_no_permission() {
1210         $this->resetAfterTest();
1212         // Create some skeleton data just so we can call the WS.
1213         $user1 = self::getDataGenerator()->create_user();
1214         $user2 = self::getDataGenerator()->create_user();
1215         $user3 = self::getDataGenerator()->create_user();
1217         $this->setUser($user3);
1219         // Ensure an exception is thrown.
1220         $this->expectException('required_capability_exception');
1221         core_message_external::unblock_user($user1->id, $user2->id);
1222     }
1224     /**
1225      * Test search_contacts.
1226      */
1227     public function test_search_contacts() {
1228         global $DB;
1229         $this->resetAfterTest(true);
1231         $course1 = $this->getDataGenerator()->create_course();
1232         $course2 = $this->getDataGenerator()->create_course();
1234         $user1 = new stdClass();
1235         $user1->firstname = 'X';
1236         $user1->lastname = 'X';
1237         $user1 = $this->getDataGenerator()->create_user($user1);
1238         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1239         $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1241         $user2 = new stdClass();
1242         $user2->firstname = 'Eric';
1243         $user2->lastname = 'Cartman';
1244         $user2 = self::getDataGenerator()->create_user($user2);
1245         $user3 = new stdClass();
1246         $user3->firstname = 'Stan';
1247         $user3->lastname = 'Marsh';
1248         $user3 = self::getDataGenerator()->create_user($user3);
1249         self::getDataGenerator()->enrol_user($user3->id, $course1->id);
1250         $user4 = new stdClass();
1251         $user4->firstname = 'Kyle';
1252         $user4->lastname = 'Broflovski';
1253         $user4 = self::getDataGenerator()->create_user($user4);
1254         $user5 = new stdClass();
1255         $user5->firstname = 'Kenny';
1256         $user5->lastname = 'McCormick';
1257         $user5 = self::getDataGenerator()->create_user($user5);
1258         self::getDataGenerator()->enrol_user($user5->id, $course2->id);
1260         $this->setUser($user1);
1262         $results = core_message_external::search_contacts('r');
1263         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1264         $this->assertCount(5, $results); // Users 2 through 5 + admin
1266         $results = core_message_external::search_contacts('r', true);
1267         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1268         $this->assertCount(2, $results);
1270         $results = core_message_external::search_contacts('Kyle', false);
1271         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1272         $this->assertCount(1, $results);
1273         $result = reset($results);
1274         $this->assertEquals($user4->id, $result['id']);
1276         $results = core_message_external::search_contacts('y', false);
1277         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1278         $this->assertCount(2, $results);
1280         $results = core_message_external::search_contacts('y', true);
1281         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1282         $this->assertCount(1, $results);
1283         $result = reset($results);
1284         $this->assertEquals($user5->id, $result['id']);
1286         // Empty query, will throw an exception.
1287         $this->expectException(moodle_exception::class);
1288         $results = core_message_external::search_contacts('');
1289     }
1291     /**
1292      * Test get_messages.
1293      */
1294     public function test_get_messages() {
1295         global $CFG, $DB, $PAGE;
1296         $this->resetAfterTest(true);
1298         $this->preventResetByRollback();
1300         $user1 = self::getDataGenerator()->create_user();
1301         $user2 = self::getDataGenerator()->create_user();
1302         $user3 = self::getDataGenerator()->create_user();
1304         $course = self::getDataGenerator()->create_course();
1306         // Send a message from one user to another.
1307         $im1 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1308         $im2 = message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE);
1309         $im3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1310         $im4 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1311         $im5 = message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE);
1312         $im6 = message_post_message($user1, $user2, 'some random text 6', FORMAT_MOODLE);
1314         // Mark a message as read by user2.
1315         $message = $DB->get_record('messages', ['id' => $im6]);
1316         \core_message\api::mark_message_as_read($user2->id, $message);
1318         $this->setUser($user1);
1319         // Get unread conversations from user1 to user2.
1320         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1321         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1322         $this->assertCount(1, $messages['messages']);
1323         $this->assertEquals($im1, $messages['messages'][0]['id']);
1325         // Get read conversations from user1 to user2.
1326         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', MESSAGE_GET_READ, true, 0, 0);
1327         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1328         $this->assertCount(1, $messages['messages']);
1329         $this->assertEquals($im6, $messages['messages'][0]['id']);
1331         // Get both read and unread conversations from user1 to user2.
1332         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', MESSAGE_GET_READ_AND_UNREAD,
1333             true, 0, 0);
1334         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1335         $this->assertCount(2, $messages['messages']);
1337         // Delete an unread message.
1338         \core_message\api::delete_message($user1->id, $im1);
1340         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1341         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1342         $this->assertCount(0, $messages['messages']);
1344         $this->setUser($user2);
1345         // Get unread conversations from any user to user2.
1346         $messages = core_message_external::get_messages($user2->id, 0, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1347         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1348         $this->assertCount(2, $messages['messages']);
1350         // Conversations from user3 to user2.
1351         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1352         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1353         $this->assertCount(1, $messages['messages']);
1355         // Delete the message.
1356         \core_message\api::delete_message($user2->id, $im4);
1358         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1359         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1360         $this->assertCount(0, $messages['messages']);
1362         $this->setUser($user3);
1363         // Get unread notifications received by user3.
1364         $messages = core_message_external::get_messages($user3->id, 0, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0);
1365         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1366         $this->assertCount(0, $messages['messages']);
1368         // Now, create some notifications...
1369         // We are creating fake notifications but based on real ones.
1371         // This one comes from a disabled plugin's provider and therefore is not sent.
1372         $eventdata = new \core\message\message();
1373         $eventdata->courseid          = $course->id;
1374         $eventdata->notification      = 1;
1375         $eventdata->modulename        = 'moodle';
1376         $eventdata->component         = 'enrol_paypal';
1377         $eventdata->name              = 'paypal_enrolment';
1378         $eventdata->userfrom          = get_admin();
1379         $eventdata->userto            = $user1;
1380         $eventdata->subject           = "Moodle: PayPal payment";
1381         $eventdata->fullmessage       = "Your PayPal payment is pending.";
1382         $eventdata->fullmessageformat = FORMAT_PLAIN;
1383         $eventdata->fullmessagehtml   = '';
1384         $eventdata->smallmessage      = '';
1385         message_send($eventdata);
1386         $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '.
1387             'that is inactive or not allowed for the user id='.$user1->id);
1389         // This one omits notification = 1.
1390         $message = new \core\message\message();
1391         $message->courseid          = $course->id;
1392         $message->component         = 'enrol_manual';
1393         $message->name              = 'expiry_notification';
1394         $message->userfrom          = $user2;
1395         $message->userto            = $user1;
1396         $message->subject           = 'Test: This is not a notification but otherwise is valid';
1397         $message->fullmessage       = 'Test: Full message';
1398         $message->fullmessageformat = FORMAT_MARKDOWN;
1399         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1400         $message->smallmessage      = $message->subject;
1401         $message->contexturlname    = $course->fullname;
1402         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1403         message_send($message);
1405         $message = new \core\message\message();
1406         $message->courseid          = $course->id;
1407         $message->notification      = 1;
1408         $message->component         = 'enrol_manual';
1409         $message->name              = 'expiry_notification';
1410         $message->userfrom          = $user2;
1411         $message->userto            = $user1;
1412         $message->subject           = 'Enrolment expired';
1413         $message->fullmessage       = 'Enrolment expired blah blah blah';
1414         $message->fullmessageformat = FORMAT_MARKDOWN;
1415         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1416         $message->smallmessage      = $message->subject;
1417         $message->contexturlname    = $course->fullname;
1418         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1419         message_send($message);
1421         $userfrom = core_user::get_noreply_user();
1422         $userfrom->maildisplay = true;
1423         $eventdata = new \core\message\message();
1424         $eventdata->courseid          = $course->id;
1425         $eventdata->component         = 'moodle';
1426         $eventdata->name              = 'badgecreatornotice';
1427         $eventdata->userfrom          = $userfrom;
1428         $eventdata->userto            = $user1;
1429         $eventdata->notification      = 1;
1430         $eventdata->subject           = 'New badge';
1431         $eventdata->fullmessage       = format_text_email($eventdata->subject, FORMAT_HTML);
1432         $eventdata->fullmessageformat = FORMAT_PLAIN;
1433         $eventdata->fullmessagehtml   = $eventdata->subject;
1434         $eventdata->smallmessage      = $eventdata->subject;
1435         message_send($eventdata);
1437         $eventdata = new \core\message\message();
1438         $eventdata->courseid         = $course->id;
1439         $eventdata->name             = 'submission';
1440         $eventdata->component        = 'mod_feedback';
1441         $eventdata->userfrom         = $user1;
1442         $eventdata->userto           = $user2;
1443         $eventdata->subject          = 'Feedback submitted';
1444         $eventdata->fullmessage      = 'Feedback submitted from an user';
1445         $eventdata->fullmessageformat = FORMAT_PLAIN;
1446         $eventdata->fullmessagehtml  = '<strong>Feedback submitted</strong>';
1447         $eventdata->smallmessage     = '';
1448         $eventdata->customdata         = ['datakey' => 'data'];
1449         message_send($eventdata);
1451         $this->setUser($user1);
1452         // Get unread notifications from any user to user1.
1453         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0);
1454         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1455         $this->assertCount(3, $messages['messages']);
1457         // Get one unread notifications from any user to user1.
1458         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', MESSAGE_GET_UNREAD, true, 0, 1);
1459         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1460         $this->assertCount(1, $messages['messages']);
1462         // Get read notifications from any user to user1.
1463         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', MESSAGE_GET_READ, true, 0, 0);
1464         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1465         $this->assertCount(0, $messages['messages']);
1467         // Get unread both type of messages from any user to user1.
1468         $messages = core_message_external::get_messages($user1->id, 0, 'both', MESSAGE_GET_UNREAD, true, 0, 0);
1469         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1470         $this->assertCount(4, $messages['messages']);
1472         // Get unread notifications from no-reply-user to user1.
1473         $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0);
1474         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1475         $this->assertCount(1, $messages['messages']);
1477         // Get notifications send by user1 to any user.
1478         $messages = core_message_external::get_messages(0, $user1->id, 'notifications', MESSAGE_GET_UNREAD, true, 0, 0);
1479         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1480         $this->assertCount(1, $messages['messages']);
1481         // Check we receive custom data as a unserialisable json.
1482         $this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata']));
1483         $this->assertEquals('mod_feedback', $messages['messages'][0]['component']);
1484         $this->assertEquals('submission', $messages['messages'][0]['eventtype']);
1485         $feedbackicon = clean_param($PAGE->get_renderer('core')->image_url('icon', 'mod_feedback')->out(), PARAM_URL);
1486         $this->assertEquals($feedbackicon, $messages['messages'][0]['iconurl']);
1488         // Test warnings.
1489         $CFG->messaging = 0;
1491         $messages = core_message_external::get_messages(0, $user1->id, 'both', MESSAGE_GET_UNREAD, true, 0, 0);
1492         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1493         $this->assertCount(1, $messages['warnings']);
1495         // Test exceptions.
1497         // Messaging disabled.
1498         try {
1499             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1500             $this->fail('Exception expected due messaging disabled.');
1501         } catch (moodle_exception $e) {
1502             $this->assertEquals('disabled', $e->errorcode);
1503         }
1505         $CFG->messaging = 1;
1507         // Invalid users.
1508         try {
1509             $messages = core_message_external::get_messages(0, 0, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1510             $this->fail('Exception expected due invalid users.');
1511         } catch (moodle_exception $e) {
1512             $this->assertEquals('accessdenied', $e->errorcode);
1513         }
1515         // Invalid user ids.
1516         try {
1517             $messages = core_message_external::get_messages(2500, 0, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1518             $this->fail('Exception expected due invalid users.');
1519         } catch (moodle_exception $e) {
1520             $this->assertEquals('invaliduser', $e->errorcode);
1521         }
1523         // Invalid users (permissions).
1524         $this->setUser($user2);
1525         try {
1526             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', MESSAGE_GET_UNREAD, true, 0, 0);
1527             $this->fail('Exception expected due invalid user.');
1528         } catch (moodle_exception $e) {
1529             $this->assertEquals('accessdenied', $e->errorcode);
1530         }
1532     }
1534     /**
1535      * Test get_messages where we want all messages from a user, sent to any user.
1536      */
1537     public function test_get_messages_useridto_all() {
1538         $this->resetAfterTest(true);
1540         $user1 = self::getDataGenerator()->create_user();
1541         $user2 = self::getDataGenerator()->create_user();
1542         $user3 = self::getDataGenerator()->create_user();
1544         $this->setUser($user1);
1546         // Send a message from user 1 to two other users.
1547         $this->send_message($user1, $user2, 'some random text 1', 0, 1);
1548         $this->send_message($user1, $user3, 'some random text 2', 0, 2);
1550         // Get messages sent from user 1.
1551         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', MESSAGE_GET_UNREAD, false, 0, 0);
1552         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1554         // Confirm the data is correct.
1555         $messages = $messages['messages'];
1556         $this->assertCount(2, $messages);
1558         $message1 = array_shift($messages);
1559         $message2 = array_shift($messages);
1561         $this->assertEquals($user1->id, $message1['useridfrom']);
1562         $this->assertEquals($user2->id, $message1['useridto']);
1564         $this->assertEquals($user1->id, $message2['useridfrom']);
1565         $this->assertEquals($user3->id, $message2['useridto']);
1566     }
1568     /**
1569      * Test get_messages where we want all messages to a user, sent by any user.
1570      */
1571     public function test_get_messages_useridfrom_all() {
1572         $this->resetAfterTest();
1574         $user1 = self::getDataGenerator()->create_user();
1575         $user2 = self::getDataGenerator()->create_user();
1576         $user3 = self::getDataGenerator()->create_user();
1578         $this->setUser($user1);
1580         // Send a message to user 1 from two other users.
1581         $this->send_message($user2, $user1, 'some random text 1', 0, 1);
1582         $this->send_message($user3, $user1, 'some random text 2', 0, 2);
1584         // Get messages sent to user 1.
1585         $messages = core_message_external::get_messages($user1->id, 0, 'conversations', MESSAGE_GET_UNREAD, false, 0, 0);
1586         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1588         // Confirm the data is correct.
1589         $messages = $messages['messages'];
1590         $this->assertCount(2, $messages);
1592         $message1 = array_shift($messages);
1593         $message2 = array_shift($messages);
1595         $this->assertEquals($user2->id, $message1['useridfrom']);
1596         $this->assertEquals($user1->id, $message1['useridto']);
1598         $this->assertEquals($user3->id, $message2['useridfrom']);
1599         $this->assertEquals($user1->id, $message2['useridto']);
1600     }
1602     /**
1603      * Test get_blocked_users.
1604      */
1605     public function test_get_blocked_users() {
1606         $this->resetAfterTest(true);
1608         $user1 = self::getDataGenerator()->create_user();
1609         $userstranger = self::getDataGenerator()->create_user();
1610         $useroffline1 = self::getDataGenerator()->create_user();
1611         $useroffline2 = self::getDataGenerator()->create_user();
1612         $userblocked = self::getDataGenerator()->create_user();
1614         // Login as user1.
1615         $this->setUser($user1);
1617         \core_message\api::add_contact($user1->id, $useroffline1->id);
1618         \core_message\api::add_contact($user1->id, $useroffline2->id);
1620         // The userstranger sends a couple of messages to user1.
1621         $this->send_message($userstranger, $user1, 'Hello there!');
1622         $this->send_message($userstranger, $user1, 'How you goin?');
1624         // The userblocked sends a message to user1.
1625         // Note that this user is not blocked at this point.
1626         $this->send_message($userblocked, $user1, 'Here, have some spam.');
1628         // Retrieve the list of blocked users.
1629         $this->setUser($user1);
1630         $blockedusers = core_message_external::get_blocked_users($user1->id);
1631         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1632         $this->assertCount(0, $blockedusers['users']);
1634         // Block the $userblocked and retrieve again the list.
1635         \core_message\api::block_user($user1->id, $userblocked->id);
1636         $blockedusers = core_message_external::get_blocked_users($user1->id);
1637         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1638         $this->assertCount(1, $blockedusers['users']);
1640         // Remove the $userblocked and check that the list now is empty.
1641         delete_user($userblocked);
1642         $blockedusers = core_message_external::get_blocked_users($user1->id);
1643         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1644         $this->assertCount(0, $blockedusers['users']);
1645     }
1647     /**
1648      * Test mark_message_read.
1649      */
1650     public function test_mark_message_read() {
1651         $this->resetAfterTest(true);
1653         $user1 = self::getDataGenerator()->create_user();
1654         $user2 = self::getDataGenerator()->create_user();
1655         $user3 = self::getDataGenerator()->create_user();
1657         // Login as user1.
1658         $this->setUser($user1);
1659         \core_message\api::add_contact($user1->id, $user2->id);
1660         \core_message\api::add_contact($user1->id, $user3->id);
1662         // The user2 sends a couple of messages to user1.
1663         $this->send_message($user2, $user1, 'Hello there!');
1664         $this->send_message($user2, $user1, 'How you goin?');
1665         $this->send_message($user3, $user1, 'How you goin?');
1666         $this->send_message($user3, $user2, 'How you goin?');
1668         // Retrieve all messages sent by user2 (they are currently unread).
1669         $lastmessages = message_get_messages($user1->id, $user2->id, 0, MESSAGE_GET_UNREAD);
1671         $messageids = array();
1672         foreach ($lastmessages as $m) {
1673             $messageid = core_message_external::mark_message_read($m->id, time());
1674             $messageids[] = external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid);
1675         }
1677         // Retrieve all messages sent (they are currently read).
1678         $lastmessages = message_get_messages($user1->id, $user2->id, 0, MESSAGE_GET_READ);
1679         $this->assertCount(2, $lastmessages);
1680         $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages);
1681         $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages);
1683         // Retrieve all messages sent by any user (that are currently unread).
1684         $lastmessages = message_get_messages($user1->id, 0, 0, MESSAGE_GET_UNREAD);
1685         $this->assertCount(1, $lastmessages);
1687         // Invalid message ids.
1688         try {
1689             $messageid = core_message_external::mark_message_read(1337, time());
1690             $this->fail('Exception expected due invalid messageid.');
1691         } catch (dml_missing_record_exception $e) {
1692             $this->assertEquals('invalidrecordunknown', $e->errorcode);
1693         }
1695         // A message to a different user.
1696         $lastmessages = message_get_messages($user2->id, $user3->id, 0, MESSAGE_GET_UNREAD);
1697         $messageid = array_pop($lastmessages)->id;
1698         try {
1699             $messageid = core_message_external::mark_message_read($messageid, time());
1700             $this->fail('Exception expected due invalid messageid.');
1701         } catch (invalid_parameter_exception $e) {
1702             $this->assertEquals('invalidparameter', $e->errorcode);
1703         }
1704     }
1706     /**
1707      * Test mark_notification_read.
1708      */
1709     public function test_mark_notification_read() {
1710         $this->resetAfterTest(true);
1712         $user1 = self::getDataGenerator()->create_user();
1713         $user2 = self::getDataGenerator()->create_user();
1714         $user3 = self::getDataGenerator()->create_user();
1716         // Login as user1.
1717         $this->setUser($user1);
1718         \core_message\api::add_contact($user1->id, $user2->id);
1719         \core_message\api::add_contact($user1->id, $user3->id);
1721         // The user2 sends a couple of notifications to user1.
1722         $this->send_message($user2, $user1, 'Hello there!', 1);
1723         $this->send_message($user2, $user1, 'How you goin?', 1);
1724         $this->send_message($user3, $user1, 'How you goin?', 1);
1725         $this->send_message($user3, $user2, 'How you goin?', 1);
1727         // Retrieve all notifications sent by user2 (they are currently unread).
1728         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, MESSAGE_GET_UNREAD);
1730         $notificationids = array();
1731         foreach ($lastnotifications as $n) {
1732             $notificationid = core_message_external::mark_notification_read($n->id, time());
1733             $notificationids[] = external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(),
1734                 $notificationid);
1735         }
1737         // Retrieve all notifications sent (they are currently read).
1738         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, MESSAGE_GET_READ);
1739         $this->assertCount(2, $lastnotifications);
1740         $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications);
1741         $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications);
1743         // Retrieve all notifications sent by any user (that are currently unread).
1744         $lastnotifications = message_get_messages($user1->id, 0, 1, MESSAGE_GET_UNREAD);
1745         $this->assertCount(1, $lastnotifications);
1747         // Invalid notification ids.
1748         try {
1749             $notificationid = core_message_external::mark_notification_read(1337, time());
1750             $this->fail('Exception expected due invalid notificationid.');
1751         } catch (dml_missing_record_exception $e) {
1752             $this->assertEquals('invalidrecord', $e->errorcode);
1753         }
1755         // A notification to a different user.
1756         $lastnotifications = message_get_messages($user2->id, $user3->id, 1, MESSAGE_GET_UNREAD);
1757         $notificationid = array_pop($lastnotifications)->id;
1758         try {
1759             $notificationid = core_message_external::mark_notification_read($notificationid, time());
1760             $this->fail('Exception expected due invalid notificationid.');
1761         } catch (invalid_parameter_exception $e) {
1762             $this->assertEquals('invalidparameter', $e->errorcode);
1763         }
1764     }
1766     /**
1767      * Test delete_message.
1768      */
1769     public function test_delete_message() {
1770         global $DB;
1771         $this->resetAfterTest(true);
1773         $user1 = self::getDataGenerator()->create_user();
1774         $user2 = self::getDataGenerator()->create_user();
1775         $user3 = self::getDataGenerator()->create_user();
1776         $user4 = self::getDataGenerator()->create_user();
1778         // Login as user1.
1779         $this->setUser($user1);
1780         \core_message\api::add_contact($user1->id, $user2->id);
1781         \core_message\api::add_contact($user1->id, $user3->id);
1783         // User user1 does not interchange messages with user3.
1784         $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1785         $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1786         $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1787         $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE);
1789         // Retrieve all messages sent by user2 (they are currently unread).
1790         $lastmessages = message_get_messages($user1->id, $user2->id, 0, MESSAGE_GET_UNREAD);
1792         // Delete a message not read, as a user from.
1793         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1794         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1795         $this->assertTrue($result['status']);
1796         $this->assertCount(0, $result['warnings']);
1797         $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id));
1798         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action);
1800         // Try to delete the same message again.
1801         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1802         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1803         $this->assertFalse($result['status']);
1805         // Try to delete a message that does not belong to me.
1806         try {
1807             $messageid = core_message_external::delete_message($m2to3, $user3->id, false);
1808             $this->fail('Exception expected due invalid messageid.');
1809         } catch (moodle_exception $e) {
1810             $this->assertEquals('You do not have permission to delete this message', $e->errorcode);
1811         }
1813         $this->setUser($user3);
1814         // Delete a message not read, as a user to.
1815         $result = core_message_external::delete_message($m2to3, $user3->id, false);
1816         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1817         $this->assertTrue($result['status']);
1818         $this->assertCount(0, $result['warnings']);
1819         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id,
1820             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1822         // Delete a message read.
1823         $message = $DB->get_record('messages', ['id' => $m3to2]);
1824         \core_message\api::mark_message_as_read($user3->id, $message, time());
1825         $result = core_message_external::delete_message($m3to2, $user3->id);
1826         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1827         $this->assertTrue($result['status']);
1828         $this->assertCount(0, $result['warnings']);
1829         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id,
1830             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1832         // Invalid message ids.
1833         try {
1834             $result = core_message_external::delete_message(-1, $user1->id);
1835             $this->fail('Exception expected due invalid messageid.');
1836         } catch (dml_missing_record_exception $e) {
1837             $this->assertEquals('invalidrecord', $e->errorcode);
1838         }
1840         // Invalid user.
1841         try {
1842             $result = core_message_external::delete_message($m1to2, -1, false);
1843             $this->fail('Exception expected due invalid user.');
1844         } catch (moodle_exception $e) {
1845             $this->assertEquals('invaliduser', $e->errorcode);
1846         }
1848         // Not active user.
1849         delete_user($user2);
1850         try {
1851             $result = core_message_external::delete_message($m1to2, $user2->id, false);
1852             $this->fail('Exception expected due invalid user.');
1853         } catch (moodle_exception $e) {
1854             $this->assertEquals('userdeleted', $e->errorcode);
1855         }
1857         // Now, as an admin, try to delete any message.
1858         $this->setAdminUser();
1859         $result = core_message_external::delete_message($m3to4, $user4->id, false);
1860         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1861         $this->assertTrue($result['status']);
1862         $this->assertCount(0, $result['warnings']);
1863         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id,
1864             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1866     }
1868     public function test_mark_all_notifications_as_read_invalid_user_exception() {
1869         $this->resetAfterTest(true);
1871         $this->expectException('moodle_exception');
1872         core_message_external::mark_all_notifications_as_read(-2132131, 0);
1873     }
1875     public function test_mark_all_notifications_as_read_access_denied_exception() {
1876         $this->resetAfterTest(true);
1878         $sender = $this->getDataGenerator()->create_user();
1879         $user = $this->getDataGenerator()->create_user();
1881         $this->setUser($user);
1882         $this->expectException('moodle_exception');
1883         core_message_external::mark_all_notifications_as_read($sender->id, 0);
1884     }
1886     public function test_mark_all_notifications_as_read_missing_from_user_exception() {
1887         $this->resetAfterTest(true);
1889         $sender = $this->getDataGenerator()->create_user();
1891         $this->setUser($sender);
1892         $this->expectException('moodle_exception');
1893         core_message_external::mark_all_notifications_as_read($sender->id, 99999);
1894     }
1896     public function test_mark_all_notifications_as_read() {
1897         global $DB;
1899         $this->resetAfterTest(true);
1901         $sender1 = $this->getDataGenerator()->create_user();
1902         $sender2 = $this->getDataGenerator()->create_user();
1903         $sender3 = $this->getDataGenerator()->create_user();
1904         $recipient = $this->getDataGenerator()->create_user();
1906         $this->setUser($recipient);
1908         $this->send_message($sender1, $recipient, 'Notification', 1);
1909         $this->send_message($sender1, $recipient, 'Notification', 1);
1910         $this->send_message($sender2, $recipient, 'Notification', 1);
1911         $this->send_message($sender2, $recipient, 'Notification', 1);
1912         $this->send_message($sender3, $recipient, 'Notification', 1);
1913         $this->send_message($sender3, $recipient, 'Notification', 1);
1915         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id);
1916         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1917         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1919         $this->assertCount(2, $readnotifications);
1920         $this->assertCount(4, $unreadnotifications);
1922         core_message_external::mark_all_notifications_as_read($recipient->id, 0);
1923         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1924         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1926         $this->assertCount(6, $readnotifications);
1927         $this->assertCount(0, $unreadnotifications);
1928     }
1930     public function test_mark_all_notifications_as_read_time_created_to() {
1931         global $DB;
1933         $this->resetAfterTest(true);
1935         $sender1 = $this->getDataGenerator()->create_user();
1936         $sender2 = $this->getDataGenerator()->create_user();
1938         $recipient = $this->getDataGenerator()->create_user();
1939         $this->setUser($recipient);
1941         // Record messages as sent on one second intervals.
1942         $time = time();
1944         $this->send_message($sender1, $recipient, 'Message 1', 1, $time);
1945         $this->send_message($sender2, $recipient, 'Message 2', 1, $time + 1);
1946         $this->send_message($sender1, $recipient, 'Message 3', 1, $time + 2);
1947         $this->send_message($sender2, $recipient, 'Message 4', 1, $time + 3);
1949         // Mark notifications sent from sender1 up until the second message; should only mark the first notification as read.
1950         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id, $time + 1);
1952         $params = [$recipient->id];
1954         $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params));
1955         $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params));
1957         // Mark all notifications as read from any sender up to the time the third message was sent.
1958         core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 2);
1960         $this->assertEquals(3, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params));
1961         $this->assertEquals(1, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params));
1963         // Mark all notifications as read from any sender with a time after all messages were sent.
1964         core_message_external::mark_all_notifications_as_read($recipient->id, 0, $time + 10);
1966         $this->assertEquals(4, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', $params));
1967         $this->assertEquals(0, $DB->count_records_select('notifications', 'useridto = ? AND timeread IS NULL', $params));
1968     }
1970     /**
1971      * Test get_user_notification_preferences
1972      */
1973     public function test_get_user_notification_preferences() {
1974         $this->resetAfterTest(true);
1976         $user = self::getDataGenerator()->create_user();
1977         $this->setUser($user);
1979         // Set a couple of preferences to test.
1980         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
1981         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
1983         $prefs = core_message_external::get_user_notification_preferences();
1984         $prefs = external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs);
1985         // Check processors.
1986         $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors']));
1987         $this->assertEquals($user->id, $prefs['preferences']['userid']);
1989         // Check components.
1990         $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components']));
1992         // Check some preferences that we previously set.
1993         $found = 0;
1994         foreach ($prefs['preferences']['components'] as $component) {
1995             foreach ($component['notifications'] as $prefdata) {
1996                 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') {
1997                     continue;
1998                 }
1999                 foreach ($prefdata['processors'] as $processor) {
2000                     if ($processor['name'] == 'popup') {
2001                         $this->assertTrue($processor['loggedin']['checked']);
2002                         $found++;
2003                     } else if ($processor['name'] == 'email') {
2004                         $this->assertTrue($processor['loggedoff']['checked']);
2005                         $found++;
2006                     }
2007                 }
2008             }
2009         }
2010         $this->assertEquals(2, $found);
2011     }
2013     /**
2014      * Test get_user_notification_preferences permissions
2015      */
2016     public function test_get_user_notification_preferences_permissions() {
2017         $this->resetAfterTest(true);
2019         $user = self::getDataGenerator()->create_user();
2020         $otheruser = self::getDataGenerator()->create_user();
2021         $this->setUser($user);
2023         $this->expectException('moodle_exception');
2024         $prefs = core_message_external::get_user_notification_preferences($otheruser->id);
2025     }
2027     /**
2028      * Tests searching for users when site-wide messaging is disabled.
2029      *
2030      * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
2031      * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
2032      * profile.
2033      */
2034     public function test_message_search_users_messagingallusers_disabled() {
2035         global $DB;
2036         $this->resetAfterTest();
2038         // Create some users.
2039         $users = [];
2040         foreach (range(1, 8) as $i) {
2041             $user = new stdClass();
2042             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2043             $user->lastname = $i;
2044             $user = $this->getDataGenerator()->create_user($user);
2045             $users[$i] = $user;
2046         }
2048         // Enrol a few users in the same course, but leave them as non-contacts.
2049         $course1 = $this->getDataGenerator()->create_course();
2050         $course2 = $this->getDataGenerator()->create_course();
2052         $this->setAdminUser();
2053         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2054         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2055         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2057         // Add some other users as contacts.
2058         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2059         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2060         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2062         // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
2063         $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher');
2064         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
2065         set_config('coursecontact', $teacherrole->id);
2067         // Create individual conversations between some users, one contact and one non-contact.
2068         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2069             [$users[1]->id, $users[2]->id]);
2070         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2071             [$users[6]->id, $users[1]->id]);
2073         // Create a group conversation between 4 users, including a contact and a non-contact.
2074         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2075             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
2077         // Set as the user performing the search.
2078         $this->setUser($users[1]);
2080         // Perform a search with $CFG->messagingallusers disabled.
2081         set_config('messagingallusers', 0);
2082         $result = core_message_external::message_search_users($users[1]->id, 'search');
2083         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2085         // Confirm that we returns contacts and non-contacts.
2086         $this->assertArrayHasKey('contacts', $result);
2087         $this->assertArrayHasKey('noncontacts', $result);
2088         $contacts = $result['contacts'];
2089         $noncontacts = $result['noncontacts'];
2091         // Check that we retrieved the correct contacts.
2092         $this->assertCount(2, $contacts);
2093         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2094         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2096         // Verify the correct conversations were returned for the contacts.
2097         $this->assertCount(2, $contacts[0]['conversations']);
2098         // We can't rely on the ordering of conversations within the results, so sort by id first.
2099         usort($contacts[0]['conversations'], function($a, $b) {
2100             return $b['id'] <=> $a['id'];
2101         });
2102         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2103         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2105         $this->assertCount(0, $contacts[1]['conversations']);
2107         // Check that we retrieved the correct non-contacts.
2108         // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles
2109         // are visible in that course. This excludes users like course contacts.
2110         $this->assertCount(3, $noncontacts);
2111         // Self-conversation first.
2112         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2113         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2114         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2116         // Verify the correct conversations were returned for the non-contacts.
2117         $this->assertCount(1, $noncontacts[1]['conversations']);
2118         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']);
2120         $this->assertCount(1, $noncontacts[2]['conversations']);
2121         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']);
2122     }
2124     /**
2125      * Tests searching for users when site-wide messaging is enabled.
2126      *
2127      * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user
2128      * can view their respective profile.
2129      */
2130     public function test_message_search_users_messagingallusers_enabled() {
2131         global $DB;
2132         $this->resetAfterTest();
2134         // Create some users.
2135         $users = [];
2136         foreach (range(1, 9) as $i) {
2137             $user = new stdClass();
2138             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2139             $user->lastname = $i;
2140             $user = $this->getDataGenerator()->create_user($user);
2141             $users[$i] = $user;
2142         }
2144         // Enrol a few users in the same course, but leave them as non-contacts.
2145         $course1 = $this->getDataGenerator()->create_course();
2146         $course2 = $this->getDataGenerator()->create_course();
2148         $this->setAdminUser();
2149         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2150         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2151         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2153         // Add some other users as contacts.
2154         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2155         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2156         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2158         // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
2159         $this->getDataGenerator()->enrol_user($users[9]->id, $course2->id, 'editingteacher');
2160         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
2161         set_config('coursecontact', $teacherrole->id);
2163         // Create individual conversations between some users, one contact and one non-contact.
2164         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2165             [$users[1]->id, $users[2]->id]);
2166         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2167             [$users[6]->id, $users[1]->id]);
2169         // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
2170         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2171             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
2173         // Set as the user performing the search.
2174         $this->setUser($users[1]);
2176         // Perform a search with $CFG->messagingallusers enabled.
2177         set_config('messagingallusers', 1);
2178         $result = core_message_external::message_search_users($users[1]->id, 'search');
2179         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2181         // Confirm that we returns contacts and non-contacts.
2182         $this->assertArrayHasKey('contacts', $result);
2183         $this->assertArrayHasKey('noncontacts', $result);
2184         $contacts = $result['contacts'];
2185         $noncontacts = $result['noncontacts'];
2187         // Check that we retrieved the correct contacts.
2188         $this->assertCount(2, $contacts);
2189         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2190         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2192         // Verify the correct conversations were returned for the contacts.
2193         $this->assertCount(2, $contacts[0]['conversations']);
2194         // We can't rely on the ordering of conversations within the results, so sort by id first.
2195         usort($contacts[0]['conversations'], function($a, $b) {
2196             return $b['id'] <=> $a['id'];
2197         });
2198         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2199         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2201         $this->assertCount(0, $contacts[1]['conversations']);
2203         // Check that we retrieved the correct non-contacts.
2204         // If site wide messaging is enabled, we expect to be able to search for any users whose profiles we can view.
2205         // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1.
2206         $this->assertCount(4, $noncontacts);
2207         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2208         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2209         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2210         $this->assertEquals($users[9]->id, $noncontacts[3]['id']);
2212         // Verify the correct conversations were returned for the non-contacts.
2213         $this->assertCount(1, $noncontacts[1]['conversations']);
2214         $this->assertCount(1, $noncontacts[2]['conversations']);
2215         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']);
2216         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']);
2217         $this->assertCount(0, $noncontacts[3]['conversations']);
2218     }
2220     /**
2221      * Verify searching for users find themselves when they have self-conversations.
2222      */
2223     public function test_message_search_users_self_conversations() {
2224         $this->resetAfterTest();
2226         // Create some users.
2227         $user1 = new stdClass();
2228         $user1->firstname = 'User';
2229         $user1->lastname = 'One';
2230         $user1 = $this->getDataGenerator()->create_user($user1);
2231         $user2 = new stdClass();
2232         $user2->firstname = 'User';
2233         $user2->lastname = 'Two';
2234         $user2 = $this->getDataGenerator()->create_user($user2);
2236         // Get self-conversation for user1.
2237         $sc1 = \core_message\api::get_self_conversation($user1->id);
2238         testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
2240         // Perform a search as user1.
2241         $this->setUser($user1);
2242         $result = core_message_external::message_search_users($user1->id, 'One');
2243         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2245         // Check results are empty.
2246         $this->assertCount(0, $result['contacts']);
2247         $this->assertCount(1, $result['noncontacts']);
2248     }
2250     /**
2251      * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
2252      */
2253     public function test_message_search_users_with_empty_result() {
2254         $this->resetAfterTest();
2256         // Create some users, but make sure neither will match the search term.
2257         $user1 = new stdClass();
2258         $user1->firstname = 'User';
2259         $user1->lastname = 'One';
2260         $user1 = $this->getDataGenerator()->create_user($user1);
2261         $user2 = new stdClass();
2262         $user2->firstname = 'User';
2263         $user2->lastname = 'Two';
2264         $user2 = $this->getDataGenerator()->create_user($user2);
2266         // Perform a search as user1.
2267         $this->setUser($user1);
2268         $result = core_message_external::message_search_users($user1->id, 'search');
2269         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2271         // Check results are empty.
2272         $this->assertCount(0, $result['contacts']);
2273         $this->assertCount(0, $result['noncontacts']);
2274     }
2276     /**
2277      * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
2278      */
2279     public function test_message_search_users_limit_offset() {
2280         $this->resetAfterTest();
2282         // Create 20 users.
2283         $users = [];
2284         foreach (range(1, 20) as $i) {
2285             $user = new stdClass();
2286             $user->firstname = "User search";
2287             $user->lastname = $i;
2288             $user = $this->getDataGenerator()->create_user($user);
2289             $users[$i] = $user;
2290         }
2292         // Enrol the first 8 users in the same course, but leave them as non-contacts.
2293         $this->setAdminUser();
2294         $course1 = $this->getDataGenerator()->create_course();
2295         foreach (range(1, 8) as $i) {
2296             $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
2297         }
2299         // Add 5 users, starting at the 11th user, as contacts for user1.
2300         foreach (range(11, 15) as $i) {
2301             \core_message\api::add_contact($users[1]->id, $users[$i]->id);
2302         }
2304         // Set as the user performing the search.
2305         $this->setUser($users[1]);
2307         // Search using a limit of 3.
2308         // This tests the case where we have more results than the limit for both contacts and non-contacts.
2309         $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3);
2310         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2311         $contacts = $result['contacts'];
2312         $noncontacts = $result['noncontacts'];
2314         // Check that we retrieved the correct contacts.
2315         $this->assertCount(3, $contacts);
2316         $this->assertEquals($users[11]->id, $contacts[0]['id']);
2317         $this->assertEquals($users[12]->id, $contacts[1]['id']);
2318         $this->assertEquals($users[13]->id, $contacts[2]['id']);
2320         // Check that we retrieved the correct non-contacts.
2321         // Consider first conversation is self-conversation.
2322         $this->assertCount(3, $noncontacts);
2323         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2324         $this->assertEquals($users[2]->id, $noncontacts[1]['id']);
2325         $this->assertEquals($users[3]->id, $noncontacts[2]['id']);
2327         // Now, offset to get the next batch of results.
2328         // We expect to see 2 contacts, and 3 non-contacts.
2329         $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3);
2330         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2331         $contacts = $result['contacts'];
2332         $noncontacts = $result['noncontacts'];
2333         $this->assertCount(2, $contacts);
2334         $this->assertEquals($users[14]->id, $contacts[0]['id']);
2335         $this->assertEquals($users[15]->id, $contacts[1]['id']);
2337         $this->assertCount(3, $noncontacts);
2338         $this->assertEquals($users[4]->id, $noncontacts[0]['id']);
2339         $this->assertEquals($users[5]->id, $noncontacts[1]['id']);
2340         $this->assertEquals($users[6]->id, $noncontacts[2]['id']);
2342         // Now, offset to get the next batch of results.
2343         // We expect to see 0 contacts, and 2 non-contacts.
2344         $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3);
2345         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2346         $contacts = $result['contacts'];
2347         $noncontacts = $result['noncontacts'];
2348         $this->assertCount(0, $contacts);
2350         $this->assertCount(2, $noncontacts);
2351         $this->assertEquals($users[7]->id, $noncontacts[0]['id']);
2352         $this->assertEquals($users[8]->id, $noncontacts[1]['id']);
2353     }
2355     /**
2356      * Tests searching users as another user having the 'moodle/user:viewdetails' capability.
2357      */
2358     public function test_message_search_users_with_cap() {
2359         $this->resetAfterTest();
2360         global $DB;
2362         // Create some users.
2363         $users = [];
2364         foreach (range(1, 8) as $i) {
2365             $user = new stdClass();
2366             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2367             $user->lastname = $i;
2368             $user = $this->getDataGenerator()->create_user($user);
2369             $users[$i] = $user;
2370         }
2372         // Enrol a few users in the same course, but leave them as non-contacts.
2373         $course1 = $this->getDataGenerator()->create_course();
2374         $this->setAdminUser();
2375         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2376         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2377         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2379         // Add some other users as contacts.
2380         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2381         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2382         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2384         // Set as the user performing the search.
2385         $this->setUser($users[1]);
2387         // Grant the authenticated user role the capability 'user:viewdetails' at site context.
2388         $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
2389         assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
2391         // Perform a search with $CFG->messagingallusers disabled.
2392         set_config('messagingallusers', 0);
2393         $result = core_message_external::message_search_users($users[1]->id, 'search');
2394         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2395         $contacts = $result['contacts'];
2396         $noncontacts = $result['noncontacts'];
2398         // Check that we retrieved the correct contacts.
2399         $this->assertCount(2, $contacts);
2400         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2401         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2403         // Check that we retrieved the correct non-contacts.
2404         // Site-wide messaging is disabled, so we expect to be able to search for any users whose profile we can view.
2405         // Consider first conversations is self-conversation.
2406         $this->assertCount(3, $noncontacts);
2407         $this->assertEquals($users[1]->id, $noncontacts[0]['id']);
2408         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2409         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2410     }
2412     /**
2413      * Tests searching users as another user without the 'moodle/user:viewdetails' capability.
2414      */
2415     public function test_message_search_users_without_cap() {
2416         $this->resetAfterTest();
2418         // Create some users.
2419         $user1 = $this->getDataGenerator()->create_user();
2420         $user2 = $this->getDataGenerator()->create_user();
2422         // The person doing the search for another user.
2423         $this->setUser($user1);
2425         // Ensure an exception is thrown.
2426         $this->expectException('moodle_exception');
2427         core_message_external::message_search_users($user2->id, 'User');
2428         $this->assertDebuggingCalled();
2429     }
2431     /**
2432      * Tests searching users with messaging disabled.
2433      */
2434     public function test_message_search_users_messaging_disabled() {
2435         $this->resetAfterTest();
2437         // Create some skeleton data just so we can call the WS.
2438         $user = $this->getDataGenerator()->create_user();
2440         // The person doing the search.
2441         $this->setUser($user);
2443         // Disable messaging.
2444         set_config('messaging', 0);
2446         // Ensure an exception is thrown.
2447         $this->expectException('moodle_exception');
2448         core_message_external::message_search_users($user->id, 'User');
2449     }
2451     /**
2452      * Tests searching messages.
2453      */
2454     public function test_messagearea_search_messages() {
2455         $this->resetAfterTest(true);
2457         // Create some users.
2458         $user1 = self::getDataGenerator()->create_user();
2459         $user2 = self::getDataGenerator()->create_user();
2461         // The person doing the search.
2462         $this->setUser($user1);
2464         // Send some messages back and forth.
2465         $time = time();
2466         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2467         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2468         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2469         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2470         $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2472         // Perform a search.
2473         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2475         // We need to execute the return values cleaning process to simulate the web service server.
2476         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result);
2478         // Confirm the data is correct.
2479         $messages = $result['contacts'];
2480         $this->assertCount(2, $messages);
2482         $message1 = $messages[0];
2483         $message2 = $messages[1];
2485         $this->assertEquals($user2->id, $message1['userid']);
2486         $this->assertEquals(fullname($user2), $message1['fullname']);
2487         $this->assertTrue($message1['ismessaging']);
2488         $this->assertFalse($message1['sentfromcurrentuser']);
2489         $this->assertEquals('Word.', $message1['lastmessage']);
2490         $this->assertNotEmpty($message1['messageid']);
2491         $this->assertNull($message1['isonline']);
2492         $this->assertFalse($message1['isread']);
2493         $this->assertFalse($message1['isblocked']);
2494         $this->assertNull($message1['unreadcount']);
2495         $this->assertEquals($convid, $message1['conversationid']);
2497         $this->assertEquals($user2->id, $message2['userid']);
2498         $this->assertEquals(fullname($user2), $message2['fullname']);
2499         $this->assertTrue($message2['ismessaging']);
2500         $this->assertTrue($message2['sentfromcurrentuser']);
2501         $this->assertEquals('Yo!', $message2['lastmessage']);
2502         $this->assertNotEmpty($message2['messageid']);
2503         $this->assertNull($message2['isonline']);
2504         $this->assertTrue($message2['isread']);
2505         $this->assertFalse($message2['isblocked']);
2506         $this->assertNull($message2['unreadcount']);
2507         $this->assertEquals($convid, $message2['conversationid']);
2508     }
2510     /**
2511      * Tests searching messages as another user.
2512      */
2513     public function test_messagearea_search_messages_as_other_user() {
2514         $this->resetAfterTest(true);
2516         // The person doing the search.
2517         $this->setAdminUser();
2519         // Create some users.
2520         $user1 = self::getDataGenerator()->create_user();
2521         $user2 = self::getDataGenerator()->create_user();
2523         // Send some messages back and forth.
2524         $time = time();
2525         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2526         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2527         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2528         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2530         // Perform a search.
2531         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2533         // We need to execute the return values cleaning process to simulate the web service server.
2534         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(),
2535             $result);
2537         // Confirm the data is correct.
2538         $messages = $result['contacts'];
2539         $this->assertCount(2, $messages);
2541         $message1 = $messages[0];
2542         $message2 = $messages[1];
2544         $this->assertEquals($user2->id, $message1['userid']);
2545         $this->assertEquals(fullname($user2), $message1['fullname']);
2546         $this->assertTrue($message1['ismessaging']);
2547         $this->assertFalse($message1['sentfromcurrentuser']);
2548         $this->assertEquals('Word.', $message1['lastmessage']);
2549         $this->assertNotEmpty($message1['messageid']);
2550         $this->assertFalse($message1['isonline']);
2551         $this->assertFalse($message1['isread']);
2552         $this->assertFalse($message1['isblocked']);
2553         $this->assertNull($message1['unreadcount']);
2555         $this->assertEquals($user2->id, $message2['userid']);
2556         $this->assertEquals(fullname($user2), $message2['fullname']);
2557         $this->assertTrue($message2['ismessaging']);
2558         $this->assertTrue($message2['sentfromcurrentuser']);
2559         $this->assertEquals('Yo!', $message2['lastmessage']);
2560         $this->assertNotEmpty($message2['messageid']);
2561         $this->assertFalse($message2['isonline']);
2562         $this->assertTrue($message2['isread']);
2563         $this->assertFalse($message2['isblocked']);
2564         $this->assertNull($message2['unreadcount']);
2565     }
2567     /**
2568      * Tests searching messages as another user without the proper capabilities.
2569      */
2570     public function test_messagearea_search_messages_as_other_user_without_cap() {
2571         $this->resetAfterTest(true);
2573         // Create some users.
2574         $user1 = self::getDataGenerator()->create_user();
2575         $user2 = self::getDataGenerator()->create_user();
2577         // The person doing the search for another user.
2578         $this->setUser($user1);
2580         // Ensure an exception is thrown.
2581         $this->expectException('moodle_exception');
2582         core_message_external::data_for_messagearea_search_messages($user2->id, 'Search');
2583     }
2585     /**
2586      * Tests searching messages with messaging disabled
2587      */
2588     public function test_messagearea_search_messages_messaging_disabled() {
2589         global $CFG;
2591         $this->resetAfterTest(true);
2593         // Create some skeleton data just so we can call the WS.
2594         $user = self::getDataGenerator()->create_user();
2596         // The person doing the search .
2597         $this->setUser($user);
2599         // Disable messaging.
2600         $CFG->messaging = 0;
2602         // Ensure an exception is thrown.
2603         $this->expectException('moodle_exception');
2604         core_message_external::data_for_messagearea_search_messages($user->id, 'Search');
2605     }
2607     /**
2608      * Tests retrieving contacts.
2609      */
2610     public function test_get_user_contacts() {
2611         $this->resetAfterTest(true);
2613         // Create some users.
2614         $user1 = self::getDataGenerator()->create_user();
2616         // Set as the user.
2617         $this->setUser($user1);
2619         $user2 = new stdClass();
2620         $user2->firstname = 'User';
2621         $user2->lastname = 'A';
2622         $user2 = self::getDataGenerator()->create_user($user2);
2624         $user3 = new stdClass();
2625         $user3->firstname = 'User';
2626         $user3->lastname = 'B';
2627         $user3 = self::getDataGenerator()->create_user($user3);
2629         $user4 = new stdClass();
2630         $user4->firstname = 'User';
2631         $user4->lastname = 'C';
2632         $user4 = self::getDataGenerator()->create_user($user4);
2634         $user5 = new stdClass();
2635         $user5->firstname = 'User';
2636         $user5->lastname = 'D';
2637         $user5 = self::getDataGenerator()->create_user($user5);
2639         // Add some users as contacts.
2640         \core_message\api::add_contact($user1->id, $user2->id);
2641         \core_message\api::add_contact($user1->id, $user3->id);
2642         \core_message\api::add_contact($user1->id, $user4->id);
2644         // Retrieve the contacts.
2645         $result = core_message_external::get_user_contacts($user1->id);
2647         // We need to execute the return values cleaning process to simulate the web service server.
2648         $result = external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(),
2649             $result);
2651         // Confirm the data is correct.
2652         $contacts = $result;
2653         usort($contacts, ['static', 'sort_contacts_id']);
2654         $this->assertCount(3, $contacts);
2656         $contact1 = array_shift($contacts);
2657         $contact2 = array_shift($contacts);
2658         $contact3 = array_shift($contacts);
2660         $this->assertEquals($user2->id, $contact1['id']);
2661         $this->assertEquals(fullname($user2), $contact1['fullname']);
2662         $this->assertTrue($contact1['iscontact']);
2664         $this->assertEquals($user3->id, $contact2['id']);
2665         $this->assertEquals(fullname($user3), $contact2['fullname']);
2666         $this->assertTrue($contact2['iscontact']);
2668         $this->assertEquals($user4->id, $contact3['id']);
2669         $this->assertEquals(fullname($user4), $contact3['fullname']);
2670         $this->assertTrue($contact3['iscontact']);
2671     }
2673     /**
2674      * Tests retrieving contacts as another user.
2675      */
2676     public function test_get_user_contacts_as_other_user() {
2677         $this->resetAfterTest(true);
2679         $this->setAdminUser();
2681         // Create some users.
2682         $user1 = self::getDataGenerator()->create_user();
2684         $user2 = new stdClass();
2685         $user2->firstname = 'User';
2686         $user2->lastname = 'A';
2687         $user2 = self::getDataGenerator()->create_user($user2);
2689         $user3 = new stdClass();
2690         $user3->firstname = 'User';
2691         $user3->lastname = 'B';
2692         $user3 = self::getDataGenerator()->create_user($user3);
2694         $user4 = new stdClass();
2695         $user4->firstname = 'User';
2696         $user4->lastname = 'C';
2697         $user4 = self::getDataGenerator()->create_user($user4);
2699         $user5 = new stdClass();
2700         $user5->firstname = 'User';
2701         $user5->lastname = 'D';
2702         $user5 = self::getDataGenerator()->create_user($user5);
2704         // Add some users as contacts.
2705         \core_message\api::add_contact($user1->id, $user2->id);
2706         \core_message\api::add_contact($user1->id, $user3->id);
2707         \core_message\api::add_contact($user1->id, $user4->id);
2709         // Retrieve the contacts.
2710         $result = core_message_external::get_user_contacts($user1->id);
2712         // We need to execute the return values cleaning process to simulate the web service server.
2713         $result = external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(),
2714             $result);
2716         // Confirm the data is correct.
2717         $contacts = $result;
2718         usort($contacts, ['static', 'sort_contacts_id']);
2719         $this->assertCount(3, $contacts);
2721         $contact1 = array_shift($contacts);
2722         $contact2 = array_shift($contacts);
2723         $contact3 = array_shift($contacts);
2725         $this->assertEquals($user2->id, $contact1['id']);
2726         $this->assertEquals(fullname($user2), $contact1['fullname']);
2727         $this->assertTrue($contact1['iscontact']);
2729         $this->assertEquals($user3->id, $contact2['id']);
2730         $this->assertEquals(fullname($user3), $contact2['fullname']);
2731         $this->assertTrue($contact2['iscontact']);
2733         $this->assertEquals($user4->id, $contact3['id']);
2734         $this->assertEquals(fullname($user4), $contact3['fullname']);
2735         $this->assertTrue($contact3['iscontact']);
2736     }
2738     /**
2739      * Tests retrieving contacts as another user without the proper capabilities.
2740      */
2741     public function test_get_user_contacts_as_other_user_without_cap() {
2742         $this->resetAfterTest(true);
2744         // Create some users.
2745         $user1 = self::getDataGenerator()->create_user();
2746         $user2 = self::getDataGenerator()->create_user();
2748         // The person retrieving the contacts for another user.
2749         $this->setUser($user1);
2751         // Perform the WS call and ensure an exception is thrown.
2752         $this->expectException('moodle_exception');
2753         core_message_external::get_user_contacts($user2->id);
2754     }
2756     /**
2757      * Tests retrieving contacts with messaging disabled.
2758      */
2759     public function test_get_user_contacts_messaging_disabled() {
2760         global $CFG;
2762         $this->resetAfterTest(true);
2764         // Create some skeleton data just so we can call the WS.
2765         $user = self::getDataGenerator()->create_user();
2767         // The person retrieving the contacts.
2768         $this->setUser($user);
2770         // Disable messaging.
2771         $CFG->messaging = 0;
2773         // Perform the WS call and ensure we are shown that it is disabled.
2774         $this->expectException('moodle_exception');
2775         core_message_external::get_user_contacts($user->id);
2776     }
2778     /**
2779      * Test getting contacts when there are no results.
2780      */
2781     public function test_get_user_contacts_no_results() {
2782         $this->resetAfterTest();
2784         $user1 = self::getDataGenerator()->create_user();
2786         $this->setUser($user1);
2788         $requests = core_message_external::get_user_contacts($user1->id);
2789         $requests = external_api::clean_returnvalue(core_message_external::get_user_contacts_returns(), $requests);
2791         $this->assertEmpty($requests);
2792     }
2794     /**
2795      * Tests get_conversation_messages for retrieving messages.
2796      */
2797     public function test_get_conversation_messages() {
2798         $this->resetAfterTest(true);
2800         // Create some users.
2801         $user1 = self::getDataGenerator()->create_user();
2802         $user2 = self::getDataGenerator()->create_user();
2803         $user3 = self::getDataGenerator()->create_user();
2804         $user4 = self::getDataGenerator()->create_user();
2805         $user5 = self::getDataGenerator()->create_user();
2807         // Create group conversation.
2808         $conversation = \core_message\api::create_conversation(
2809             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2810             [$user1->id, $user2->id, $user3->id, $user4->id]
2811         );
2813         // The person asking for the messages.
2814         $this->setUser($user1);
2816         // Send some messages back and forth.
2817         $time = time();
2818         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time);
2819         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1);
2820         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2);
2821         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3);
2823         // Retrieve the messages.
2824         $result = core_message_external::get_conversation_messages($user1->id, $conversation->id);
2826         // We need to execute the return values cleaning process to simulate the web service server.
2827         $result = external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(),
2828             $result);
2830         // Check the results are correct.
2831         $this->assertEquals($conversation->id, $result['id']);
2833         // Confirm the members data is correct.
2834         $members = $result['members'];
2835         $this->assertCount(3, $members);
2836         $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']];
2837         $this->assertContainsEquals($user1->id, $membersid);
2838         $this->assertContainsEquals($user2->id, $membersid);
2839         $this->assertContainsEquals($user3->id, $membersid);
2841         $membersfullnames = [$members[0]['fullname'], $members[1]['fullname'], $members[2]['fullname']];
2842         $this->assertContainsEquals(fullname($user1), $membersfullnames);
2843         $this->assertContainsEquals(fullname($user2), $membersfullnames);
2844         $this->assertContainsEquals(fullname($user3), $membersfullnames);
2846         // Confirm the messages data is correct.
2847         $messages = $result['messages'];
2848         $this->assertCount(4, $messages);
2850         $message1 = $messages[0];
2851         $message2 = $messages[1];
2852         $message3 = $messages[2];
2853         $message4 = $messages[3];
2855         $this->assertEquals($user1->id, $message1['useridfrom']);
2856         $this->assertStringContainsString('Yo!', $message1['text']);
2858         $this->assertEquals($user3->id, $message2['useridfrom']);
2859         $this->assertStringContainsString('Sup mang?', $message2['text']);
2861         $this->assertEquals($user2->id, $message3['useridfrom']);
2862         $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']);
2864         $this->assertEquals($user1->id, $message4['useridfrom']);
2865         $this->assertStringContainsString('Word.', $message4['text']);
2866     }
2868     /**
2869      * Tests get_conversation_messages for retrieving messages using timefrom parameter.
2870      */
2871     public function test_get_conversation_messages_timefrom() {
2872         $this->resetAfterTest(true);
2874         // Create some users.
2875         $user1 = self::getDataGenerator()->create_user();
2876         $user2 = self::getDataGenerator()->create_user();
2877         $user3 = self::getDataGenerator()->create_user();
2878         $user4 = self::getDataGenerator()->create_user();
2880         // Create group conversation.
2881         $conversation = \core_message\api::create_conversation(
2882             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2883             [$user1->id, $user2->id, $user3->id]
2884         );
2886         // The person asking for the messages.
2887         $this->setUser($user1);
2889         // Send some messages back and forth.
2890         $time = time();
2891         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time - 4);
2892         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time - 3);
2893         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 3', $time - 2);
2894         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 4', $time - 1);
2896         // Retrieve the messages from $time - 3, which should be the 3 most recent messages.
2897         $result = core_message_external::get_conversation_messages($user1->id, $conversation->id, 0, 0, false, $time - 3);
2899         // We need to execute the return values cleaning process to simulate the web service server.
2900         $result = external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(),
2901             $result);
2903         // Check the results are correct.
2904         $this->assertEquals($conversation->id, $result['id']);
2906         // Confirm the messages data is correct.
2907         $messages = $result['messages'];
2908         $this->assertCount(3, $messages);
2910         $message1 = $messages[0];
2911         $message2 = $messages[1];
2912         $message3 = $messages[2];
2914         $this->assertStringContainsString('Message 2', $message1['text']);
2915         $this->assertStringContainsString('Message 3', $message2['text']);
2916         $this->assertStringContainsString('Message 4', $message3['text']);
2918         // Confirm the members data is correct.
2919         $members = $result['members'];
2920         $this->assertCount(1, $members);
2921         $this->assertEquals($user2->id, $members[0]['id']);
2922     }
2924     /**
2925      * Tests get_conversation_messages for retrieving messages as another user.
2926      */
2927     public function test_get_conversation_messages_as_other_user() {
2928         $this->resetAfterTest(true);
2930         // Set as admin.
2931         $this->setAdminUser();
2933         // Create some users.
2934         $user1 = self::getDataGenerator()->create_user();
2935         $user2 = self::getDataGenerator()->create_user();
2936         $user3 = self::getDataGenerator()->create_user();
2937         $user4 = self::getDataGenerator()->create_user();
2939         // Create group conversation.
2940         $conversation = \core_message\api::create_conversation(
2941             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2942             [$user1->id, $user2->id, $user3->id, $user4->id]
2943         );
2945         // Send some messages back and forth.
2946         $time = time();
2947         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time);
2948         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Sup mang?', $time + 1);
2949         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Writing PHPUnit tests!', $time + 2);
2950         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 3);
2952         // Retrieve the messages.
2953         $result = core_message_external::get_conversation_messages($user1->id, $conversation->id);
2955         // We need to execute the return values cleaning process to simulate the web service server.
2956         $result = external_api::clean_returnvalue(core_message_external::get_conversation_messages_returns(),
2957             $result);
2959         // Check the results are correct.
2960         $this->assertEquals($conversation->id, $result['id']);
2962         // Confirm the members data is correct.
2963         $members = $result['members'];
2964         $this->assertCount(3, $members);
2965         $membersid = [$members[0]['id'], $members[1]['id'], $members[2]['id']];
2966         $this->assertContainsEquals($user1->id, $membersid);
2967         $this->assertContainsEquals($user2->id, $membersid);
2968         $this->assertContainsEquals($user3->id, $membersid);
2970         // Confirm the message data is correct.
2971         $messages = $result['messages'];
2972         $this->assertCount(4, $messages);
2974         $message1 = $messages[0];
2975         $message2 = $messages[1];
2976         $message3 = $messages[2];
2977         $message4 = $messages[3];
2979         $this->assertEquals($user1->id, $message1['useridfrom']);
2980         $this->assertStringContainsString('Yo!', $message1['text']);
2982         $this->assertEquals($user3->id, $message2['useridfrom']);
2983         $this->assertStringContainsString('Sup mang?', $message2['text']);
2985         $this->assertEquals($user2->id, $message3['useridfrom']);
2986         $this->assertStringContainsString('Writing PHPUnit tests!', $message3['text']);
2988         $this->assertEquals($user1->id, $message4['useridfrom']);
2989         $this->assertStringContainsString('Word.', $message4['text']);
2990     }
2992     /**
2993      * Tests get_conversation_messages for retrieving messages as another user without the proper capabilities.
2994      */
2995     public function test_get_conversation_messages_as_other_user_without_cap() {
2996         $this->resetAfterTest(true);
2998         // Create some users.
2999         $user1 = self::getDataGenerator()->create_user();
3000         $user2 = self::getDataGenerator()->create_user();
3001         $user3 = self::getDataGenerator()->create_user();
3002         $user4 = self::getDataGenerator()->create_user();
3004         // Create group conversation.
3005         $conversation = \core_message\api::create_conversation(
3006             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3007             [$user1->id, $user2->id, $user3->id, $user4->id]
3008         );
3010         // The person asking for the messages for another user.
3011         $this->setUser($user1);
3013         // Ensure an exception is thrown.
3014         $this->expectException('moodle_exception');
3015         core_message_external::get_conversation_messages($user2->id, $conversation->id);
3016     }
3018     /**
3019      * Tests get_conversation_messages for retrieving messages as another user not in the conversation.
3020      */
3021     public function test_get_conversation_messages_as_user_not_in_conversation() {
3022         $this->resetAfterTest(true);
3024         // Create some users.
3025         $user1 = self::getDataGenerator()->create_user();
3026         $user2 = self::getDataGenerator()->create_user();
3027         $user3 = self::getDataGenerator()->create_user(); // Not in group.
3029         // Create group conversation.
3030         $conversation = \core_message\api::create_conversation(
3031             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3032             [$user1->id, $user2->id]
3033         );
3035         // The person asking for the messages for a conversation he does not belong to.
3036         $this->setUser($user3);
3038         // Ensure an exception is thrown.
3039         $this->expectExceptionMessage('User is not part of conversation.');
3040         core_message_external::get_conversation_messages($user3->id, $conversation->id);
3041     }
3043     /**
3044      * Tests get_conversation_messages for retrieving messages with messaging disabled.
3045      */
3046     public function test_get_conversation_messages_messaging_disabled() {
3047         $this->resetAfterTest(true);
3049         // Create some skeleton data just so we can call the WS.
3050         $user1 = self::getDataGenerator()->create_user();
3051         $user2 = self::getDataGenerator()->create_user();
3052         $user3 = self::getDataGenerator()->create_user();
3053         $user4 = self::getDataGenerator()->create_user();
3055         // Create group conversation.
3056         $conversation = \core_message\api::create_conversation(
3057             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3058             [$user1->id, $user2->id, $user3->id, $user4->id]
3059         );
3061         // The person asking for the messages for another user.
3062         $this->setUser($user1);
3064         // Disable messaging.
3065         set_config('messaging', 0);
3067         // Ensure an exception is thrown.
3068         $this->expectException('moodle_exception');
3069         core_message_external::get_conversation_messages($user1->id, $conversation->id);
3070     }
3072     /**
3073      * Test marking all conversation messages as read with an invalid user.
3074      */
3075     public function test_mark_all_conversation_messages_as_read_invalid_user_exception() {
3076         $this->resetAfterTest(true);
3078         $user1 = self::getDataGenerator()->create_user();
3079         $user2 = self::getDataGenerator()->create_user();
3081         // Send some messages back and forth.
3082         $time = time();
3083         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3084         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3085         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3086         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3088         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3090         $this->expectException('moodle_exception');
3091         core_message_external::mark_all_conversation_messages_as_read(-2132131, $conversationid);
3092     }
3094     /**
3095      * Test marking all conversation messages as read without proper access.
3096      */
3097     public function test_mark_all_conversation_messages_as_read_access_denied_exception() {
3098         $this->resetAfterTest(true);
3100         $user1 = self::getDataGenerator()->create_user();
3101         $user2 = self::getDataGenerator()->create_user();
3102         $user3 = self::getDataGenerator()->create_user();
3104         // Send some messages back and forth.
3105         $time = time();
3106         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3107         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3108         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3109         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3111         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3113         // User 3 is not in the conversation.
3114         $this->expectException('moodle_exception');
3115         core_message_external::mark_all_conversation_messages_as_read($user3->id, $conversationid);
3116     }
3118     /**
3119      * Test marking all conversation messages as read for another user.
3120      */
3121     public function test_mark_all_conversation_messages_as_read_wrong_user() {
3122         $this->resetAfterTest(true);
3124         $user1 = self::getDataGenerator()->create_user();
3125         $user2 = self::getDataGenerator()->create_user();
3127         // Send some messages back and forth.
3128         $time = time();
3129         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3130         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3131         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3132         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3134         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3136         // Can't mark the messages as read for user 2.
3137         $this->setUser($user1);
3138         $this->expectException('moodle_exception');
3139         core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid);
3140     }
3142     /**
3143      * Test marking all conversation messages as admin.
3144      */
3145     public function test_mark_all_conversation_messages_as_admin() {
3146         global $DB;
3148         $this->resetAfterTest(true);
3150         $user1 = self::getDataGenerator()->create_user();
3151         $user2 = self::getDataGenerator()->create_user();
3153         // Send some messages back and forth.
3154         $time = time();
3155         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3156         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3157         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3158         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3160         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3162         // Admin can do anything.
3163         $this->setAdminUser();
3164         core_message_external::mark_all_conversation_messages_as_read($user2->id, $conversationid);
3165         $this->assertEquals(2, $DB->count_records('message_user_actions'));
3166     }
3168     /**
3169      * Test marking all conversation messages.
3170      */
3171     public function test_mark_all_conversation_messages_as_read() {
3172         global $DB;
3174         $this->resetAfterTest(true);
3176         $user1 = self::getDataGenerator()->create_user();
3177         $user2 = self::getDataGenerator()->create_user();
3179         // Send some messages back and forth.
3180         $time = time();
3181         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3182         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3183         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3184         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3186         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3188         // We are the user we want to mark the messages for and we are in the conversation, all good.
3189         $this->setUser($user1);
3190         core_message_external::mark_all_conversation_messages_as_read($user1->id, $conversationid);
3191         $this->assertEquals(2, $DB->count_records('message_user_actions'));
3192     }
3194     /**
3195      * Test getting unread conversation count.
3196      */
3197     public function test_get_unread_conversations_count() {
3198         $this->resetAfterTest(true);
3200         // Create some users.
3201         $user1 = self::getDataGenerator()->create_user();
3202         $user2 = self::getDataGenerator()->create_user();
3203         $user3 = self::getDataGenerator()->create_user();
3204         $user4 = self::getDataGenerator()->create_user();
3206         // The person wanting the conversation count.
3207         $this->setUser($user1);
3209         // Send some messages back and forth, have some different conversations with different users.
3210         $this->send_message($user1, $user2, 'Yo!');
3211         $this->send_message($user2, $user1, 'Sup mang?');
3212         $this->send_message($user1, $user2, 'Writing PHPUnit tests!');
3213         $this->send_message($user2, $user1, 'Word.');
3215         $this->send_message($user1, $user3, 'Booyah');
3216         $this->send_message($user3, $user1, 'Whaaat?');
3217         $this->send_message($user1, $user3, 'Nothing.');
3218         $this->send_message($user3, $user1, 'Cool.');
3220         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3221         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3222         $this->send_message($user1, $user4, 'Dope.');
3224         // Get the unread conversation count.
3225         $result = core_message_external::get_unread_conversations_count($user1->id);
3227         // We need to execute the return values cleaning process to simulate the web service server.
3228         $result = external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(),
3229             $result);
3231         $this->assertEquals(3, $result);
3232     }
3234     /**
3235      * Test getting unread conversation count as other user.
3236      */
3237     public function test_get_unread_conversations_count_as_other_user() {
3238         $this->resetAfterTest(true);
3240         // The person wanting the conversation count.
3241         $this->setAdminUser();
3243         // Create some users.
3244         $user1 = self::getDataGenerator()->create_user();
3245         $user2 = self::getDataGenerator()->create_user();
3246         $user3 = self::getDataGenerator()->create_user();
3247         $user4 = self::getDataGenerator()->create_user();
3249         // Send some messages back and forth, have some different conversations with different users.
3250         $this->send_message($user1, $user2, 'Yo!');
3251         $this->send_message($user2, $user1, 'Sup mang?');
3252         $this->send_message($user1, $user2, 'Writing PHPUnit tests!');
3253         $this->send_message($user2, $user1, 'Word.');
3255         $this->send_message($user1, $user3, 'Booyah');
3256         $this->send_message($user3, $user1, 'Whaaat?');
3257         $this->send_message($user1, $user3, 'Nothing.');
3258         $this->send_message($user3, $user1, 'Cool.');
3260         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3261         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3262         $this->send_message($user1, $user4, 'Dope.');
3264         // Get the unread conversation count.
3265         $result = core_message_external::get_unread_conversations_count($user1->id);
3267         // We need to execute the return values cleaning process to simulate the web service server.
3268         $result = external_api::clean_returnvalue(core_message_external::get_unread_conversations_count_returns(),
3269             $result);
3271         $this->assertEquals(3, $result);
3272     }
3274     /**
3275      * Test getting unread conversation count as other user without proper capability.
3276      */
3277     public function test_get_unread_conversations_count_as_other_user_without_cap() {
3278         $this->resetAfterTest(true);
3280         // Create some users.
3281         $user1 = self::getDataGenerator()->create_user();
3282         $user2 = self::getDataGenerator()->create_user();
3284         // The person wanting the conversation count.
3285         $this->setUser($user1);
3287         // Ensure an exception is thrown.
3288         $this->expectException('moodle_exception');
3289         core_message_external::get_unread_conversations_count($user2->id);
3290     }
3292     /**
3293      * Test deleting conversations.
3294      */
3295     public function test_delete_conversations_by_id() {
3296         global $DB;
3298         $this->resetAfterTest(true);
3300         // Create some users.
3301         $user1 = self::getDataGenerator()->create_user();
3302         $user2 = self::getDataGenerator()->create_user();
3304         // The person wanting to delete the conversation.
3305         $this->setUser($user1);
3307         // Send some messages back and forth.
3308         $time = time();
3309         $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time);
3310         $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3311         $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3312         $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3314         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3316         // Delete the conversation.
3317         core_message_external::delete_conversations_by_id($user1->id, [$conversationid]);
3319         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3320         $this->assertCount(4, $muas);
3321         // Sort by id.
3322         ksort($muas);
3324         $mua1 = array_shift($muas);
3325         $mua2 = array_shift($muas);
3326         $mua3 = array_shift($muas);
3327         $mua4 = array_shift($muas);
3329         $this->assertEquals($user1->id, $mua1->userid);
3330         $this->assertEquals($m1id, $mua1->messageid);
3331         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3333         $this->assertEquals($user1->id, $mua2->userid);
3334         $this->assertEquals($m2id, $mua2->messageid);
3335         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
3337         $this->assertEquals($user1->id, $mua3->userid);
3338         $this->assertEquals($m3id, $mua3->messageid);
3339         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
3341         $this->assertEquals($user1->id, $mua4->userid);
3342         $this->assertEquals($m4id, $mua4->messageid);
3343         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
3344     }
3346     /**
3347      * Test deleting conversations as other user.
3348      */
3349     public function test_delete_conversations_by_id_as_other_user() {
3350         global $DB;
3352         $this->resetAfterTest(true);
3354         $this->setAdminUser();
3356         // Create some users.
3357         $user1 = self::getDataGenerator()->create_user();
3358         $user2 = self::getDataGenerator()->create_user();
3360         // Send some messages back and forth.
3361         $time = time();
3362         $m1id = $this->send_message($user1, $user2, 'Yo!', 0, $time);
3363         $m2id = $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3364         $m3id = $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3365         $m4id = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3367         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3369         // Delete the conversation.
3370         core_message_external::delete_conversations_by_id($user1->id, [$conversationid]);
3372         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3373         $this->assertCount(4, $muas);
3374         // Sort by id.
3375         ksort($muas);
3377         $mua1 = array_shift($muas);
3378         $mua2 = array_shift($muas);
3379         $mua3 = array_shift($muas);
3380         $mua4 = array_shift($muas);
3382         $this->assertEquals($user1->id, $mua1->userid);
3383         $this->assertEquals($m1id, $mua1->messageid);
3384         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3386         $this->assertEquals($user1->id, $mua2->userid);
3387   &nbs