Merge branch 'MDL-63974-master' of https://github.com/snake/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() {
41         global $CFG;
43         require_once($CFG->dirroot . '/message/lib.php');
44     }
46     /**
47      * Send a fake message.
48      *
49      * {@link message_send()} does not support transaction, this function will simulate a message
50      * sent from a user to another. We should stop using it once {@link message_send()} will support
51      * transactions. This is not clean at all, this is just used to add rows to the table.
52      *
53      * @param stdClass $userfrom user object of the one sending the message.
54      * @param stdClass $userto user object of the one receiving the message.
55      * @param string $message message to send.
56      * @param int $notification is the message a notification.
57      * @param int $time the time the message was sent
58      */
59     protected function send_message($userfrom, $userto, $message = 'Hello world!', $notification = 0, $time = 0) {
60         global $DB;
62         if (empty($time)) {
63             $time = time();
64         }
66         if ($notification) {
67             $record = new stdClass();
68             $record->useridfrom = $userfrom->id;
69             $record->useridto = $userto->id;
70             $record->subject = 'No subject';
71             $record->fullmessage = $message;
72             $record->smallmessage = $message;
73             $record->timecreated = $time;
75             return $DB->insert_record('notifications', $record);
76         }
78         if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) {
79             $conversation = \core_message\api::create_conversation(
80                 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
81                 [
82                     $userfrom->id,
83                     $userto->id
84                 ]
85             );
86             $conversationid = $conversation->id;
87         }
89         // Ok, send the message.
90         $record = new stdClass();
91         $record->useridfrom = $userfrom->id;
92         $record->conversationid = $conversationid;
93         $record->subject = 'No subject';
94         $record->fullmessage = $message;
95         $record->smallmessage = $message;
96         $record->timecreated = $time;
98         return $DB->insert_record('messages', $record);
99     }
101     /**
102      * Test send_instant_messages.
103      */
104     public function test_send_instant_messages() {
105         global $DB, $USER;
107         $this->resetAfterTest();
109         // Transactions used in tests, tell phpunit use alternative reset method.
110         $this->preventResetByRollback();
112         $user1 = self::getDataGenerator()->create_user();
113         $user2 = self::getDataGenerator()->create_user();
115         $this->setUser($user1);
117         // Create test message data.
118         $message1 = array();
119         $message1['touserid'] = $user2->id;
120         $message1['text'] = 'the message.';
121         $message1['clientmsgid'] = 4;
122         $messages = array($message1);
124         $sentmessages = core_message_external::send_instant_messages($messages);
125         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
126         $this->assertEquals(
127             get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message1['touserid']))),
128             array_pop($sentmessages)['errormessage']
129         );
131         // Add the user1 as a contact.
132         \core_message\api::add_contact($user1->id, $user2->id);
134         // Send message again. Now it should work properly.
135         $sentmessages = core_message_external::send_instant_messages($messages);
136         // We need to execute the return values cleaning process to simulate the web service server.
137         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
139         $sentmessage = reset($sentmessages);
141         $sql = "SELECT m.*, mcm.userid as useridto
142                  FROM {messages} m
143            INNER JOIN {message_conversations} mc
144                    ON m.conversationid = mc.id
145            INNER JOIN {message_conversation_members} mcm
146                    ON mcm.conversationid = mc.id
147                 WHERE mcm.userid != ?
148                   AND m.id = ?";
149         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
151         // Confirm that the message was inserted correctly.
152         $this->assertEquals($themessage->useridfrom, $user1->id);
153         $this->assertEquals($themessage->useridto, $message1['touserid']);
154         $this->assertEquals($themessage->smallmessage, $message1['text']);
155         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
156     }
158     /**
159      * Test send_instant_messages to a user who has blocked you.
160      */
161     public function test_send_instant_messages_blocked_user() {
162         global $DB;
164         $this->resetAfterTest();
166         // Transactions used in tests, tell phpunit use alternative reset method.
167         $this->preventResetByRollback();
169         $user1 = self::getDataGenerator()->create_user();
170         $user2 = self::getDataGenerator()->create_user();
172         $this->setUser($user1);
174         \core_message\api::block_user($user2->id, $user1->id);
176         // Create test message data.
177         $message1 = array();
178         $message1['touserid'] = $user2->id;
179         $message1['text'] = 'the message.';
180         $message1['clientmsgid'] = 4;
181         $messages = array($message1);
183         $sentmessages = core_message_external::send_instant_messages($messages);
184         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
186         $sentmessage = reset($sentmessages);
188         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
190         $this->assertEquals(0, $DB->count_records('messages'));
191     }
193     /**
194      * Test send_instant_messages when sending a message to a non-contact who has blocked non-contacts.
195      */
196     public function test_send_instant_messages_block_non_contacts() {
197         global $DB;
199         $this->resetAfterTest(true);
201         // Transactions used in tests, tell phpunit use alternative reset method.
202         $this->preventResetByRollback();
204         $user1 = self::getDataGenerator()->create_user();
205         $user2 = self::getDataGenerator()->create_user();
207         $this->setUser($user1);
209         // Set the user preference so user 2 does not accept messages from non-contacts.
210         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
212         // Create test message data.
213         $message1 = array();
214         $message1['touserid'] = $user2->id;
215         $message1['text'] = 'the message.';
216         $message1['clientmsgid'] = 4;
217         $messages = array($message1);
219         $sentmessages = core_message_external::send_instant_messages($messages);
220         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
222         $sentmessage = reset($sentmessages);
224         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
226         $this->assertEquals(0, $DB->count_records('messages'));
227     }
229     /**
230      * Test send_instant_messages when sending a message to a contact who has blocked non-contacts.
231      */
232     public function test_send_instant_messages_block_non_contacts_but_am_contact() {
233         global $DB, $USER;
235         $this->resetAfterTest(true);
237         // Transactions used in tests, tell phpunit use alternative reset method.
238         $this->preventResetByRollback();
240         $user1 = self::getDataGenerator()->create_user();
241         $user2 = self::getDataGenerator()->create_user();
243         $this->setUser($user1);
245         // Set the user preference so user 2 does not accept messages from non-contacts.
246         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
248         \core_message\api::add_contact($user1->id, $user2->id);
250         // Create test message data.
251         $message1 = array();
252         $message1['touserid'] = $user2->id;
253         $message1['text'] = 'the message.';
254         $message1['clientmsgid'] = 4;
255         $messages = array($message1);
257         $sentmessages = core_message_external::send_instant_messages($messages);
258         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
260         $sentmessage = reset($sentmessages);
262         $sql = "SELECT m.*, mcm.userid as useridto
263                  FROM {messages} m
264            INNER JOIN {message_conversations} mc
265                    ON m.conversationid = mc.id
266            INNER JOIN {message_conversation_members} mcm
267                    ON mcm.conversationid = mc.id
268                 WHERE mcm.userid != ?
269                   AND m.id = ?";
270         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
272         // Confirm that the message was inserted correctly.
273         $this->assertEquals($themessage->useridfrom, $user1->id);
274         $this->assertEquals($themessage->useridto, $message1['touserid']);
275         $this->assertEquals($themessage->smallmessage, $message1['text']);
276         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
277     }
279     /**
280      * Test send_instant_messages with no capabilities
281      */
282     public function test_send_instant_messages_no_capability() {
283         global $DB;
285         $this->resetAfterTest(true);
287         // Transactions used in tests, tell phpunit use alternative reset method.
288         $this->preventResetByRollback();
290         $user1 = self::getDataGenerator()->create_user();
291         $user2 = self::getDataGenerator()->create_user();
293         $this->setUser($user1);
295         // Unset the required capabilities by the external function.
296         $contextid = context_system::instance()->id;
297         $userrole = $DB->get_record('role', array('shortname' => 'user'));
298         $this->unassignUserCapability('moodle/site:sendmessage', $contextid, $userrole->id);
300         // Create test message data.
301         $message1 = array();
302         $message1['touserid'] = $user2->id;
303         $message1['text'] = 'the message.';
304         $message1['clientmsgid'] = 4;
305         $messages = array($message1);
307         $this->expectException('required_capability_exception');
308         core_message_external::send_instant_messages($messages);
309     }
311     /**
312      * Test send_instant_messages when messaging is disabled.
313      */
314     public function test_send_instant_messages_messaging_disabled() {
315         global $CFG;
317         $this->resetAfterTest(true);
319         // Transactions used in tests, tell phpunit use alternative reset method.
320         $this->preventResetByRollback();
322         $user1 = self::getDataGenerator()->create_user();
323         $user2 = self::getDataGenerator()->create_user();
325         $this->setUser($user1);
327         // Disable messaging.
328         $CFG->messaging = 0;
330         // Create test message data.
331         $message1 = array();
332         $message1['touserid'] = $user2->id;
333         $message1['text'] = 'the message.';
334         $message1['clientmsgid'] = 4;
335         $messages = array($message1);
337         $this->expectException('moodle_exception');
338         core_message_external::send_instant_messages($messages);
339     }
341     /**
342      * Test create_contacts.
343      */
344     public function test_create_contacts() {
345         $this->resetAfterTest(true);
347         $user1 = self::getDataGenerator()->create_user();
348         $user2 = self::getDataGenerator()->create_user();
349         $user3 = self::getDataGenerator()->create_user();
350         $user4 = self::getDataGenerator()->create_user();
351         $user5 = self::getDataGenerator()->create_user();
352         $this->setUser($user1);
354         // Adding a contact.
355         $return = core_message_external::create_contacts(array($user2->id));
356         $this->assertDebuggingCalled();
357         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
358         $this->assertEquals(array(), $return);
360         // Adding a contact who is already a contact.
361         $return = core_message_external::create_contacts(array($user2->id));
362         $this->assertDebuggingCalled();
363         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
364         $this->assertEquals(array(), $return);
366         // Adding multiple contacts.
367         $return = core_message_external::create_contacts(array($user3->id, $user4->id));
368         $this->assertDebuggingCalledCount(2);
369         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
370         $this->assertEquals(array(), $return);
372         // Adding a non-existing user.
373         $return = core_message_external::create_contacts(array(99999));
374         $this->assertDebuggingCalled();
375         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
376         $this->assertCount(1, $return);
377         $return = array_pop($return);
378         $this->assertEquals($return['warningcode'], 'contactnotcreated');
379         $this->assertEquals($return['itemid'], 99999);
381         // Adding contacts with valid and invalid parameters.
382         $return = core_message_external::create_contacts(array($user5->id, 99999));
383         $this->assertDebuggingCalledCount(2);
384         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
385         $this->assertCount(1, $return);
386         $return = array_pop($return);
387         $this->assertEquals($return['warningcode'], 'contactnotcreated');
388         $this->assertEquals($return['itemid'], 99999);
390         // Try to add a contact to another user, should throw an exception.
391         // All assertions must be added before this point.
392         $this->expectException('required_capability_exception');
393         core_message_external::create_contacts(array($user2->id), $user3->id);
394     }
396     /**
397      * Test delete_contacts.
398      */
399     public function test_delete_contacts() {
400         $this->resetAfterTest(true);
402         $user1 = self::getDataGenerator()->create_user();
403         $user2 = self::getDataGenerator()->create_user();
404         $user3 = self::getDataGenerator()->create_user();
405         $user4 = self::getDataGenerator()->create_user();
406         $user5 = self::getDataGenerator()->create_user();
407         $user6 = self::getDataGenerator()->create_user();
408         $this->setUser($user1);
410         \core_message\api::add_contact($user1->id, $user3->id);
411         \core_message\api::add_contact($user1->id, $user4->id);
412         \core_message\api::add_contact($user1->id, $user5->id);
413         \core_message\api::add_contact($user1->id, $user6->id);
415         // Removing a non-contact.
416         $return = core_message_external::delete_contacts(array($user2->id));
417         $this->assertNull($return);
419         // Removing one contact.
420         $return = core_message_external::delete_contacts(array($user3->id));
421         $this->assertNull($return);
423         // Removing multiple contacts.
424         $return = core_message_external::delete_contacts(array($user4->id, $user5->id));
425         $this->assertNull($return);
427         // Removing contact from unexisting user.
428         $return = core_message_external::delete_contacts(array(99999));
429         $this->assertNull($return);
431         // Removing mixed valid and invalid data.
432         $return = core_message_external::delete_contacts(array($user6->id, 99999));
433         $this->assertNull($return);
435         // Try to delete a contact of another user contact list, should throw an exception.
436         // All assertions must be added before this point.
437         $this->expectException('required_capability_exception');
438         core_message_external::delete_contacts(array($user2->id), $user3->id);
439     }
441     /**
442      * Test block_contacts.
443      */
444     public function test_block_contacts() {
445         $this->resetAfterTest(true);
447         $user1 = self::getDataGenerator()->create_user();
448         $user2 = self::getDataGenerator()->create_user();
449         $user3 = self::getDataGenerator()->create_user();
450         $user4 = self::getDataGenerator()->create_user();
451         $user5 = self::getDataGenerator()->create_user();
452         $this->setUser($user1);
454         \core_message\api::add_contact($user1->id, $user3->id);
455         \core_message\api::add_contact($user1->id, $user4->id);
456         \core_message\api::add_contact($user1->id, $user5->id);
458         // Blocking a contact.
459         $return = core_message_external::block_contacts(array($user2->id));
460         $this->assertDebuggingCalled();
461         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
462         $this->assertEquals(array(), $return);
464         // Blocking a contact who is already a contact.
465         $return = core_message_external::block_contacts(array($user2->id));
466         $this->assertDebuggingCalled();
467         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
468         $this->assertEquals(array(), $return);
470         // Blocking multiple contacts.
471         $return = core_message_external::block_contacts(array($user3->id, $user4->id));
472         $this->assertDebuggingCalledCount(2);
473         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
474         $this->assertEquals(array(), $return);
476         // Blocking a non-existing user.
477         $return = core_message_external::block_contacts(array(99999));
478         $this->assertDebuggingCalled();
479         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
480         $this->assertCount(1, $return);
481         $return = array_pop($return);
482         $this->assertEquals($return['warningcode'], 'contactnotblocked');
483         $this->assertEquals($return['itemid'], 99999);
485         // Blocking contacts with valid and invalid parameters.
486         $return = core_message_external::block_contacts(array($user5->id, 99999));
487         $this->assertDebuggingCalledCount(2);
488         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
489         $this->assertCount(1, $return);
490         $return = array_pop($return);
491         $this->assertEquals($return['warningcode'], 'contactnotblocked');
492         $this->assertEquals($return['itemid'], 99999);
494         // Try to block a contact of another user contact list, should throw an exception.
495         // All assertions must be added before this point.
496         $this->expectException('required_capability_exception');
497         core_message_external::block_contacts(array($user2->id), $user3->id);
498     }
500     /**
501      * Test unblock_contacts.
502      */
503     public function test_unblock_contacts() {
504         $this->resetAfterTest(true);
506         $user1 = self::getDataGenerator()->create_user();
507         $user2 = self::getDataGenerator()->create_user();
508         $user3 = self::getDataGenerator()->create_user();
509         $user4 = self::getDataGenerator()->create_user();
510         $user5 = self::getDataGenerator()->create_user();
511         $user6 = self::getDataGenerator()->create_user();
512         $this->setUser($user1);
514         \core_message\api::add_contact($user1->id, $user3->id);
515         \core_message\api::add_contact($user1->id, $user4->id);
516         \core_message\api::add_contact($user1->id, $user5->id);
517         \core_message\api::add_contact($user1->id, $user6->id);
519         // Removing a non-contact.
520         $return = core_message_external::unblock_contacts(array($user2->id));
521         $this->assertDebuggingCalled();
522         $this->assertNull($return);
524         // Removing one contact.
525         $return = core_message_external::unblock_contacts(array($user3->id));
526         $this->assertDebuggingCalled();
527         $this->assertNull($return);
529         // Removing multiple contacts.
530         $return = core_message_external::unblock_contacts(array($user4->id, $user5->id));
531         $this->assertDebuggingCalledCount(2);
532         $this->assertNull($return);
534         // Removing contact from unexisting user.
535         $return = core_message_external::unblock_contacts(array(99999));
536         $this->assertDebuggingCalled();
537         $this->assertNull($return);
539         // Removing mixed valid and invalid data.
540         $return = core_message_external::unblock_contacts(array($user6->id, 99999));
541         $this->assertDebuggingCalledCount(2);
542         $this->assertNull($return);
544         // Try to unblock a contact of another user contact list, should throw an exception.
545         // All assertions must be added before this point.
546         $this->expectException('required_capability_exception');
547         core_message_external::unblock_contacts(array($user2->id), $user3->id);
548         $this->assertDebuggingCalled();
549     }
551     /**
552      * Test getting contact requests.
553      */
554     public function test_get_contact_requests() {
555         $this->resetAfterTest();
557         $user1 = self::getDataGenerator()->create_user();
558         $user2 = self::getDataGenerator()->create_user();
559         $user3 = self::getDataGenerator()->create_user();
561         $this->setUser($user1);
563         // Block one user, their request should not show up.
564         \core_message\api::block_user($user1->id, $user3->id);
566         \core_message\api::create_contact_request($user2->id, $user1->id);
567         \core_message\api::create_contact_request($user3->id, $user1->id);
569         $requests = core_message_external::get_contact_requests($user1->id);
570         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
572         $this->assertCount(1, $requests);
574         $request = reset($requests);
576         $this->assertEquals($user2->id, $request['id']);
577         $this->assertEquals(fullname($user2), $request['fullname']);
578         $this->assertArrayHasKey('profileimageurl', $request);
579         $this->assertArrayHasKey('profileimageurlsmall', $request);
580         $this->assertArrayHasKey('isonline', $request);
581         $this->assertArrayHasKey('showonlinestatus', $request);
582         $this->assertArrayHasKey('isblocked', $request);
583         $this->assertArrayHasKey('iscontact', $request);
584     }
586     /**
587      * Test getting contact requests when there are none.
588      */
589     public function test_get_contact_requests_no_requests() {
590         $this->resetAfterTest();
592         $user1 = self::getDataGenerator()->create_user();
594         $this->setUser($user1);
596         $requests = core_message_external::get_contact_requests($user1->id);
597         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
599         $this->assertEmpty($requests);
600     }
602     /**
603      * Test getting contact requests with limits.
604      */
605     public function test_get_contact_requests_with_limits() {
606         $this->resetAfterTest();
608         $user1 = self::getDataGenerator()->create_user();
609         $user2 = self::getDataGenerator()->create_user();
610         $user3 = self::getDataGenerator()->create_user();
612         $this->setUser($user1);
614         \core_message\api::create_contact_request($user2->id, $user1->id);
615         \core_message\api::create_contact_request($user3->id, $user1->id);
617         $requests = core_message_external::get_contact_requests($user1->id, 0, 1);
618         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
620         $this->assertCount(1, $requests);
621     }
623     /**
624      * Test getting contact requests with messaging disabled.
625      */
626     public function test_get_contact_requests_messaging_disabled() {
627         global $CFG;
629         $this->resetAfterTest();
631         // Create some skeleton data just so we can call the WS.
632         $user1 = self::getDataGenerator()->create_user();
634         $this->setUser($user1);
636         // Disable messaging.
637         $CFG->messaging = 0;
639         // Ensure an exception is thrown.
640         $this->expectException('moodle_exception');
641         core_message_external::get_contact_requests($user1->id);
642     }
644     /**
645      * Test getting contact requests with no permission.
646      */
647     public function test_get_contact_requests_no_permission() {
648         $this->resetAfterTest();
650         // Create some skeleton data just so we can call the WS.
651         $user1 = self::getDataGenerator()->create_user();
652         $user2 = self::getDataGenerator()->create_user();
653         $user3 = self::getDataGenerator()->create_user();
655         $this->setUser($user3);
657         // Ensure an exception is thrown.
658         $this->expectException('required_capability_exception');
659         core_message_external::create_contact_request($user1->id, $user2->id);
660     }
662     /**
663      * Test creating a contact request.
664      */
665     public function test_create_contact_request() {
666         global $CFG, $DB;
668         $this->resetAfterTest();
670         $user1 = self::getDataGenerator()->create_user();
671         $user2 = self::getDataGenerator()->create_user();
673         $this->setUser($user1);
675         // Allow users to message anyone site-wide.
676         $CFG->messagingallusers = 1;
678         $return = core_message_external::create_contact_request($user1->id, $user2->id);
679         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
680         $this->assertEquals(array(), $return);
682         $request = $DB->get_records('message_contact_requests');
684         $this->assertCount(1, $request);
686         $request = reset($request);
688         $this->assertEquals($user1->id, $request->userid);
689         $this->assertEquals($user2->id, $request->requesteduserid);
690     }
692     /**
693      * Test creating a contact request when not allowed.
694      */
695     public function test_create_contact_request_not_allowed() {
696         global $CFG;
698         $this->resetAfterTest();
700         $user1 = self::getDataGenerator()->create_user();
701         $user2 = self::getDataGenerator()->create_user();
703         $this->setUser($user1);
705         $CFG->messagingallusers = 0;
707         $return = core_message_external::create_contact_request($user1->id, $user2->id);
708         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
710         $warning = reset($return);
712         $this->assertEquals('user', $warning['item']);
713         $this->assertEquals($user2->id, $warning['itemid']);
714         $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']);
715         $this->assertEquals('You are unable to create a contact request for this user', $warning['message']);
716     }
718     /**
719      * Test creating a contact request with messaging disabled.
720      */
721     public function test_create_contact_request_messaging_disabled() {
722         global $CFG;
724         $this->resetAfterTest();
726         // Create some skeleton data just so we can call the WS.
727         $user1 = self::getDataGenerator()->create_user();
728         $user2 = self::getDataGenerator()->create_user();
730         $this->setUser($user1);
732         // Disable messaging.
733         $CFG->messaging = 0;
735         // Ensure an exception is thrown.
736         $this->expectException('moodle_exception');
737         core_message_external::create_contact_request($user1->id, $user2->id);
738     }
740     /**
741      * Test creating a contact request with no permission.
742      */
743     public function test_create_contact_request_no_permission() {
744         $this->resetAfterTest();
746         // Create some skeleton data just so we can call the WS.
747         $user1 = self::getDataGenerator()->create_user();
748         $user2 = self::getDataGenerator()->create_user();
749         $user3 = self::getDataGenerator()->create_user();
751         $this->setUser($user3);
753         // Ensure an exception is thrown.
754         $this->expectException('required_capability_exception');
755         core_message_external::create_contact_request($user1->id, $user2->id);
756     }
758     /**
759      * Test confirming a contact request.
760      */
761     public function test_confirm_contact_request() {
762         global $DB;
764         $this->resetAfterTest();
766         $user1 = self::getDataGenerator()->create_user();
767         $user2 = self::getDataGenerator()->create_user();
769         $this->setUser($user1);
771         \core_message\api::create_contact_request($user1->id, $user2->id);
773         $this->setUser($user2);
775         $return = core_message_external::confirm_contact_request($user1->id, $user2->id);
776         $return = external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return);
777         $this->assertEquals(array(), $return);
779         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
781         $contact = $DB->get_records('message_contacts');
783         $this->assertCount(1, $contact);
785         $contact = reset($contact);
787         $this->assertEquals($user1->id, $contact->userid);
788         $this->assertEquals($user2->id, $contact->contactid);
789     }
791     /**
792      * Test confirming a contact request with messaging disabled.
793      */
794     public function test_confirm_contact_request_messaging_disabled() {
795         global $CFG;
797         $this->resetAfterTest();
799         // Create some skeleton data just so we can call the WS.
800         $user1 = self::getDataGenerator()->create_user();
801         $user2 = self::getDataGenerator()->create_user();
803         $this->setUser($user1);
805         // Disable messaging.
806         $CFG->messaging = 0;
808         // Ensure an exception is thrown.
809         $this->expectException('moodle_exception');
810         core_message_external::confirm_contact_request($user1->id, $user2->id);
811     }
813     /**
814      * Test confirming a contact request with no permission.
815      */
816     public function test_confirm_contact_request_no_permission() {
817         $this->resetAfterTest();
819         // Create some skeleton data just so we can call the WS.
820         $user1 = self::getDataGenerator()->create_user();
821         $user2 = self::getDataGenerator()->create_user();
822         $user3 = self::getDataGenerator()->create_user();
824         $this->setUser($user3);
826         // Ensure an exception is thrown.
827         $this->expectException('required_capability_exception');
828         core_message_external::confirm_contact_request($user1->id, $user2->id);
829     }
831     /**
832      * Test declining a contact request.
833      */
834     public function test_decline_contact_request() {
835         global $DB;
837         $this->resetAfterTest();
839         $user1 = self::getDataGenerator()->create_user();
840         $user2 = self::getDataGenerator()->create_user();
842         $this->setUser($user1);
844         \core_message\api::create_contact_request($user1->id, $user2->id);
846         $this->setUser($user2);
848         $return = core_message_external::decline_contact_request($user1->id, $user2->id);
849         $return = external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return);
850         $this->assertEquals(array(), $return);
852         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
853         $this->assertEquals(0, $DB->count_records('message_contacts'));
854     }
856     /**
857      * Test declining a contact request with messaging disabled.
858      */
859     public function test_decline_contact_request_messaging_disabled() {
860         global $CFG;
862         $this->resetAfterTest();
864         // Create some skeleton data just so we can call the WS.
865         $user1 = self::getDataGenerator()->create_user();
866         $user2 = self::getDataGenerator()->create_user();
868         $this->setUser($user1);
870         // Disable messaging.
871         $CFG->messaging = 0;
873         // Ensure an exception is thrown.
874         $this->expectException('moodle_exception');
875         core_message_external::decline_contact_request($user1->id, $user2->id);
876     }
878     /**
879      * Test declining a contact request with no permission.
880      */
881     public function test_decline_contact_request_no_permission() {
882         $this->resetAfterTest();
884         // Create some skeleton data just so we can call the WS.
885         $user1 = self::getDataGenerator()->create_user();
886         $user2 = self::getDataGenerator()->create_user();
887         $user3 = self::getDataGenerator()->create_user();
889         $this->setUser($user3);
891         // Ensure an exception is thrown.
892         $this->expectException('required_capability_exception');
893         core_message_external::decline_contact_request($user1->id, $user2->id);
894     }
896     /**
897      * Test blocking a user.
898      */
899     public function test_block_user() {
900         global $DB;
902         $this->resetAfterTest(true);
904         $user1 = self::getDataGenerator()->create_user();
905         $user2 = self::getDataGenerator()->create_user();
907         $this->setUser($user1);
909         // Blocking a user.
910         $return = core_message_external::block_user($user1->id, $user2->id);
911         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
912         $this->assertEquals(array(), $return);
914         // Get list of blocked users.
915         $record = $DB->get_record('message_users_blocked', []);
917         $this->assertEquals($user1->id, $record->userid);
918         $this->assertEquals($user2->id, $record->blockeduserid);
920         // Blocking a user who is already blocked.
921         $return = core_message_external::block_user($user1->id, $user2->id);
922         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
923         $this->assertEquals(array(), $return);
925         $this->assertEquals(1, $DB->count_records('message_users_blocked'));
926     }
928     /**
929      * Test blocking a user with messaging disabled.
930      */
931     public function test_block_user_messaging_disabled() {
932         global $CFG;
934         $this->resetAfterTest();
936         // Create some skeleton data just so we can call the WS.
937         $user1 = self::getDataGenerator()->create_user();
938         $user2 = self::getDataGenerator()->create_user();
940         $this->setUser($user1);
942         // Disable messaging.
943         $CFG->messaging = 0;
945         // Ensure an exception is thrown.
946         $this->expectException('moodle_exception');
947         core_message_external::block_user($user1->id, $user2->id);
948     }
950     /**
951      * Test blocking a user with no permission.
952      */
953     public function test_block_user_no_permission() {
954         $this->resetAfterTest();
956         // Create some skeleton data just so we can call the WS.
957         $user1 = self::getDataGenerator()->create_user();
958         $user2 = self::getDataGenerator()->create_user();
959         $user3 = self::getDataGenerator()->create_user();
961         $this->setUser($user3);
963         // Ensure an exception is thrown.
964         $this->expectException('required_capability_exception');
965         core_message_external::block_user($user1->id, $user2->id);
966     }
968     /**
969      * Test unblocking a user.
970      */
971     public function test_unblock_user() {
972         global $DB;
974         $this->resetAfterTest(true);
976         $user1 = self::getDataGenerator()->create_user();
977         $user2 = self::getDataGenerator()->create_user();
979         $this->setUser($user1);
981         // Block the user.
982         \core_message\api::block_user($user1->id, $user2->id);
984         // Unblocking a user.
985         $return = core_message_external::unblock_user($user1->id, $user2->id);
986         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
987         $this->assertEquals(array(), $return);
989         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
991         // Unblocking a user who is already unblocked.
992         $return = core_message_external::unblock_user($user1->id, $user2->id);
993         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
994         $this->assertEquals(array(), $return);
996         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
997     }
999     /**
1000      * Test unblocking a user with messaging disabled.
1001      */
1002     public function test_unblock_user_messaging_disabled() {
1003         global $CFG;
1005         $this->resetAfterTest();
1007         // Create some skeleton data just so we can call the WS.
1008         $user1 = self::getDataGenerator()->create_user();
1009         $user2 = self::getDataGenerator()->create_user();
1011         $this->setUser($user1);
1013         // Disable messaging.
1014         $CFG->messaging = 0;
1016         // Ensure an exception is thrown.
1017         $this->expectException('moodle_exception');
1018         core_message_external::unblock_user($user1->id, $user2->id);
1019     }
1021     /**
1022      * Test unblocking a user with no permission.
1023      */
1024     public function test_unblock_user_no_permission() {
1025         $this->resetAfterTest();
1027         // Create some skeleton data just so we can call the WS.
1028         $user1 = self::getDataGenerator()->create_user();
1029         $user2 = self::getDataGenerator()->create_user();
1030         $user3 = self::getDataGenerator()->create_user();
1032         $this->setUser($user3);
1034         // Ensure an exception is thrown.
1035         $this->expectException('required_capability_exception');
1036         core_message_external::unblock_user($user1->id, $user2->id);
1037     }
1039     /**
1040      * Test get_contacts.
1041      */
1042     public function test_get_contacts() {
1043         $this->resetAfterTest(true);
1045         $user1 = self::getDataGenerator()->create_user();
1046         $user_stranger = self::getDataGenerator()->create_user();
1047         $user_offline1 = self::getDataGenerator()->create_user();
1048         $user_offline2 = self::getDataGenerator()->create_user();
1049         $user_offline3 = self::getDataGenerator()->create_user();
1050         $user_online = new stdClass();
1051         $user_online->lastaccess = time();
1052         $user_online = self::getDataGenerator()->create_user($user_online);
1053         $user_blocked = self::getDataGenerator()->create_user();
1054         $noreplyuser = core_user::get_user(core_user::NOREPLY_USER);
1056         // Login as user1.
1057         $this->setUser($user1);
1058         \core_message\api::add_contact($user1->id, $user_offline1->id);
1059         \core_message\api::add_contact($user1->id, $user_offline2->id);
1060         \core_message\api::add_contact($user1->id, $user_offline3->id);
1061         \core_message\api::add_contact($user1->id, $user_online->id);
1063         // User_stranger sends a couple of messages to user1.
1064         $this->send_message($user_stranger, $user1, 'Hello there!');
1065         $this->send_message($user_stranger, $user1, 'How you goin?');
1066         $this->send_message($user_stranger, $user1, 'Cya!');
1067         $this->send_message($noreplyuser, $user1, 'I am not a real user');
1069         // User_blocked sends a message to user1.
1070         $this->send_message($user_blocked, $user1, 'Here, have some spam.');
1072         // Retrieve the contacts of the user.
1073         $this->setUser($user1);
1074         $contacts = core_message_external::get_contacts();
1075         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1076         $this->assertCount(3, $contacts['offline']);
1077         $this->assertCount(1, $contacts['online']);
1078         $this->assertCount(3, $contacts['strangers']);
1079         core_message_external::block_contacts(array($user_blocked->id));
1080         $this->assertDebuggingCalled();
1081         $contacts = core_message_external::get_contacts();
1082         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1083         $this->assertCount(3, $contacts['offline']);
1084         $this->assertCount(1, $contacts['online']);
1085         $this->assertCount(2, $contacts['strangers']);
1087         // Checking some of the fields returned.
1088         $stranger = array_pop($contacts['strangers']);
1090         $this->assertEquals(core_user::NOREPLY_USER, $stranger['id']);
1091         $this->assertEquals(1, $stranger['unread']);
1093         // Check that deleted users are not returned.
1094         delete_user($user_offline1);
1095         delete_user($user_stranger);
1096         delete_user($user_online);
1097         $contacts = core_message_external::get_contacts();
1098         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1099         $this->assertCount(2, $contacts['offline']);
1100         $this->assertCount(0, $contacts['online']);
1101         $this->assertCount(1, $contacts['strangers']);
1102     }
1104     /**
1105      * Test search_contacts.
1106      * @expectedException moodle_exception
1107      */
1108     public function test_search_contacts() {
1109         global $DB;
1110         $this->resetAfterTest(true);
1112         $course1 = $this->getDataGenerator()->create_course();
1113         $course2 = $this->getDataGenerator()->create_course();
1115         $user1 = new stdClass();
1116         $user1->firstname = 'X';
1117         $user1->lastname = 'X';
1118         $user1 = $this->getDataGenerator()->create_user($user1);
1119         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1120         $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1122         $user2 = new stdClass();
1123         $user2->firstname = 'Eric';
1124         $user2->lastname = 'Cartman';
1125         $user2 = self::getDataGenerator()->create_user($user2);
1126         $user3 = new stdClass();
1127         $user3->firstname = 'Stan';
1128         $user3->lastname = 'Marsh';
1129         $user3 = self::getDataGenerator()->create_user($user3);
1130         self::getDataGenerator()->enrol_user($user3->id, $course1->id);
1131         $user4 = new stdClass();
1132         $user4->firstname = 'Kyle';
1133         $user4->lastname = 'Broflovski';
1134         $user4 = self::getDataGenerator()->create_user($user4);
1135         $user5 = new stdClass();
1136         $user5->firstname = 'Kenny';
1137         $user5->lastname = 'McCormick';
1138         $user5 = self::getDataGenerator()->create_user($user5);
1139         self::getDataGenerator()->enrol_user($user5->id, $course2->id);
1141         $this->setUser($user1);
1143         $results = core_message_external::search_contacts('r');
1144         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1145         $this->assertCount(5, $results); // Users 2 through 5 + admin
1147         $results = core_message_external::search_contacts('r', true);
1148         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1149         $this->assertCount(2, $results);
1151         $results = core_message_external::search_contacts('Kyle', false);
1152         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1153         $this->assertCount(1, $results);
1154         $result = reset($results);
1155         $this->assertEquals($user4->id, $result['id']);
1157         $results = core_message_external::search_contacts('y', false);
1158         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1159         $this->assertCount(2, $results);
1161         $results = core_message_external::search_contacts('y', true);
1162         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1163         $this->assertCount(1, $results);
1164         $result = reset($results);
1165         $this->assertEquals($user5->id, $result['id']);
1167         // Empty query, will throw an exception.
1168         $results = core_message_external::search_contacts('');
1169     }
1171     /**
1172      * Test get_messages.
1173      */
1174     public function test_get_messages() {
1175         global $CFG, $DB;
1176         $this->resetAfterTest(true);
1178         $this->preventResetByRollback();
1179         // This mark the messages as read!.
1180         $sink = $this->redirectMessages();
1182         $user1 = self::getDataGenerator()->create_user();
1183         $user2 = self::getDataGenerator()->create_user();
1184         $user3 = self::getDataGenerator()->create_user();
1186         $course = self::getDataGenerator()->create_course();
1188         // Send a message from one user to another.
1189         message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1190         message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE);
1191         message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1192         message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1193         message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE);
1195         $this->setUser($user1);
1196         // Get read conversations from user1 to user2.
1197         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1198         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1199         $this->assertCount(1, $messages['messages']);
1201         // Delete the message.
1202         $message = array_shift($messages['messages']);
1203         \core_message\api::delete_message($user1->id, $message['id']);
1205         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1206         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1207         $this->assertCount(0, $messages['messages']);
1209         // Get unread conversations from user1 to user2.
1210         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0);
1211         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1212         $this->assertCount(0, $messages['messages']);
1214         // Get read messages send from user1.
1215         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1216         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1217         $this->assertCount(1, $messages['messages']);
1219         $this->setUser($user2);
1220         // Get read conversations from any user to user2.
1221         $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0);
1222         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1223         $this->assertCount(2, $messages['messages']);
1225         // Conversations from user3 to user2.
1226         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1227         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1228         $this->assertCount(1, $messages['messages']);
1230         // Delete the message.
1231         $message = array_shift($messages['messages']);
1232         \core_message\api::delete_message($user2->id, $message['id']);
1234         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1235         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1236         $this->assertCount(0, $messages['messages']);
1238         $this->setUser($user3);
1239         // Get read notifications received by user3.
1240         $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0);
1241         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1242         $this->assertCount(0, $messages['messages']);
1244         // Now, create some notifications...
1245         // We are creating fake notifications but based on real ones.
1247         // This one comes from a disabled plugin's provider and therefore is not sent.
1248         $eventdata = new \core\message\message();
1249         $eventdata->courseid          = $course->id;
1250         $eventdata->notification      = 1;
1251         $eventdata->modulename        = 'moodle';
1252         $eventdata->component         = 'enrol_paypal';
1253         $eventdata->name              = 'paypal_enrolment';
1254         $eventdata->userfrom          = get_admin();
1255         $eventdata->userto            = $user1;
1256         $eventdata->subject           = "Moodle: PayPal payment";
1257         $eventdata->fullmessage       = "Your PayPal payment is pending.";
1258         $eventdata->fullmessageformat = FORMAT_PLAIN;
1259         $eventdata->fullmessagehtml   = '';
1260         $eventdata->smallmessage      = '';
1261         message_send($eventdata);
1262         $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '.
1263             'that is inactive or not allowed for the user id='.$user1->id);
1265         // This one omits notification = 1.
1266         $message = new \core\message\message();
1267         $message->courseid          = $course->id;
1268         $message->component         = 'enrol_manual';
1269         $message->name              = 'expiry_notification';
1270         $message->userfrom          = $user2;
1271         $message->userto            = $user1;
1272         $message->subject           = 'Test: This is not a notification but otherwise is valid';
1273         $message->fullmessage       = 'Test: Full message';
1274         $message->fullmessageformat = FORMAT_MARKDOWN;
1275         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1276         $message->smallmessage      = $message->subject;
1277         $message->contexturlname    = $course->fullname;
1278         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1279         message_send($message);
1281         $message = new \core\message\message();
1282         $message->courseid          = $course->id;
1283         $message->notification      = 1;
1284         $message->component         = 'enrol_manual';
1285         $message->name              = 'expiry_notification';
1286         $message->userfrom          = $user2;
1287         $message->userto            = $user1;
1288         $message->subject           = 'Enrolment expired';
1289         $message->fullmessage       = 'Enrolment expired blah blah blah';
1290         $message->fullmessageformat = FORMAT_MARKDOWN;
1291         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1292         $message->smallmessage      = $message->subject;
1293         $message->contexturlname    = $course->fullname;
1294         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1295         message_send($message);
1297         $userfrom = core_user::get_noreply_user();
1298         $userfrom->maildisplay = true;
1299         $eventdata = new \core\message\message();
1300         $eventdata->courseid          = $course->id;
1301         $eventdata->component         = 'moodle';
1302         $eventdata->name              = 'badgecreatornotice';
1303         $eventdata->userfrom          = $userfrom;
1304         $eventdata->userto            = $user1;
1305         $eventdata->notification      = 1;
1306         $eventdata->subject           = 'New badge';
1307         $eventdata->fullmessage       = format_text_email($eventdata->subject, FORMAT_HTML);
1308         $eventdata->fullmessageformat = FORMAT_PLAIN;
1309         $eventdata->fullmessagehtml   = $eventdata->subject;
1310         $eventdata->smallmessage      = $eventdata->subject;
1311         message_send($eventdata);
1313         $eventdata = new \core\message\message();
1314         $eventdata->courseid         = $course->id;
1315         $eventdata->name             = 'submission';
1316         $eventdata->component        = 'mod_feedback';
1317         $eventdata->userfrom         = $user1;
1318         $eventdata->userto           = $user2;
1319         $eventdata->subject          = 'Feedback submitted';
1320         $eventdata->fullmessage      = 'Feedback submitted from an user';
1321         $eventdata->fullmessageformat = FORMAT_PLAIN;
1322         $eventdata->fullmessagehtml  = '<strong>Feedback submitted</strong>';
1323         $eventdata->smallmessage     = '';
1324         message_send($eventdata);
1326         $this->setUser($user1);
1327         // Get read notifications from any user to user1.
1328         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0);
1329         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1330         $this->assertCount(3, $messages['messages']);
1332         // Get one read notifications from any user to user1.
1333         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1);
1334         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1335         $this->assertCount(1, $messages['messages']);
1337         // Get unread notifications from any user to user1.
1338         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0);
1339         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1340         $this->assertCount(0, $messages['messages']);
1342         // Get read both type of messages from any user to user1.
1343         $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0);
1344         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1345         $this->assertCount(4, $messages['messages']);
1347         // Get read notifications from no-reply-user to user1.
1348         $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0);
1349         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1350         $this->assertCount(1, $messages['messages']);
1352         // Get notifications send by user1 to any user.
1353         $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0);
1354         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1355         $this->assertCount(1, $messages['messages']);
1357         // Test warnings.
1358         $CFG->messaging = 0;
1360         $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0);
1361         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1362         $this->assertCount(1, $messages['warnings']);
1364         // Test exceptions.
1366         // Messaging disabled.
1367         try {
1368             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1369             $this->fail('Exception expected due messaging disabled.');
1370         } catch (moodle_exception $e) {
1371             $this->assertEquals('disabled', $e->errorcode);
1372         }
1374         $CFG->messaging = 1;
1376         // Invalid users.
1377         try {
1378             $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0);
1379             $this->fail('Exception expected due invalid users.');
1380         } catch (moodle_exception $e) {
1381             $this->assertEquals('accessdenied', $e->errorcode);
1382         }
1384         // Invalid user ids.
1385         try {
1386             $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0);
1387             $this->fail('Exception expected due invalid users.');
1388         } catch (moodle_exception $e) {
1389             $this->assertEquals('invaliduser', $e->errorcode);
1390         }
1392         // Invalid users (permissions).
1393         $this->setUser($user2);
1394         try {
1395             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1396             $this->fail('Exception expected due invalid user.');
1397         } catch (moodle_exception $e) {
1398             $this->assertEquals('accessdenied', $e->errorcode);
1399         }
1401     }
1403     /**
1404      * Test get_messages where we want all messages from a user, sent to any user.
1405      */
1406     public function test_get_messages_useridto_all() {
1407         $this->resetAfterTest(true);
1409         $user1 = self::getDataGenerator()->create_user();
1410         $user2 = self::getDataGenerator()->create_user();
1411         $user3 = self::getDataGenerator()->create_user();
1413         $this->setUser($user1);
1415         // Send a message from user 1 to two other users.
1416         $this->send_message($user1, $user2, 'some random text 1', 0, 1);
1417         $this->send_message($user1, $user3, 'some random text 2', 0, 2);
1419         // Get messages sent from user 1.
1420         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', false, false, 0, 0);
1421         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1423         // Confirm the data is correct.
1424         $messages = $messages['messages'];
1425         $this->assertCount(2, $messages);
1427         $message1 = array_shift($messages);
1428         $message2 = array_shift($messages);
1430         $this->assertEquals($user1->id, $message1['useridfrom']);
1431         $this->assertEquals($user2->id, $message1['useridto']);
1433         $this->assertEquals($user1->id, $message2['useridfrom']);
1434         $this->assertEquals($user3->id, $message2['useridto']);
1435     }
1437     /**
1438      * Test get_messages where we want all messages to a user, sent by any user.
1439      */
1440     public function test_get_messages_useridfrom_all() {
1441         $this->resetAfterTest();
1443         $user1 = self::getDataGenerator()->create_user();
1444         $user2 = self::getDataGenerator()->create_user();
1445         $user3 = self::getDataGenerator()->create_user();
1447         $this->setUser($user1);
1449         // Send a message to user 1 from two other users.
1450         $this->send_message($user2, $user1, 'some random text 1', 0, 1);
1451         $this->send_message($user3, $user1, 'some random text 2', 0, 2);
1453         // Get messages sent to user 1.
1454         $messages = core_message_external::get_messages($user1->id, 0, 'conversations', false, false, 0, 0);
1455         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1457         // Confirm the data is correct.
1458         $messages = $messages['messages'];
1459         $this->assertCount(2, $messages);
1461         $message1 = array_shift($messages);
1462         $message2 = array_shift($messages);
1464         $this->assertEquals($user2->id, $message1['useridfrom']);
1465         $this->assertEquals($user1->id, $message1['useridto']);
1467         $this->assertEquals($user3->id, $message2['useridfrom']);
1468         $this->assertEquals($user1->id, $message2['useridto']);
1469     }
1471     /**
1472      * Test get_blocked_users.
1473      */
1474     public function test_get_blocked_users() {
1475         $this->resetAfterTest(true);
1477         $user1 = self::getDataGenerator()->create_user();
1478         $userstranger = self::getDataGenerator()->create_user();
1479         $useroffline1 = self::getDataGenerator()->create_user();
1480         $useroffline2 = self::getDataGenerator()->create_user();
1481         $userblocked = self::getDataGenerator()->create_user();
1483         // Login as user1.
1484         $this->setUser($user1);
1486         \core_message\api::add_contact($user1->id, $useroffline1->id);
1487         \core_message\api::add_contact($user1->id, $useroffline2->id);
1489         // The userstranger sends a couple of messages to user1.
1490         $this->send_message($userstranger, $user1, 'Hello there!');
1491         $this->send_message($userstranger, $user1, 'How you goin?');
1493         // The userblocked sends a message to user1.
1494         // Note that this user is not blocked at this point.
1495         $this->send_message($userblocked, $user1, 'Here, have some spam.');
1497         // Retrieve the list of blocked users.
1498         $this->setUser($user1);
1499         $blockedusers = core_message_external::get_blocked_users($user1->id);
1500         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1501         $this->assertCount(0, $blockedusers['users']);
1503         // Block the $userblocked and retrieve again the list.
1504         core_message_external::block_contacts(array($userblocked->id));
1505         $this->assertDebuggingCalled();
1506         $blockedusers = core_message_external::get_blocked_users($user1->id);
1507         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1508         $this->assertCount(1, $blockedusers['users']);
1510         // Remove the $userblocked and check that the list now is empty.
1511         delete_user($userblocked);
1512         $blockedusers = core_message_external::get_blocked_users($user1->id);
1513         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1514         $this->assertCount(0, $blockedusers['users']);
1515     }
1517     /**
1518      * Test mark_message_read.
1519      */
1520     public function test_mark_message_read() {
1521         $this->resetAfterTest(true);
1523         $user1 = self::getDataGenerator()->create_user();
1524         $user2 = self::getDataGenerator()->create_user();
1525         $user3 = self::getDataGenerator()->create_user();
1527         // Login as user1.
1528         $this->setUser($user1);
1529         \core_message\api::add_contact($user1->id, $user2->id);
1530         \core_message\api::add_contact($user1->id, $user3->id);
1532         // The user2 sends a couple of messages to user1.
1533         $this->send_message($user2, $user1, 'Hello there!');
1534         $this->send_message($user2, $user1, 'How you goin?');
1535         $this->send_message($user3, $user1, 'How you goin?');
1536         $this->send_message($user3, $user2, 'How you goin?');
1538         // Retrieve all messages sent by user2 (they are currently unread).
1539         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1541         $messageids = array();
1542         foreach ($lastmessages as $m) {
1543             $messageid = core_message_external::mark_message_read($m->id, time());
1544             $messageids[] = external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid);
1545         }
1547         // Retrieve all messages sent (they are currently read).
1548         $lastmessages = message_get_messages($user1->id, $user2->id, 0, true);
1549         $this->assertCount(2, $lastmessages);
1550         $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages);
1551         $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages);
1553         // Retrieve all messages sent by any user (that are currently unread).
1554         $lastmessages = message_get_messages($user1->id, 0, 0, false);
1555         $this->assertCount(1, $lastmessages);
1557         // Invalid message ids.
1558         try {
1559             $messageid = core_message_external::mark_message_read(1337, time());
1560             $this->fail('Exception expected due invalid messageid.');
1561         } catch (dml_missing_record_exception $e) {
1562             $this->assertEquals('invalidrecordunknown', $e->errorcode);
1563         }
1565         // A message to a different user.
1566         $lastmessages = message_get_messages($user2->id, $user3->id, 0, false);
1567         $messageid = array_pop($lastmessages)->id;
1568         try {
1569             $messageid = core_message_external::mark_message_read($messageid, time());
1570             $this->fail('Exception expected due invalid messageid.');
1571         } catch (invalid_parameter_exception $e) {
1572             $this->assertEquals('invalidparameter', $e->errorcode);
1573         }
1574     }
1576     /**
1577      * Test mark_notification_read.
1578      */
1579     public function test_mark_notification_read() {
1580         $this->resetAfterTest(true);
1582         $user1 = self::getDataGenerator()->create_user();
1583         $user2 = self::getDataGenerator()->create_user();
1584         $user3 = self::getDataGenerator()->create_user();
1586         // Login as user1.
1587         $this->setUser($user1);
1588         \core_message\api::add_contact($user1->id, $user2->id);
1589         \core_message\api::add_contact($user1->id, $user3->id);
1591         // The user2 sends a couple of notifications to user1.
1592         $this->send_message($user2, $user1, 'Hello there!', 1);
1593         $this->send_message($user2, $user1, 'How you goin?', 1);
1594         $this->send_message($user3, $user1, 'How you goin?', 1);
1595         $this->send_message($user3, $user2, 'How you goin?', 1);
1597         // Retrieve all notifications sent by user2 (they are currently unread).
1598         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, false);
1600         $notificationids = array();
1601         foreach ($lastnotifications as $n) {
1602             $notificationid = core_message_external::mark_notification_read($n->id, time());
1603             $notificationids[] = external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(),
1604                 $notificationid);
1605         }
1607         // Retrieve all notifications sent (they are currently read).
1608         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, true);
1609         $this->assertCount(2, $lastnotifications);
1610         $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications);
1611         $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications);
1613         // Retrieve all notifications sent by any user (that are currently unread).
1614         $lastnotifications = message_get_messages($user1->id, 0, 1, false);
1615         $this->assertCount(1, $lastnotifications);
1617         // Invalid notification ids.
1618         try {
1619             $notificationid = core_message_external::mark_notification_read(1337, time());
1620             $this->fail('Exception expected due invalid notificationid.');
1621         } catch (dml_missing_record_exception $e) {
1622             $this->assertEquals('invalidrecord', $e->errorcode);
1623         }
1625         // A notification to a different user.
1626         $lastnotifications = message_get_messages($user2->id, $user3->id, 1, false);
1627         $notificationid = array_pop($lastnotifications)->id;
1628         try {
1629             $notificationid = core_message_external::mark_notification_read($notificationid, time());
1630             $this->fail('Exception expected due invalid notificationid.');
1631         } catch (invalid_parameter_exception $e) {
1632             $this->assertEquals('invalidparameter', $e->errorcode);
1633         }
1634     }
1636     /**
1637      * Test delete_message.
1638      */
1639     public function test_delete_message() {
1640         global $DB;
1641         $this->resetAfterTest(true);
1643         $user1 = self::getDataGenerator()->create_user();
1644         $user2 = self::getDataGenerator()->create_user();
1645         $user3 = self::getDataGenerator()->create_user();
1646         $user4 = self::getDataGenerator()->create_user();
1648         // Login as user1.
1649         $this->setUser($user1);
1650         \core_message\api::add_contact($user1->id, $user2->id);
1651         \core_message\api::add_contact($user1->id, $user3->id);
1653         // User user1 does not interchange messages with user3.
1654         $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1655         $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1656         $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1657         $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE);
1659         // Retrieve all messages sent by user2 (they are currently unread).
1660         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1662         // Delete a message not read, as a user from.
1663         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1664         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1665         $this->assertTrue($result['status']);
1666         $this->assertCount(0, $result['warnings']);
1667         $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id));
1668         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action);
1670         // Try to delete the same message again.
1671         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1672         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1673         $this->assertFalse($result['status']);
1675         // Try to delete a message that does not belong to me.
1676         try {
1677             $messageid = core_message_external::delete_message($m2to3, $user3->id, false);
1678             $this->fail('Exception expected due invalid messageid.');
1679         } catch (moodle_exception $e) {
1680             $this->assertEquals('You do not have permission to delete this message', $e->errorcode);
1681         }
1683         $this->setUser($user3);
1684         // Delete a message not read, as a user to.
1685         $result = core_message_external::delete_message($m2to3, $user3->id, false);
1686         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1687         $this->assertTrue($result['status']);
1688         $this->assertCount(0, $result['warnings']);
1689         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id,
1690             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1692         // Delete a message read.
1693         $message = $DB->get_record('messages', ['id' => $m3to2]);
1694         \core_message\api::mark_message_as_read($user3->id, $message, time());
1695         $result = core_message_external::delete_message($m3to2, $user3->id);
1696         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1697         $this->assertTrue($result['status']);
1698         $this->assertCount(0, $result['warnings']);
1699         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id,
1700             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1702         // Invalid message ids.
1703         try {
1704             $result = core_message_external::delete_message(-1, $user1->id);
1705             $this->fail('Exception expected due invalid messageid.');
1706         } catch (dml_missing_record_exception $e) {
1707             $this->assertEquals('invalidrecord', $e->errorcode);
1708         }
1710         // Invalid user.
1711         try {
1712             $result = core_message_external::delete_message($m1to2, -1, false);
1713             $this->fail('Exception expected due invalid user.');
1714         } catch (moodle_exception $e) {
1715             $this->assertEquals('invaliduser', $e->errorcode);
1716         }
1718         // Not active user.
1719         delete_user($user2);
1720         try {
1721             $result = core_message_external::delete_message($m1to2, $user2->id, false);
1722             $this->fail('Exception expected due invalid user.');
1723         } catch (moodle_exception $e) {
1724             $this->assertEquals('userdeleted', $e->errorcode);
1725         }
1727         // Now, as an admin, try to delete any message.
1728         $this->setAdminUser();
1729         $result = core_message_external::delete_message($m3to4, $user4->id, false);
1730         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1731         $this->assertTrue($result['status']);
1732         $this->assertCount(0, $result['warnings']);
1733         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id,
1734             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1736     }
1738     public function test_mark_all_notifications_as_read_invalid_user_exception() {
1739         $this->resetAfterTest(true);
1741         $this->expectException('moodle_exception');
1742         core_message_external::mark_all_notifications_as_read(-2132131, 0);
1743     }
1745     public function test_mark_all_notifications_as_read_access_denied_exception() {
1746         $this->resetAfterTest(true);
1748         $sender = $this->getDataGenerator()->create_user();
1749         $user = $this->getDataGenerator()->create_user();
1751         $this->setUser($user);
1752         $this->expectException('moodle_exception');
1753         core_message_external::mark_all_notifications_as_read($sender->id, 0);
1754     }
1756     public function test_mark_all_notifications_as_read_missing_from_user_exception() {
1757         $this->resetAfterTest(true);
1759         $sender = $this->getDataGenerator()->create_user();
1761         $this->setUser($sender);
1762         $this->expectException('moodle_exception');
1763         core_message_external::mark_all_notifications_as_read($sender->id, 99999);
1764     }
1766     public function test_mark_all_notifications_as_read() {
1767         global $DB;
1769         $this->resetAfterTest(true);
1771         $sender1 = $this->getDataGenerator()->create_user();
1772         $sender2 = $this->getDataGenerator()->create_user();
1773         $sender3 = $this->getDataGenerator()->create_user();
1774         $recipient = $this->getDataGenerator()->create_user();
1776         $this->setUser($recipient);
1778         $this->send_message($sender1, $recipient, 'Notification', 1);
1779         $this->send_message($sender1, $recipient, 'Notification', 1);
1780         $this->send_message($sender2, $recipient, 'Notification', 1);
1781         $this->send_message($sender2, $recipient, 'Notification', 1);
1782         $this->send_message($sender3, $recipient, 'Notification', 1);
1783         $this->send_message($sender3, $recipient, 'Notification', 1);
1785         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id);
1786         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1787         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1789         $this->assertCount(2, $readnotifications);
1790         $this->assertCount(4, $unreadnotifications);
1792         core_message_external::mark_all_notifications_as_read($recipient->id, 0);
1793         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1794         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1796         $this->assertCount(6, $readnotifications);
1797         $this->assertCount(0, $unreadnotifications);
1798     }
1800     /**
1801      * Test get_user_notification_preferences
1802      */
1803     public function test_get_user_notification_preferences() {
1804         $this->resetAfterTest(true);
1806         $user = self::getDataGenerator()->create_user();
1807         $this->setUser($user);
1809         // Set a couple of preferences to test.
1810         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
1811         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
1813         $prefs = core_message_external::get_user_notification_preferences();
1814         $prefs = external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs);
1815         // Check processors.
1816         $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors']));
1817         $this->assertEquals($user->id, $prefs['preferences']['userid']);
1819         // Check components.
1820         $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components']));
1822         // Check some preferences that we previously set.
1823         $found = 0;
1824         foreach ($prefs['preferences']['components'] as $component) {
1825             foreach ($component['notifications'] as $prefdata) {
1826                 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') {
1827                     continue;
1828                 }
1829                 foreach ($prefdata['processors'] as $processor) {
1830                     if ($processor['name'] == 'popup') {
1831                         $this->assertTrue($processor['loggedin']['checked']);
1832                         $found++;
1833                     } else if ($processor['name'] == 'email') {
1834                         $this->assertTrue($processor['loggedoff']['checked']);
1835                         $found++;
1836                     }
1837                 }
1838             }
1839         }
1840         $this->assertEquals(2, $found);
1841     }
1843     /**
1844      * Test get_user_notification_preferences permissions
1845      */
1846     public function test_get_user_notification_preferences_permissions() {
1847         $this->resetAfterTest(true);
1849         $user = self::getDataGenerator()->create_user();
1850         $otheruser = self::getDataGenerator()->create_user();
1851         $this->setUser($user);
1853         $this->expectException('moodle_exception');
1854         $prefs = core_message_external::get_user_notification_preferences($otheruser->id);
1855     }
1857     /**
1858      * Tests searching users in a course.
1859      */
1860     public function test_data_for_messagearea_search_users_in_course() {
1861         $this->resetAfterTest(true);
1863         // Create some users.
1864         $user1 = new stdClass();
1865         $user1->firstname = 'User';
1866         $user1->lastname = 'One';
1867         $user1 = self::getDataGenerator()->create_user($user1);
1869         // The person doing the search.
1870         $this->setUser($user1);
1872         // Set the second user's status to online by setting their last access to now.
1873         $user2 = new stdClass();
1874         $user2->firstname = 'User';
1875         $user2->lastname = 'Two';
1876         $user2->lastaccess = time();
1877         $user2 = self::getDataGenerator()->create_user($user2);
1879         // Block the second user.
1880         \core_message\api::block_user($user1->id, $user2->id);
1882         $user3 = new stdClass();
1883         $user3->firstname = 'User';
1884         $user3->lastname = 'Three';
1885         $user3 = self::getDataGenerator()->create_user($user3);
1887         // Create a course.
1888         $course1 = new stdClass();
1889         $course1->fullname = 'Course';
1890         $course1->shortname = 'One';
1891         $course1 = $this->getDataGenerator()->create_course();
1893         // Enrol the user we are doing the search for and one user in the course.
1894         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1895         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1897         // Perform a search.
1898         $result = core_message_external::data_for_messagearea_search_users_in_course($user1->id, $course1->id, 'User');
1900         // We need to execute the return values cleaning process to simulate the web service.
1901         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_in_course_returns(),
1902             $result);
1904         // Check that we only retrieved a user that was enrolled, and that the user performing the search was not returned.
1905         $users = $result['contacts'];
1906         $this->assertCount(1, $users);
1908         $user = $users[0];
1909         $this->assertEquals($user2->id, $user['userid']);
1910         $this->assertEquals(fullname($user2), $user['fullname']);
1911         $this->assertFalse($user['ismessaging']);
1912         $this->assertFalse($user['sentfromcurrentuser']);
1913         $this->assertNull($user['lastmessage']);
1914         $this->assertNull($user['messageid']);
1915         $this->assertNull($user['isonline']);
1916         $this->assertFalse($user['isread']);
1917         $this->assertTrue($user['isblocked']);
1918         $this->assertNull($user['unreadcount']);
1919     }
1921     /**
1922      * Tests searching users in course as another user.
1923      */
1924     public function test_data_for_messagearea_search_users_in_course_as_other_user() {
1925         $this->resetAfterTest(true);
1927         // The person doing the search for another user.
1928         $this->setAdminUser();
1930         // Create some users.
1931         $user1 = new stdClass();
1932         $user1->firstname = 'User';
1933         $user1->lastname = 'One';
1934         $user1 = self::getDataGenerator()->create_user($user1);
1936         $user2 = new stdClass();
1937         $user2->firstname = 'User';
1938         $user2->lastname = 'Two';
1939         $user2 = self::getDataGenerator()->create_user($user2);
1941         $user3 = new stdClass();
1942         $user3->firstname = 'User';
1943         $user3->lastname = 'Three';
1944         $user3 = self::getDataGenerator()->create_user($user3);
1946         // Create a course.
1947         $course1 = new stdClass();
1948         $course1->fullname = 'Course';
1949         $course1->shortname = 'One';
1950         $course1 = $this->getDataGenerator()->create_course();
1952         // Enrol the user we are doing the search for and one user in the course.
1953         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1954         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1956         // Perform a search.
1957         $result = core_message_external::data_for_messagearea_search_users_in_course($user1->id, $course1->id, 'User');
1959         // We need to execute the return values cleaning process to simulate the web service server.
1960         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_in_course_returns(),
1961             $result);
1963         // Check that we got the user enrolled, and that the user we are performing the search on behalf of was not returned.
1964         $users = $result['contacts'];
1965         $this->assertCount(1, $users);
1967         $user = $users[0];
1968         $this->assertEquals($user2->id, $user['userid']);
1969         $this->assertEquals(fullname($user2), $user['fullname']);
1970         $this->assertFalse($user['ismessaging']);
1971         $this->assertFalse($user['sentfromcurrentuser']);
1972         $this->assertNull($user['lastmessage']);
1973         $this->assertNull($user['messageid']);
1974         $this->assertFalse($user['isonline']);
1975         $this->assertFalse($user['isread']);
1976         $this->assertFalse($user['isblocked']);
1977         $this->assertNull($user['unreadcount']);
1978     }
1980     /**
1981      * Tests searching users in course as another user without the proper capabilities.
1982      */
1983     public function test_data_for_messagearea_search_users_in_course_as_other_user_without_cap() {
1984         $this->resetAfterTest(true);
1986         // Create some users.
1987         $user1 = self::getDataGenerator()->create_user();
1988         $user2 = self::getDataGenerator()->create_user();
1990         // The person doing the search for another user.
1991         $this->setUser($user1);
1993         // Create a course.
1994         $course = $this->getDataGenerator()->create_course();
1996         // Ensure an exception is thrown.
1997         $this->expectException('moodle_exception');
1998         core_message_external::data_for_messagearea_search_users_in_course($user2->id, $course->id, 'User');
1999         $this->assertDebuggingCalled();
2000     }
2002     /**
2003      * Tests searching users in course with messaging disabled.
2004      */
2005     public function test_data_for_messagearea_search_users_in_course_messaging_disabled() {
2006         global $CFG;
2008         $this->resetAfterTest(true);
2010         // Create some skeleton data just so we can call the WS..
2011         $user = self::getDataGenerator()->create_user();
2012         $course = $this->getDataGenerator()->create_course();
2014         // The person doing the search for another user.
2015         $this->setUser($user);
2017         // Disable messaging.
2018         $CFG->messaging = 0;
2020         // Ensure an exception is thrown.
2021         $this->expectException('moodle_exception');
2022         core_message_external::data_for_messagearea_search_users_in_course($user->id, $course->id, 'User');
2023         $this->assertDebuggingCalled();
2024     }
2026     /**
2027      * Tests searching users.
2028      */
2029     public function test_data_for_messagearea_search_users() {
2030         $this->resetAfterTest(true);
2032         // Create some users.
2033         $user1 = new stdClass();
2034         $user1->firstname = 'User';
2035         $user1->lastname = 'One';
2036         $user1 = self::getDataGenerator()->create_user($user1);
2038         // Set as the user performing the search.
2039         $this->setUser($user1);
2041         $user2 = new stdClass();
2042         $user2->firstname = 'User search';
2043         $user2->lastname = 'Two';
2044         $user2 = self::getDataGenerator()->create_user($user2);
2046         $user3 = new stdClass();
2047         $user3->firstname = 'User search';
2048         $user3->lastname = 'Three';
2049         $user3 = self::getDataGenerator()->create_user($user3);
2051         $user4 = new stdClass();
2052         $user4->firstname = 'User';
2053         $user4->lastname = 'Four';
2054         $user4 = self::getDataGenerator()->create_user($user4);
2056         $user5 = new stdClass();
2057         $user5->firstname = 'User search';
2058         $user5->lastname = 'Five';
2059         $user5 = self::getDataGenerator()->create_user($user5);
2061         $user6 = new stdClass();
2062         $user6->firstname = 'User';
2063         $user6->lastname = 'Six';
2064         $user6 = self::getDataGenerator()->create_user($user6);
2066         // Create some courses.
2067         $course1 = new stdClass();
2068         $course1->fullname = 'Course search';
2069         $course1->shortname = 'One';
2070         $course1 = $this->getDataGenerator()->create_course($course1);
2072         $course2 = new stdClass();
2073         $course2->fullname = 'Course';
2074         $course2->shortname = 'Two';
2075         $course2 = $this->getDataGenerator()->create_course($course2);
2077         $course3 = new stdClass();
2078         $course3->fullname = 'Course';
2079         $course3->shortname = 'Three search';
2080         $course3 = $this->getDataGenerator()->create_course($course3);
2082         $course4 = new stdClass();
2083         $course4->fullname = 'Course Four';
2084         $course4->shortname = 'CF100';
2085         $course4 = $this->getDataGenerator()->create_course($course4);
2087         $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
2088         $this->getDataGenerator()->enrol_user($user1->id, $course2->id, 'student');
2089         $this->getDataGenerator()->enrol_user($user1->id, $course3->id, 'student');
2091         // Add some users as contacts.
2092         \core_message\api::add_contact($user1->id, $user2->id);
2093         \core_message\api::add_contact($user1->id, $user3->id);
2094         \core_message\api::add_contact($user1->id, $user4->id);
2096         // Perform a search $CFG->messagingallusers setting enabled.
2097         set_config('messagingallusers', 1);
2098         $result = core_message_external::data_for_messagearea_search_users($user1->id, 'search');
2100         // We need to execute the return values cleaning process to simulate the web service server.
2101         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_returns(),
2102             $result);
2104         // Confirm that we returns contacts, courses and non-contacts.
2105         $contacts = $result['contacts'];
2106         $courses = $result['courses'];
2107         $noncontacts = $result['noncontacts'];
2109         // Check that we retrieved the correct contacts.
2110         $this->assertCount(2, $contacts);
2111         $this->assertEquals($user3->id, $contacts[0]['userid']);
2112         $this->assertEquals($user2->id, $contacts[1]['userid']);
2114         // Check that we retrieved the correct courses.
2115         $this->assertCount(2, $courses);
2116         $this->assertEquals($course3->id, $courses[0]['id']);
2117         $this->assertEquals($course1->id, $courses[1]['id']);
2119         // Check that we retrieved the correct non-contacts.
2120         $this->assertCount(1, $noncontacts);
2121         $this->assertEquals($user5->id, $noncontacts[0]['userid']);
2122     }
2124     /**
2125      * Tests searching users as another user.
2126      */
2127     public function test_data_for_messagearea_search_users_as_other_user() {
2128         $this->resetAfterTest(true);
2130         // The person doing the search.
2131         $this->setAdminUser();
2133         // Create some users.
2134         $user1 = new stdClass();
2135         $user1->firstname = 'User';
2136         $user1->lastname = 'One';
2137         $user1 = self::getDataGenerator()->create_user($user1);
2139         $user2 = new stdClass();
2140         $user2->firstname = 'User search';
2141         $user2->lastname = 'Two';
2142         $user2 = self::getDataGenerator()->create_user($user2);
2144         $user3 = new stdClass();
2145         $user3->firstname = 'User search';
2146         $user3->lastname = 'Three';
2147         $user3 = self::getDataGenerator()->create_user($user3);
2149         $user4 = new stdClass();
2150         $user4->firstname = 'User';
2151         $user4->lastname = 'Four';
2152         $user4 = self::getDataGenerator()->create_user($user4);
2154         $user5 = new stdClass();
2155         $user5->firstname = 'User search';
2156         $user5->lastname = 'Five';
2157         $user5 = self::getDataGenerator()->create_user($user5);
2159         $user6 = new stdClass();
2160         $user6->firstname = 'User';
2161         $user6->lastname = 'Six';
2162         $user6 = self::getDataGenerator()->create_user($user6);
2164         // Create some courses.
2165         $course1 = new stdClass();
2166         $course1->fullname = 'Course search';
2167         $course1->shortname = 'One';
2168         $course1 = $this->getDataGenerator()->create_course($course1);
2170         $course2 = new stdClass();
2171         $course2->fullname = 'Course';
2172         $course2->shortname = 'Two';
2173         $course2 = $this->getDataGenerator()->create_course($course2);
2175         $course3 = new stdClass();
2176         $course3->fullname = 'Course';
2177         $course3->shortname = 'Three search';
2178         $course3 = $this->getDataGenerator()->create_course($course3);
2180         // Add some users as contacts.
2181         \core_message\api::add_contact($user1->id, $user2->id);
2182         \core_message\api::add_contact($user1->id, $user3->id);
2183         \core_message\api::add_contact($user1->id, $user4->id);
2185         // Perform a search $CFG->messagingallusers setting enabled.
2186         set_config('messagingallusers', 1);
2187         $result = core_message_external::data_for_messagearea_search_users($user1->id, 'search');
2189         // We need to execute the return values cleaning process to simulate the web service server.
2190         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_returns(),
2191             $result);
2193         // Confirm that we returns contacts, courses and non-contacts.
2194         $contacts = $result['contacts'];
2195         $courses = $result['courses'];
2196         $noncontacts = $result['noncontacts'];
2198         // Check that we retrieved the correct contacts.
2199         $this->assertCount(2, $contacts);
2200         $this->assertEquals($user3->id, $contacts[0]['userid']);
2201         $this->assertEquals($user2->id, $contacts[1]['userid']);
2203         // Check that we retrieved the correct courses.
2204         $this->assertCount(0, $courses);
2206         // Check that we retrieved the correct non-contacts.
2207         $this->assertCount(1, $noncontacts);
2208         $this->assertEquals($user5->id, $noncontacts[0]['userid']);
2209     }
2211     /**
2212      * Tests searching users as another user without the proper capabilities.
2213      */
2214     public function test_data_for_messagearea_search_users_as_other_user_without_cap() {
2215         $this->resetAfterTest(true);
2217         // Create some users.
2218         $user1 = self::getDataGenerator()->create_user();
2219         $user2 = self::getDataGenerator()->create_user();
2221         // The person doing the search for another user.
2222         $this->setUser($user1);
2224         // Ensure an exception is thrown.
2225         $this->expectException('moodle_exception');
2226         core_message_external::data_for_messagearea_search_users($user2->id, 'User');
2227         $this->assertDebuggingCalled();
2228     }
2230     /**
2231      * Tests searching users with messaging disabled.
2232      */
2233     public function test_data_for_messagearea_search_users_messaging_disabled() {
2234         global $CFG;
2236         $this->resetAfterTest(true);
2238         // Create some skeleton data just so we can call the WS.
2239         $user = self::getDataGenerator()->create_user();
2241         // The person doing the search.
2242         $this->setUser($user);
2244         // Disable messaging.
2245         $CFG->messaging = 0;
2247         // Ensure an exception is thrown.
2248         $this->expectException('moodle_exception');
2249         core_message_external::data_for_messagearea_search_users($user->id, 'User');
2250         $this->assertDebuggingCalled();
2251     }
2253     /**
2254      * Tests searching for users when site-wide messaging is disabled.
2255      *
2256      * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
2257      * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
2258      * profile.
2259      */
2260     public function test_message_search_users_messagingallusers_disabled() {
2261         $this->resetAfterTest();
2263         // Create some users.
2264         $users = [];
2265         foreach (range(1, 7) as $i) {
2266             $user = new stdClass();
2267             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2268             $user->lastname = $i;
2269             $user = $this->getDataGenerator()->create_user($user);
2270             $users[$i] = $user;
2271         }
2273         // Enrol a few users in the same course, but leave them as non-contacts.
2274         $course1 = $this->getDataGenerator()->create_course();
2275         $this->setAdminUser();
2276         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2277         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2278         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2280         // Add some other users as contacts.
2281         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2282         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2283         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2285         // Create individual conversations between some users, one contact and one non-contact.
2286         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2287             [$users[1]->id, $users[2]->id]);
2288         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2289             [$users[6]->id, $users[1]->id]);
2291         // Create a group conversation between 4 users, including a contact and a non-contact.
2292         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2293             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
2295         // Set as the user performing the search.
2296         $this->setUser($users[1]);
2298         // Perform a search with $CFG->messagingallusers disabled.
2299         set_config('messagingallusers', 0);
2300         $result = core_message_external::message_search_users($users[1]->id, 'search');
2301         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2303         // Confirm that we returns contacts and non-contacts.
2304         $this->assertArrayHasKey('contacts', $result);
2305         $this->assertArrayHasKey('noncontacts', $result);
2306         $contacts = $result['contacts'];
2307         $noncontacts = $result['noncontacts'];
2309         // Check that we retrieved the correct contacts.
2310         $this->assertCount(2, $contacts);
2311         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2312         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2314         // Verify the correct conversations were returned for the contacts.
2315         $this->assertCount(2, $contacts[0]['conversations']);
2316         // We can't rely on the ordering of conversations within the results, so sort by id first.
2317         usort($contacts[0]['conversations'], function($a, $b) {
2318             return $a['id'] < $b['id'];
2319         });
2320         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2321         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2323         $this->assertCount(0, $contacts[1]['conversations']);
2325         // Check that we retrieved the correct non-contacts.
2326         // When site wide messaging is disabled, we expect to see only those users whose profiles we can view.
2327         $this->assertCount(2, $noncontacts);
2328         $this->assertEquals($users[6]->id, $noncontacts[0]['id']);
2329         $this->assertEquals($users[7]->id, $noncontacts[1]['id']);
2331         // Verify the correct conversations were returned for the non-contacts.
2332         $this->assertCount(1, $noncontacts[0]['conversations']);
2333         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[0]['conversations'][0]['type']);
2335         $this->assertCount(1, $noncontacts[1]['conversations']);
2336         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[1]['conversations'][0]['type']);
2337     }
2339     /**
2340      * Tests searching for users when site-wide messaging is enabled.
2341      *
2342      * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user
2343      * can view their respective profile.
2344      */
2345     public function test_message_search_users_messagingallusers_enabled() {
2346         $this->resetAfterTest();
2348         // Create some users.
2349         $users = [];
2350         foreach (range(1, 8) as $i) {
2351             $user = new stdClass();
2352             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2353             $user->lastname = $i;
2354             $user = $this->getDataGenerator()->create_user($user);
2355             $users[$i] = $user;
2356         }
2358         // Enrol a few users in the same course, but leave them as non-contacts.
2359         $course1 = $this->getDataGenerator()->create_course();
2360         $this->setAdminUser();
2361         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2362         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2363         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2365         // Add some other users as contacts.
2366         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2367         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2368         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2370         // Create individual conversations between some users, one contact and one non-contact.
2371         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2372             [$users[1]->id, $users[2]->id]);
2373         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2374             [$users[6]->id, $users[1]->id]);
2376         // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
2377         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2378             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
2380         // Set as the user performing the search.
2381         $this->setUser($users[1]);
2383         // Perform a search with $CFG->messagingallusers enabled.
2384         set_config('messagingallusers', 1);
2385         $result = core_message_external::message_search_users($users[1]->id, 'search');
2386         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2388         // Confirm that we returns contacts and non-contacts.
2389         $this->assertArrayHasKey('contacts', $result);
2390         $this->assertArrayHasKey('noncontacts', $result);
2391         $contacts = $result['contacts'];
2392         $noncontacts = $result['noncontacts'];
2394         // Check that we retrieved the correct contacts.
2395         $this->assertCount(2, $contacts);
2396         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2397         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2399         // Verify the correct conversations were returned for the contacts.
2400         $this->assertCount(2, $contacts[0]['conversations']);
2401         // We can't rely on the ordering of conversations within the results, so sort by id first.
2402         usort($contacts[0]['conversations'], function($a, $b) {
2403             return $a['id'] < $b['id'];
2404         });
2405         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2406         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2408         $this->assertCount(0, $contacts[1]['conversations']);
2410         // Check that we retrieved the correct non-contacts.
2411         // If site wide messaging is enabled, we expect to be able to search for any users.
2412         $this->assertCount(4, $noncontacts);
2413         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2414         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2415         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2416         $this->assertEquals($users[8]->id, $noncontacts[3]['id']);
2418         // Verify the correct conversations were returned for the non-contacts.
2419         $this->assertCount(0, $noncontacts[0]['conversations']);
2421         $this->assertCount(1, $noncontacts[1]['conversations']);
2422         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']);
2424         $this->assertCount(1, $noncontacts[2]['conversations']);
2425         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']);
2427         $this->assertCount(1, $noncontacts[3]['conversations']);
2428         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[3]['conversations'][0]['type']);
2429     }
2431     /**
2432      * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
2433      */
2434     public function test_message_search_users_with_empty_result() {
2435         $this->resetAfterTest();
2437         // Create some users, but make sure neither will match the search term.
2438         $user1 = new stdClass();
2439         $user1->firstname = 'User';
2440         $user1->lastname = 'One';
2441         $user1 = $this->getDataGenerator()->create_user($user1);
2442         $user2 = new stdClass();
2443         $user2->firstname = 'User';
2444         $user2->lastname = 'Two';
2445         $user2 = $this->getDataGenerator()->create_user($user2);
2447         // Perform a search as user1.
2448         $this->setUser($user1);
2449         $result = core_message_external::message_search_users($user1->id, 'search');
2450         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2452         // Check results are empty.
2453         $this->assertCount(0, $result['contacts']);
2454         $this->assertCount(0, $result['noncontacts']);
2455     }
2457     /**
2458      * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
2459      */
2460     public function test_message_search_users_limit_offset() {
2461         $this->resetAfterTest();
2463         // Create 20 users.
2464         $users = [];
2465         foreach (range(1, 20) as $i) {
2466             $user = new stdClass();
2467             $user->firstname = "User search";
2468             $user->lastname = $i;
2469             $user = $this->getDataGenerator()->create_user($user);
2470             $users[$i] = $user;
2471         }
2473         // Enrol the first 9 users in the same course, but leave them as non-contacts.
2474         $this->setAdminUser();
2475         $course1 = $this->getDataGenerator()->create_course();
2476         foreach (range(1, 9) as $i) {
2477             $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
2478         }
2480         // Add 5 users, starting at the 11th user, as contacts for user1.
2481         foreach (range(11, 15) as $i) {
2482             \core_message\api::add_contact($users[1]->id, $users[$i]->id);
2483         }
2485         // Set as the user performing the search.
2486         $this->setUser($users[1]);
2488         // Search using a limit of 3.
2489         // This tests the case where we have more results than the limit for both contacts and non-contacts.
2490         $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3);
2491         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2492         $contacts = $result['contacts'];
2493         $noncontacts = $result['noncontacts'];
2495         // Check that we retrieved the correct contacts.
2496         $this->assertCount(3, $contacts);
2497         $this->assertEquals($users[11]->id, $contacts[0]['id']);
2498         $this->assertEquals($users[12]->id, $contacts[1]['id']);
2499         $this->assertEquals($users[13]->id, $contacts[2]['id']);
2501         // Check that we retrieved the correct non-contacts.
2502         $this->assertCount(3, $noncontacts);
2503         $this->assertEquals($users[2]->id, $noncontacts[0]['id']);
2504         $this->assertEquals($users[3]->id, $noncontacts[1]['id']);
2505         $this->assertEquals($users[4]->id, $noncontacts[2]['id']);
2507         // Now, offset to get the next batch of results.
2508         // We expect to see 2 contacts, and 3 non-contacts.
2509         $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3);
2510         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2511         $contacts = $result['contacts'];
2512         $noncontacts = $result['noncontacts'];
2513         $this->assertCount(2, $contacts);
2514         $this->assertEquals($users[14]->id, $contacts[0]['id']);
2515         $this->assertEquals($users[15]->id, $contacts[1]['id']);
2517         $this->assertCount(3, $noncontacts);
2518         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2519         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2520         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2522         // Now, offset to get the next batch of results.
2523         // We expect to see 0 contacts, and 2 non-contacts.
2524         $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3);
2525         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2526         $contacts = $result['contacts'];
2527         $noncontacts = $result['noncontacts'];
2528         $this->assertCount(0, $contacts);
2530         $this->assertCount(2, $noncontacts);
2531         $this->assertEquals($users[8]->id, $noncontacts[0]['id']);
2532         $this->assertEquals($users[9]->id, $noncontacts[1]['id']);
2533     }
2535     /**
2536      * Tests searching users as another user having the 'moodle/user:viewdetails' capability.
2537      */
2538     public function test_message_search_users_with_cap() {
2539         $this->resetAfterTest();
2540         global $DB;
2542         // Create some users.
2543         $users = [];
2544         foreach (range(1, 8) as $i) {
2545             $user = new stdClass();
2546             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2547             $user->lastname = $i;
2548             $user = $this->getDataGenerator()->create_user($user);
2549             $users[$i] = $user;
2550         }
2552         // Enrol a few users in the same course, but leave them as non-contacts.
2553         $course1 = $this->getDataGenerator()->create_course();
2554         $this->setAdminUser();
2555         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2556         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2557         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2559         // Add some other users as contacts.
2560         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2561         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2562         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2564         // Set as the user performing the search.
2565         $this->setUser($users[1]);
2567         // Grant the authenticated user role the capability 'user:viewdetails' at site context.
2568         $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
2569         assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
2571         // Perform a search with $CFG->messagingallusers disabled.
2572         set_config('messagingallusers', 0);
2573         $result = core_message_external::message_search_users($users[1]->id, 'search');
2574         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2575         $contacts = $result['contacts'];
2576         $noncontacts = $result['noncontacts'];
2578         // Check that we retrieved the correct contacts.
2579         $this->assertCount(2, $contacts);
2580         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2581         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2583         // Check that we retrieved the correct non-contacts.
2584         // Site-wide messaging is disabled, but since we can see all users, we expect to be able to search for any users.
2585         $this->assertCount(4, $noncontacts);
2586         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2587         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2588         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2589         $this->assertEquals($users[8]->id, $noncontacts[3]['id']);
2590     }
2592     /**
2593      * Tests searching users as another user without the 'moodle/user:viewdetails' capability.
2594      */
2595     public function test_message_search_users_without_cap() {
2596         $this->resetAfterTest();
2598         // Create some users.
2599         $user1 = $this->getDataGenerator()->create_user();
2600         $user2 = $this->getDataGenerator()->create_user();
2602         // The person doing the search for another user.
2603         $this->setUser($user1);
2605         // Ensure an exception is thrown.
2606         $this->expectException('moodle_exception');
2607         core_message_external::message_search_users($user2->id, 'User');
2608         $this->assertDebuggingCalled();
2609     }
2611     /**
2612      * Tests searching users with messaging disabled.
2613      */
2614     public function test_message_search_users_messaging_disabled() {
2615         $this->resetAfterTest();
2617         // Create some skeleton data just so we can call the WS.
2618         $user = $this->getDataGenerator()->create_user();
2620         // The person doing the search.
2621         $this->setUser($user);
2623         // Disable messaging.
2624         set_config('messaging', 0);
2626         // Ensure an exception is thrown.
2627         $this->expectException('moodle_exception');
2628         core_message_external::message_search_users($user->id, 'User');
2629     }
2631     /**
2632      * Tests searching messages.
2633      */
2634     public function test_messagearea_search_messages() {
2635         $this->resetAfterTest(true);
2637         // Create some users.
2638         $user1 = self::getDataGenerator()->create_user();
2639         $user2 = self::getDataGenerator()->create_user();
2641         // The person doing the search.
2642         $this->setUser($user1);
2644         // Send some messages back and forth.
2645         $time = time();
2646         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2647         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2648         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2649         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2651         // Perform a search.
2652         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2654         // We need to execute the return values cleaning process to simulate the web service server.
2655         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(),
2656             $result);
2658         // Confirm the data is correct.
2659         $messages = $result['contacts'];
2660         $this->assertCount(2, $messages);
2662         $message1 = $messages[0];
2663         $message2 = $messages[1];
2665         $this->assertEquals($user2->id, $message1['userid']);
2666         $this->assertEquals(fullname($user2), $message1['fullname']);
2667         $this->assertTrue($message1['ismessaging']);
2668         $this->assertFalse($message1['sentfromcurrentuser']);
2669         $this->assertEquals('Word.', $message1['lastmessage']);
2670         $this->assertNotEmpty($message1['messageid']);
2671         $this->assertNull($message1['isonline']);
2672         $this->assertFalse($message1['isread']);
2673         $this->assertFalse($message1['isblocked']);
2674         $this->assertNull($message1['unreadcount']);
2676         $this->assertEquals($user2->id, $message2['userid']);
2677         $this->assertEquals(fullname($user2), $message2['fullname']);
2678         $this->assertTrue($message2['ismessaging']);
2679         $this->assertTrue($message2['sentfromcurrentuser']);
2680         $this->assertEquals('Yo!', $message2['lastmessage']);
2681         $this->assertNotEmpty($message2['messageid']);
2682         $this->assertNull($message2['isonline']);
2683         $this->assertTrue($message2['isread']);
2684         $this->assertFalse($message2['isblocked']);
2685         $this->assertNull($message2['unreadcount']);
2686     }
2688     /**
2689      * Tests searching messages as another user.
2690      */
2691     public function test_messagearea_search_messages_as_other_user() {
2692         $this->resetAfterTest(true);
2694         // The person doing the search.
2695         $this->setAdminUser();
2697         // Create some users.
2698         $user1 = self::getDataGenerator()->create_user();
2699         $user2 = self::getDataGenerator()->create_user();
2701         // Send some messages back and forth.
2702         $time = time();
2703         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2704         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2705         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2706         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2708         // Perform a search.
2709         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2711         // We need to execute the return values cleaning process to simulate the web service server.
2712         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(),
2713             $result);
2715         // Confirm the data is correct.
2716         $messages = $result['contacts'];
2717         $this->assertCount(2, $messages);
2719         $message1 = $messages[0];
2720         $message2 = $messages[1];
2722         $this->assertEquals($user2->id, $message1['userid']);
2723         $this->assertEquals(fullname($user2), $message1['fullname']);
2724         $this->assertTrue($message1['ismessaging']);
2725         $this->assertFalse($message1['sentfromcurrentuser']);
2726         $this->assertEquals('Word.', $message1['lastmessage']);
2727         $this->assertNotEmpty($message1['messageid']);
2728         $this->assertFalse($message1['isonline']);
2729         $this->assertFalse($message1['isread']);
2730         $this->assertFalse($message1['isblocked']);
2731         $this->assertNull($message1['unreadcount']);
2733         $this->assertEquals($user2->id, $message2['userid']);
2734         $this->assertEquals(fullname($user2), $message2['fullname']);
2735         $this->assertTrue($message2['ismessaging']);
2736         $this->assertTrue($message2['sentfromcurrentuser']);
2737         $this->assertEquals('Yo!', $message2['lastmessage']);
2738         $this->assertNotEmpty($message2['messageid']);
2739         $this->assertFalse($message2['isonline']);
2740         $this->assertTrue($message2['isread']);
2741         $this->assertFalse($message2['isblocked']);
2742         $this->assertNull($message2['unreadcount']);
2743     }
2745     /**
2746      * Tests searching messages as another user without the proper capabilities.
2747      */
2748     public function test_messagearea_search_messages_as_other_user_without_cap() {
2749         $this->resetAfterTest(true);
2751         // Create some users.
2752         $user1 = self::getDataGenerator()->create_user();
2753         $user2 = self::getDataGenerator()->create_user();
2755         // The person doing the search for another user.
2756         $this->setUser($user1);
2758         // Ensure an exception is thrown.
2759         $this->expectException('moodle_exception');
2760         core_message_external::data_for_messagearea_search_messages($user2->id, 'Search');
2761     }
2763     /**
2764      * Tests searching messages with messaging disabled
2765      */
2766     public function test_messagearea_search_messages_messaging_disabled() {
2767         global $CFG;
2769         $this->resetAfterTest(true);
2771         // Create some skeleton data just so we can call the WS.
2772         $user = self::getDataGenerator()->create_user();
2774         // The person doing the search .
2775         $this->setUser($user);
2777         // Disable messaging.
2778         $CFG->messaging = 0;
2780         // Ensure an exception is thrown.
2781         $this->expectException('moodle_exception');
2782         core_message_external::data_for_messagearea_search_messages($user->id, 'Search');
2783     }
2785     /**
2786      * Tests retrieving conversations.
2787      */
2788     public function test_messagearea_conversations() {
2789         $this->resetAfterTest(true);
2791         // Create some users.
2792         $user1 = self::getDataGenerator()->create_user();
2793         $user2 = self::getDataGenerator()->create_user();
2794         $user3 = self::getDataGenerator()->create_user();
2795         $user4 = self::getDataGenerator()->create_user();
2797         // The person retrieving the conversations.
2798         $this->setUser($user1);
2800         // Send some messages back and forth, have some different conversations with different users.
2801         $time = time();
2802         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2803         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2804         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2805         $messageid1 = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2807         $this->send_message($user1, $user3, 'Booyah', 0, $time + 4);
2808         $this->send_message($user3, $user1, 'Whaaat?', 0, $time + 5);
2809         $this->send_message($user1, $user3, 'Nothing.', 0, $time + 6);
2810         $messageid2 = $this->send_message($user3, $user1, 'Cool.', 0, $time + 7);
2812         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 8);
2813         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 9);
2814         $messageid3 = $this->send_message($user1, $user4, 'Dope.', 0, $time + 10);
2816         // Retrieve the conversations.
2817         $result = core_message_external::data_for_messagearea_conversations($user1->id);
2819         // We need to execute the return values cleaning process to simulate the web service server.
2820         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_conversations_returns(),
2821             $result);
2823         // Confirm the data is correct.
2824         $messages = $result['contacts'];
2825         $this->assertCount(3, $messages);
2827         $message1 = $messages[0];
2828         $message2 = $messages[1];
2829         $message3 = $messages[2];
2831         $this->assertEquals($user4->id, $message1['userid']);
2832         $this->assertTrue($message1['ismessaging']);
2833         $this->assertTrue($message1['sentfromcurrentuser']);
2834         $this->assertEquals('Dope.', $message1['lastmessage']);
2835         $this->assertEquals($messageid3, $message1['messageid']);
2836         $this->assertNull($message1['isonline']);
2837         $this->assertFalse($message1['isread']);
2838         $this->assertFalse($message1['isblocked']);
2839         $this->assertEquals(1, $message1['unreadcount']);
2841         $this->assertEquals($user3->id, $message2['userid']);
2842         $this->assertTrue($message2['ismessaging']);
2843         $this->assertFalse($message2['sentfromcurrentuser']);
2844         $this->assertEquals('Cool.', $message2['lastmessage']);
2845         $this->assertEquals($messageid2, $message2['messageid']);
2846         $this->assertNull($message2['isonline']);
2847         $this->assertFalse($message2['isread']);
2848         $this->assertFalse($message2['isblocked']);
2849         $this->assertEquals(2, $message2['unreadcount']);
2851         $this->assertEquals($user2->id, $message3['userid']);
2852         $this->assertTrue($message3['ismessaging']);
2853         $this->assertFalse($message3['sentfromcurrentuser']);
2854         $this->assertEquals('Word.', $message3['lastmessage']);
2855         $this->assertEquals($messageid1, $message3['messageid']);
2856         $this->assertNull($message3['isonline']);
2857         $this->assertFalse($message3['isread']);
2858         $this->assertFalse($message3['isblocked']);
2859         $this->assertEquals(2, $message3['unreadcount']);
2860     }
2862     /**
2863      * Tests retrieving conversations as another user.
2864      */
2865     public function test_messagearea_conversations_as_other_user() {
2866         $this->resetAfterTest(true);
2868         // Set as admin.
2869         $this->setAdminUser();
2871         // Create some users.
2872         $user1 = self::getDataGenerator()->create_user();
2873         $user2 = self::getDataGenerator()->create_user();
2874         $user3 = self::getDataGenerator()->create_user();
2875         $user4 = self::getDataGenerator()->create_user();
2877         // Send some messages back and forth, have some different conversations with different users.
2878         $time = time();
2879         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2880         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2881         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2882         $messageid1 = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2884         $this->send_message($user1, $user3, 'Booyah', 0, $time + 4);
2885         $this->send_message($user3, $user1, 'Whaaat?', 0, $time + 5);
2886         $this->send_message($user1, $user3, 'Nothing.', 0, $time + 6);
2887         $messageid2 = $this->send_message($user3, $user1, 'Cool.', 0, $time + 7);
2889         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 8);
2890         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 9);
2891         $messageid3 = $this->send_message($user1, $user4, 'Dope.', 0, $time + 10);
2893         // Retrieve the conversations.
2894         $result = core_message_external::data_for_messagearea_conversations($user1->id);
2896         // We need to execute the return values cleaning process to simulate the web service server.
2897         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_conversations_returns(),
2898             $result);
2900         // Confirm the data is correct.
2901         $messages = $result['contacts'];
2902         $this->assertCount(3, $messages);
2904         $message1 = $messages[0];
2905         $message2 = $messages[1];
2906         $message3 = $messages[2];
2908         $this->assertEquals($user4->id, $message1['userid']);
2909         $this->assertTrue($message1['ismessaging']);
2910         $this->assertTrue($message1['sentfromcurrentuser']);
2911         $this->assertEquals('Dope.', $message1['lastmessage']);
2912         $this->assertEquals($messageid3, $message1['messageid']);
2913         $this->assertFalse($message1['isonline']);
2914         $this->assertFalse($message1['isread']);
2915         $this->assertFalse($message1['isblocked']);
2916         $this->assertEquals(1, $message1['unreadcount']);
2918         $this->assertEquals($user3->id, $message2['userid']);
2919         $this->assertTrue($message2['ismessaging']);
2920         $this->assertFalse($message2['sentfromcurrentuser']);
2921         $this->assertEquals('Cool.', $message2['lastmessage']);
2922         $this->assertEquals($messageid2, $message2['messageid']);
2923         $this->assertFalse($message2['isonline']);
2924         $this->assertFalse($message2['isread']);
2925         $this->assertFalse($message2['isblocked']);
2926         $this->assertEquals(2, $message2['unreadcount']);
2928         $this->assertEquals($user2->id, $message3['userid']);
2929         $this->assertTrue($message3['ismessaging']);
2930         $this->assertFalse($message3['sentfromcurrentuser']);
2931         $this->assertEquals('Word.', $message3['lastmessage']);
2932         $this->assertEquals($messageid1, $message3['messageid']);
2933         $this->assertFalse($message3['isonline']);
2934         $this->assertFalse($message3['isread']);
2935         $this->assertFalse($message3['isblocked']);
2936         $this->assertEquals(2, $message3['unreadcount']);
2937     }
2939     /**
2940      * Tests retrieving conversations as another user without the proper capabilities.
2941      */
2942     public function test_messagearea_conversations_as_other_user_without_cap() {
2943         $this->resetAfterTest(true);
2945         // Create some users.
2946         $user1 = self::getDataGenerator()->create_user();
2947         $user2 = self::getDataGenerator()->create_user();
2949         // The person retrieving the conversations for another user.
2950         $this->setUser($user1);
2952         // Ensure an exception is thrown.
2953         $this->expectException('moodle_exception');
2954         core_message_external::data_for_messagearea_conversations($user2->id);
2955     }
2957     /**
2958      * Tests retrieving conversations with messaging disabled.
2959      */
2960     public function test_messagearea_conversations_messaging_disabled() {
2961         global $CFG;
2963         $this->resetAfterTest(true);
2965         // Create some skeleton data just so we can call the WS.
2966         $user = self::getDataGenerator()->create_user();
2968         // The person retrieving the conversations.
2969         $this->setUser($user);
2971         // Disable messaging.
2972         $CFG->messaging = 0;
2974         // Ensure an exception is thrown.
2975         $this->expectException('moodle_exception');
2976         core_message_external::data_for_messagearea_conversations($user->id);
2977     }
2979     /**
2980      * Tests retrieving contacts.
2981      */
2982     public function test_messagearea_contacts() {
2983         $this->resetAfterTest(true);
2985         // Create some users.
2986         $user1 = self::getDataGenerator()->create_user();
2988         // Set as the user.
2989         $this->setUser($user1);
2991         $user2 = new stdClass();
2992         $user2->firstname = 'User';
2993         $user2->lastname = 'A';
2994         $user2 = self::getDataGenerator()->create_user($user2);
2996         $user3 = new stdClass();
2997         $user3->firstname = 'User';
2998         $user3->lastname = 'B';
2999         $user3 = self::getDataGenerator()->create_user($user3);
3001         $user4 = new stdClass();
3002         $user4->firstname = 'User';
3003         $user4->lastname = 'C';
3004         $user4 = self::getDataGenerator()->create_user($user4);
3006         $user5 = new stdClass();
3007         $user5->firstname = 'User';
3008         $user5->lastname = 'D';
3009         $user5 = self::getDataGenerator()->create_user($user5);
3011         // Add some users as contacts.
3012         \core_message\api::add_contact($user1->id, $user2->id);
3013         \core_message\api::add_contact($user1->id, $user3->id);
3014         \core_message\api::add_contact($user1->id, $user4->id);
3016         // Retrieve the contacts.
3017         $result = core_message_external::data_for_messagearea_contacts($user1->id);
3019         // We need to execute the return values cleaning process to simulate the web service server.
3020         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_contacts_returns(),
3021             $result);
3023         // Confirm the data is correct.
3024         $contacts = $result['contacts'];
3025         usort($contacts, ['static', 'sort_contacts']);
3026         $this->assertCount(3, $contacts);
3028         $contact1 = $contacts[0];
3029         $contact2 = $contacts[1];
3030         $contact3 = $contacts[2];
3032         $this->assertEquals($user2->id, $contact1['userid']);
3033         $this->assertFalse($contact1['ismessaging']);
3034         $this->assertFalse($contact1['sentfromcurrentuser']);
3035         $this->assertNull($contact1['lastmessage']);
3036         $this->assertNull($contact1['messageid']);
3037         $this->assertNull($contact1['isonline']);
3038         $this->assertFalse($contact1['isread']);
3039         $this->assertFalse($contact1['isblocked']);
3040         $this->assertNull($contact1['unreadcount']);
3042         $this->assertEquals($user3->id, $contact2['userid']);
3043         $this->assertFalse($contact2['ismessaging']);
3044         $this->assertFalse($contact2['sentfromcurrentuser']);
3045         $this->assertNull($contact2['lastmessage']);
3046         $this->assertNull($contact2['messageid']);
3047         $this->assertNull($contact2['isonline']);
3048         $this->assertFalse($contact2['isread']);
3049         $this->assertFalse($contact2['isblocked']);
3050         $this->assertNull($contact2['unreadcount']);
3052         $this->assertEquals($user4->id, $contact3['userid']);
3053         $this->assertFalse($contact3['ismessaging']);
3054         $this->assertFalse($contact3['sentfromcurrentuser']);
3055         $this->assertNull($contact3['lastmessage']);
3056         $this->assertNull($contact3['messageid']);
3057         $this->assertNull($contact3['isonline']);
3058         $this->assertFalse($contact3['isread']);
3059         $this->assertFalse($contact3['isblocked']);
3060         $this->assertNull($contact3['unreadcount']);
3061     }
3063     /**
3064      * Tests retrieving contacts as another user.
3065      */
3066     public function test_messagearea_contacts_as_other_user() {
3067         $this->resetAfterTest(true);
3069         $this->setAdminUser();
3071         // Create some users.
3072         $user1 = self::getDataGenerator()->create_user();
3074         $user2 = new stdClass();
3075         $user2->firstname = 'User';
3076         $user2->lastname = 'A';
3077         $user2 = self::getDataGenerator()->create_user($user2);
3079         $user3 = new stdClass();
3080         $user3->firstname = 'User';
3081         $user3->lastname = 'B';
3082         $user3 = self::getDataGenerator()->create_user($user3);
3084         $user4 = new stdClass();
3085         $user4->firstname = 'User';
3086         $user4->lastname = 'C';
3087         $user4 = self::getDataGenerator()->create_user($user4);
3089         $user5 = new stdClass();
3090         $user5->firstname = 'User';
3091         $user5->lastname = 'D';
3092         $user5 = self::getDataGenerator()->create_user($user5);
3094         // Add some users as contacts.
3095         \core_message\api::add_contact($user1->id, $user2->id);
3096         \core_message\api::add_contact($user1->id, $user3->id);
3097         \core_message\api::add_contact($user1->id, $user4->id);
3099         // Retrieve the contacts.
3100         $result = core_message_external::data_for_messagearea_contacts($user1->id);
3102         // We need to execute the return values cleaning process to simulate the web service server.
3103         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_contacts_returns(),
3104             $result);
3106         // Confirm the data is correct.
3107         $contacts = $result['contacts'];
3108         usort($contacts, ['static', 'sort_contacts']);
3109         $this->assertCount(3, $contacts);
3111         $contact1 = $contacts[0];
3112         $contact2 = $contacts[1];
3113         $contact3 = $contacts[2];
3115         $this->assertEquals($user2->id, $contact1['userid']);
3116         $this->assertFalse($contact1['ismessaging']);
3117         $this->assertFalse($contact1['sentfromcurrentuser']);
3118         $this->assertNull($contact1['lastmessage']);
3119         $this->assertNull($contact1['messageid']);
3120         $this->assertFalse($contact1['isonline']);
3121         $this->assertFalse($contact1['isread']);
3122         $this->assertFalse($contact1['isblocked']);
3123         $this->assertNull($contact1['unreadcount']);
3125         $this->assertEquals($user3->id, $contact2['userid']);
3126         $this->assertFalse($contact2['ismessaging']);
3127         $this->assertFalse($contact2['sentfromcurrentuser']);
3128         $this->assertNull($contact2['lastmessage']);
3129         $this->assertNull($contact2['messageid']);
3130         $this->assertFalse($contact2['isonline']);
3131         $this->assertFalse($contact2['isread']);
3132         $this->assertFalse($contact2['isblocked']);
3133         $this->assertNull($contact2['unreadcount']);
3135         $this->assertEquals($user4->id, $contact3['userid']);
3136         $this->assertFalse($contact3['ismessaging']);
3137         $this->assertFalse($contact3['sentfromcurrentuser']);
3138         $this->assertNull($contact3['lastmessage']);
3139         $this->assertNull($contact3['messageid']);
3140         $this->assertFalse($contact3['isonline']);
3141         $this->assertFalse($contact3['isread']);
3142         $this->assertFalse($contact3['isblocked']);
3143         $this->assertNull($contact3['unreadcount']);
3144     }
3146     /**
3147      * Tests retrieving contacts as another user without the proper capabilities.
3148      */
3149     public function test_messagearea_contacts_as_other_user_without_cap() {
3150         $this->resetAfterTest(true);
3152         // Create some users.
3153         $user1 = self::getDataGenerator()->create_user();
3154         $user2 = self::getDataGenerator()->create_user();
3156         // The person retrieving the contacts for another user.
3157         $this->setUser($user1);
3159         // Perform the WS call and ensure an exception is thrown.
3160         $this->expectException('moodle_exception');
3161         core_message_external::data_for_messagearea_contacts($user2->id);
3162     }
3164     /**
3165      * Tests retrieving contacts with messaging disabled.
3166      */
3167     public function test_messagearea_contacts_messaging_disabled() {
3168         global $CFG;
3170         $this->resetAfterTest(true);
3172         // Create some skeleton data just so we can call the WS.
3173         $user = self::getDataGenerator()->create_user();
3175         // The person retrieving the contacts.
3176         $this->setUser($user);
3178         // Disable messaging.
3179         $CFG->messaging = 0;
3181         // Perform the WS call and ensure we are shown that it is disabled.
3182         $this->expectException('moodle_exception');
3183         core_message_external::data_for_messagearea_contacts($user->id);
3184     }
3186     /**
3187      * Tests retrieving messages.
3188      */
3189     public function test_messagearea_messages() {
3190         $this->resetAfterTest(true);
3192         // Create some users.
3193         $user1 = self::getDataGenerator()->create_user();
3194         $user2 = self::getDataGenerator()->create_user();
3196         // The person asking for the messages.
3197         $this->setUser($user1);
3199         // Send some messages back and forth.
3200         $time = time();
3201         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3202         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3203         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3204         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3206         // Retrieve the messages.
3207         $result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id);
3209         // We need to execute the return values cleaning process to simulate the web service server.
3210         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_messages_returns(),
3211             $result);
3213         // Check the results are correct.
3214         $this->assertTrue($result['iscurrentuser']);
3215         $this->assertEquals($user1->id, $result['currentuserid']);
3216         $this->assertEquals($user2->id, $result['otheruserid']);
3217         $this->assertEquals(fullname($user2), $result['otheruserfullname']);
3218         $this->assertNull($result['isonline']);
3220         // Confirm the message data is correct.
3221         $messages = $result['messages'];
3222         $this->assertCount(4, $messages);
3224         $message1 = $messages[0];
3225         $message2 = $messages[1];
3226         $message3 = $messages[2];
3227         $message4 = $messages[3];
3229         $this->assertEquals($user1->id, $message1['useridfrom']);
3230         $this->assertEquals($user2->id, $message1['useridto']);
3231         $this->assertTrue($message1['displayblocktime']);
3232         $this->assertContains('Yo!', $message1['text']);
3234         $this->assertEquals($user2->id, $message2['useridfrom']);
3235         $this->assertEquals($user1->id, $message2['useridto']);
3236         $this->assertFalse($message2['displayblocktime']);
3237         $this->assertContains('Sup mang?', $message2['text']);
3239         $this->assertEquals($user1->id, $message3['useridfrom']);
3240         $this->assertEquals($user2->id, $message3['useridto']);
3241         $this->assertFalse($message3['displayblocktime']);
3242         $this->assertContains('Writing PHPUnit tests!', $message3['text']);
3244         $this->assertEquals($user2->id, $message4['useridfrom']);
3245         $this->assertEquals($user1->id, $message4['useridto']);
3246         $this->assertFalse($message4['displayblocktime']);
3247         $this->assertContains('Word.', $message4['text']);
3248     }
3250     /**
3251      * Tests retrieving messages.
3252      */
3253     public function test_messagearea_messages_timefrom() {
3254         $this->resetAfterTest(true);
3256         // Create some users.
3257         $user1 = self::getDataGenerator()->create_user();
3258         $user2 = self::getDataGenerator()->create_user();
3260         // The person asking for the messages.
3261         $this->setUser($user1);
3263         // Send some messages back and forth.
3264         $time = time();
3265         $this->send_message($user1, $user2, 'Message 1', 0, $time - 4);
3266         $this->send_message($user2, $user1, 'Message 2', 0, $time - 3);
3267         $this->send_message($user1, $user2, 'Message 3', 0, $time - 2);
3268         $this->send_message($user2, $user1, 'Message 4', 0, $time - 1);
3270         // Retrieve the messages from $time - 3, which should be the 3 most recent messages.
3271         $result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id, 0, 0, false, $time - 3);
3273         // We need to execute the return values cleaning process to simulate the web service server.
3274         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_messages_returns(),
3275             $result);
3277         // Confirm the message data is correct. We shouldn't get 'Message 1' back.
3278         $messages = $result['messages'];
3279         $this->assertCount(3, $messages);
3281         $message1 = $messages[0];
3282         $message2 = $messages[1];
3283         $message3 = $messages[2];
3285         $this->assertContains('Message 2', $message1['text']);
3286         $this->assertContains('Message 3', $message2['text']);
3287         $this->assertContains('Message 4', $message3['text']);
3288     }
3290     /**
3291      * Tests retrieving messages as another user.
3292      */
3293     public function test_messagearea_messages_as_other_user() {
3294         $this->resetAfterTest(true);
3296         // Set as admin.
3297         $this->setAdminUser();
3299         // Create some users.
3300         $user1 = self::getDataGenerator()->create_user();
3301         $user2 = self::getDataGenerator()->create_user();
3303         // Send some messages back and forth.
3304         $time = time();
3305         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3306         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3307         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3308         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3310         // Retrieve the messages.
3311         $result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id);
3313         // We need to execute the return values cleaning process to simulate the web service server.
3314         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_messages_returns(),
3315             $result);
3317         // Check the results are correct.
3318         $this->assertFalse($result['iscurrentuser']);
3319         $this->assertEquals($user1->id, $result['currentuserid']);
3320         $this->assertEquals($user2->id, $result['otheruserid']);
3321         $this->assertEquals(fullname($user2), $result['otheruserfullname']);
3322         $this->assertFalse($result['isonline']);
3324         // Confirm the message data is correct.
3325         $messages = $result['messages'];
3326         $this->assertCount(4, $messages);
3328         $message1 = $messages[0];
3329         $message2 = $messages[1];
3330         $message3 = $messages[2];
3331         $message4 = $messages[3];
3333         $this->assertEquals($user1->id, $message1['useridfrom']);
3334         $this->assertEquals($user2->id, $message1['useridto']);
3335         $this->assertTrue($message1['displayblocktime']);
3336         $this->assertContains('Yo!', $message1['text']);
3338         $this->assertEquals($user2->id, $message2['useridfrom']);
3339         $this->assertEquals($user1->id, $message2['useridto']);
3340         $this->assertFalse($message2['displayblocktime']);
3341         $this->assertContains('Sup mang?', $message2['text']);
3343         $this->assertEquals($user1->id, $message3['useridfrom']);
3344         $this->assertEquals($user2->id, $message3['useridto']);
3345         $this->assertFalse($message3['displayblocktime']);
3346         $this->assertContains('Writing PHPUnit tests!', $message3['text']);
3348         $this->assertEquals($user2->id, $message4['useridfrom']);
3349         $this->assertEquals($user1->id, $message4['useridto']);
3350         $this->assertFalse($message4['displayblocktime']);
3351         $this->assertContains('Word.', $message4['text']);
3352     }
3354     /**
3355      * Tests retrieving messages as another user without the proper capabilities.
3356      */
3357     public function test_messagearea_messages_as_other_user_without_cap() {
3358         $this->resetAfterTest(true);
3360         // Create some users.
3361         $user1 = self::getDataGenerator()->create_user();
3362         $user2 = self::getDataGenerator()->create_user();
3363         $user3 = self::getDataGenerator()->create_user();
3365         // The person asking for the messages for another user.
3366         $this->setUser($user1);
3368         // Ensure an exception is thrown.
3369         $this->expectException('moodle_exception');
3370         core_message_external::data_for_messagearea_messages($user2->id, $user3->id);
3371     }
3373     /**
3374      * Tests retrieving messages with messaging disabled.
3375      */
3376     public function test_messagearea_messages_messaging_disabled() {
3377         global $CFG;
3379         $this->resetAfterTest(true);
3381 &nb