MDL-64034 core_message: return conversationid in search_messages()
[moodle.git] / message / tests / externallib_test.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * External message functions unit tests
19  *
20  * @package    core_message
21  * @category   external
22  * @copyright  2012 Jerome Mouneyrac
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
31 require_once($CFG->dirroot . '/message/externallib.php');
33 use \core_message\tests\helper as testhelper;
35 class core_message_externallib_testcase extends externallib_advanced_testcase {
37     /**
38      * Tests set up
39      */
40     protected function setUp() {
41         global $CFG;
43         require_once($CFG->dirroot . '/message/lib.php');
44     }
46     /**
47      * Send a fake message.
48      *
49      * {@link message_send()} does not support transaction, this function will simulate a message
50      * sent from a user to another. We should stop using it once {@link message_send()} will support
51      * transactions. This is not clean at all, this is just used to add rows to the table.
52      *
53      * @param stdClass $userfrom user object of the one sending the message.
54      * @param stdClass $userto user object of the one receiving the message.
55      * @param string $message message to send.
56      * @param int $notification is the message a notification.
57      * @param int $time the time the message was sent
58      */
59     protected function send_message($userfrom, $userto, $message = 'Hello world!', $notification = 0, $time = 0) {
60         global $DB;
62         if (empty($time)) {
63             $time = time();
64         }
66         if ($notification) {
67             $record = new stdClass();
68             $record->useridfrom = $userfrom->id;
69             $record->useridto = $userto->id;
70             $record->subject = 'No subject';
71             $record->fullmessage = $message;
72             $record->smallmessage = $message;
73             $record->timecreated = $time;
75             return $DB->insert_record('notifications', $record);
76         }
78         if (!$conversationid = \core_message\api::get_conversation_between_users([$userfrom->id, $userto->id])) {
79             $conversation = \core_message\api::create_conversation(
80                 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
81                 [
82                     $userfrom->id,
83                     $userto->id
84                 ]
85             );
86             $conversationid = $conversation->id;
87         }
89         // Ok, send the message.
90         $record = new stdClass();
91         $record->useridfrom = $userfrom->id;
92         $record->conversationid = $conversationid;
93         $record->subject = 'No subject';
94         $record->fullmessage = $message;
95         $record->smallmessage = $message;
96         $record->timecreated = $time;
98         return $DB->insert_record('messages', $record);
99     }
101     /**
102      * Test send_instant_messages.
103      */
104     public function test_send_instant_messages() {
105         global $DB, $USER;
107         $this->resetAfterTest();
109         // Transactions used in tests, tell phpunit use alternative reset method.
110         $this->preventResetByRollback();
112         $user1 = self::getDataGenerator()->create_user();
113         $user2 = self::getDataGenerator()->create_user();
115         $this->setUser($user1);
117         // Create test message data.
118         $message1 = array();
119         $message1['touserid'] = $user2->id;
120         $message1['text'] = 'the message.';
121         $message1['clientmsgid'] = 4;
122         $messages = array($message1);
124         $sentmessages = core_message_external::send_instant_messages($messages);
125         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
126         $this->assertEquals(
127             get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message1['touserid']))),
128             array_pop($sentmessages)['errormessage']
129         );
131         // Add the user1 as a contact.
132         \core_message\api::add_contact($user1->id, $user2->id);
134         // Send message again. Now it should work properly.
135         $sentmessages = core_message_external::send_instant_messages($messages);
136         // We need to execute the return values cleaning process to simulate the web service server.
137         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
139         $sentmessage = reset($sentmessages);
141         $sql = "SELECT m.*, mcm.userid as useridto
142                  FROM {messages} m
143            INNER JOIN {message_conversations} mc
144                    ON m.conversationid = mc.id
145            INNER JOIN {message_conversation_members} mcm
146                    ON mcm.conversationid = mc.id
147                 WHERE mcm.userid != ?
148                   AND m.id = ?";
149         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
151         // Confirm that the message was inserted correctly.
152         $this->assertEquals($themessage->useridfrom, $user1->id);
153         $this->assertEquals($themessage->useridto, $message1['touserid']);
154         $this->assertEquals($themessage->smallmessage, $message1['text']);
155         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
156     }
158     /**
159      * Test send_instant_messages to a user who has blocked you.
160      */
161     public function test_send_instant_messages_blocked_user() {
162         global $DB;
164         $this->resetAfterTest();
166         // Transactions used in tests, tell phpunit use alternative reset method.
167         $this->preventResetByRollback();
169         $user1 = self::getDataGenerator()->create_user();
170         $user2 = self::getDataGenerator()->create_user();
172         $this->setUser($user1);
174         \core_message\api::block_user($user2->id, $user1->id);
176         // Create test message data.
177         $message1 = array();
178         $message1['touserid'] = $user2->id;
179         $message1['text'] = 'the message.';
180         $message1['clientmsgid'] = 4;
181         $messages = array($message1);
183         $sentmessages = core_message_external::send_instant_messages($messages);
184         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
186         $sentmessage = reset($sentmessages);
188         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
190         $this->assertEquals(0, $DB->count_records('messages'));
191     }
193     /**
194      * Test send_instant_messages when sending a message to a non-contact who has blocked non-contacts.
195      */
196     public function test_send_instant_messages_block_non_contacts() {
197         global $DB;
199         $this->resetAfterTest(true);
201         // Transactions used in tests, tell phpunit use alternative reset method.
202         $this->preventResetByRollback();
204         $user1 = self::getDataGenerator()->create_user();
205         $user2 = self::getDataGenerator()->create_user();
207         $this->setUser($user1);
209         // Set the user preference so user 2 does not accept messages from non-contacts.
210         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
212         // Create test message data.
213         $message1 = array();
214         $message1['touserid'] = $user2->id;
215         $message1['text'] = 'the message.';
216         $message1['clientmsgid'] = 4;
217         $messages = array($message1);
219         $sentmessages = core_message_external::send_instant_messages($messages);
220         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
222         $sentmessage = reset($sentmessages);
224         $this->assertEquals(get_string('usercantbemessaged', 'message', fullname($user2)), $sentmessage['errormessage']);
226         $this->assertEquals(0, $DB->count_records('messages'));
227     }
229     /**
230      * Test send_instant_messages when sending a message to a contact who has blocked non-contacts.
231      */
232     public function test_send_instant_messages_block_non_contacts_but_am_contact() {
233         global $DB, $USER;
235         $this->resetAfterTest(true);
237         // Transactions used in tests, tell phpunit use alternative reset method.
238         $this->preventResetByRollback();
240         $user1 = self::getDataGenerator()->create_user();
241         $user2 = self::getDataGenerator()->create_user();
243         $this->setUser($user1);
245         // Set the user preference so user 2 does not accept messages from non-contacts.
246         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2);
248         \core_message\api::add_contact($user1->id, $user2->id);
250         // Create test message data.
251         $message1 = array();
252         $message1['touserid'] = $user2->id;
253         $message1['text'] = 'the message.';
254         $message1['clientmsgid'] = 4;
255         $messages = array($message1);
257         $sentmessages = core_message_external::send_instant_messages($messages);
258         $sentmessages = external_api::clean_returnvalue(core_message_external::send_instant_messages_returns(), $sentmessages);
260         $sentmessage = reset($sentmessages);
262         $sql = "SELECT m.*, mcm.userid as useridto
263                  FROM {messages} m
264            INNER JOIN {message_conversations} mc
265                    ON m.conversationid = mc.id
266            INNER JOIN {message_conversation_members} mcm
267                    ON mcm.conversationid = mc.id
268                 WHERE mcm.userid != ?
269                   AND m.id = ?";
270         $themessage = $DB->get_record_sql($sql, [$USER->id, $sentmessage['msgid']]);
272         // Confirm that the message was inserted correctly.
273         $this->assertEquals($themessage->useridfrom, $user1->id);
274         $this->assertEquals($themessage->useridto, $message1['touserid']);
275         $this->assertEquals($themessage->smallmessage, $message1['text']);
276         $this->assertEquals($sentmessage['clientmsgid'], $message1['clientmsgid']);
277     }
279     /**
280      * Test send_instant_messages with no capabilities
281      */
282     public function test_send_instant_messages_no_capability() {
283         global $DB;
285         $this->resetAfterTest(true);
287         // Transactions used in tests, tell phpunit use alternative reset method.
288         $this->preventResetByRollback();
290         $user1 = self::getDataGenerator()->create_user();
291         $user2 = self::getDataGenerator()->create_user();
293         $this->setUser($user1);
295         // Unset the required capabilities by the external function.
296         $contextid = context_system::instance()->id;
297         $userrole = $DB->get_record('role', array('shortname' => 'user'));
298         $this->unassignUserCapability('moodle/site:sendmessage', $contextid, $userrole->id);
300         // Create test message data.
301         $message1 = array();
302         $message1['touserid'] = $user2->id;
303         $message1['text'] = 'the message.';
304         $message1['clientmsgid'] = 4;
305         $messages = array($message1);
307         $this->expectException('required_capability_exception');
308         core_message_external::send_instant_messages($messages);
309     }
311     /**
312      * Test send_instant_messages when messaging is disabled.
313      */
314     public function test_send_instant_messages_messaging_disabled() {
315         global $CFG;
317         $this->resetAfterTest(true);
319         // Transactions used in tests, tell phpunit use alternative reset method.
320         $this->preventResetByRollback();
322         $user1 = self::getDataGenerator()->create_user();
323         $user2 = self::getDataGenerator()->create_user();
325         $this->setUser($user1);
327         // Disable messaging.
328         $CFG->messaging = 0;
330         // Create test message data.
331         $message1 = array();
332         $message1['touserid'] = $user2->id;
333         $message1['text'] = 'the message.';
334         $message1['clientmsgid'] = 4;
335         $messages = array($message1);
337         $this->expectException('moodle_exception');
338         core_message_external::send_instant_messages($messages);
339     }
341     /**
342      * Test create_contacts.
343      */
344     public function test_create_contacts() {
345         $this->resetAfterTest(true);
347         $user1 = self::getDataGenerator()->create_user();
348         $user2 = self::getDataGenerator()->create_user();
349         $user3 = self::getDataGenerator()->create_user();
350         $user4 = self::getDataGenerator()->create_user();
351         $user5 = self::getDataGenerator()->create_user();
352         $this->setUser($user1);
354         // Adding a contact.
355         $return = core_message_external::create_contacts(array($user2->id));
356         $this->assertDebuggingCalled();
357         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
358         $this->assertEquals(array(), $return);
360         // Adding a contact who is already a contact.
361         $return = core_message_external::create_contacts(array($user2->id));
362         $this->assertDebuggingCalled();
363         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
364         $this->assertEquals(array(), $return);
366         // Adding multiple contacts.
367         $return = core_message_external::create_contacts(array($user3->id, $user4->id));
368         $this->assertDebuggingCalledCount(2);
369         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
370         $this->assertEquals(array(), $return);
372         // Adding a non-existing user.
373         $return = core_message_external::create_contacts(array(99999));
374         $this->assertDebuggingCalled();
375         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
376         $this->assertCount(1, $return);
377         $return = array_pop($return);
378         $this->assertEquals($return['warningcode'], 'contactnotcreated');
379         $this->assertEquals($return['itemid'], 99999);
381         // Adding contacts with valid and invalid parameters.
382         $return = core_message_external::create_contacts(array($user5->id, 99999));
383         $this->assertDebuggingCalledCount(2);
384         $return = external_api::clean_returnvalue(core_message_external::create_contacts_returns(), $return);
385         $this->assertCount(1, $return);
386         $return = array_pop($return);
387         $this->assertEquals($return['warningcode'], 'contactnotcreated');
388         $this->assertEquals($return['itemid'], 99999);
390         // Try to add a contact to another user, should throw an exception.
391         // All assertions must be added before this point.
392         $this->expectException('required_capability_exception');
393         core_message_external::create_contacts(array($user2->id), $user3->id);
394     }
396     /**
397      * Test delete_contacts.
398      */
399     public function test_delete_contacts() {
400         $this->resetAfterTest(true);
402         $user1 = self::getDataGenerator()->create_user();
403         $user2 = self::getDataGenerator()->create_user();
404         $user3 = self::getDataGenerator()->create_user();
405         $user4 = self::getDataGenerator()->create_user();
406         $user5 = self::getDataGenerator()->create_user();
407         $user6 = self::getDataGenerator()->create_user();
408         $this->setUser($user1);
410         \core_message\api::add_contact($user1->id, $user3->id);
411         \core_message\api::add_contact($user1->id, $user4->id);
412         \core_message\api::add_contact($user1->id, $user5->id);
413         \core_message\api::add_contact($user1->id, $user6->id);
415         // Removing a non-contact.
416         $return = core_message_external::delete_contacts(array($user2->id));
417         $this->assertNull($return);
419         // Removing one contact.
420         $return = core_message_external::delete_contacts(array($user3->id));
421         $this->assertNull($return);
423         // Removing multiple contacts.
424         $return = core_message_external::delete_contacts(array($user4->id, $user5->id));
425         $this->assertNull($return);
427         // Removing contact from unexisting user.
428         $return = core_message_external::delete_contacts(array(99999));
429         $this->assertNull($return);
431         // Removing mixed valid and invalid data.
432         $return = core_message_external::delete_contacts(array($user6->id, 99999));
433         $this->assertNull($return);
435         // Try to delete a contact of another user contact list, should throw an exception.
436         // All assertions must be added before this point.
437         $this->expectException('required_capability_exception');
438         core_message_external::delete_contacts(array($user2->id), $user3->id);
439     }
441     /**
442      * Test block_contacts.
443      */
444     public function test_block_contacts() {
445         $this->resetAfterTest(true);
447         $user1 = self::getDataGenerator()->create_user();
448         $user2 = self::getDataGenerator()->create_user();
449         $user3 = self::getDataGenerator()->create_user();
450         $user4 = self::getDataGenerator()->create_user();
451         $user5 = self::getDataGenerator()->create_user();
452         $this->setUser($user1);
454         \core_message\api::add_contact($user1->id, $user3->id);
455         \core_message\api::add_contact($user1->id, $user4->id);
456         \core_message\api::add_contact($user1->id, $user5->id);
458         // Blocking a contact.
459         $return = core_message_external::block_contacts(array($user2->id));
460         $this->assertDebuggingCalled();
461         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
462         $this->assertEquals(array(), $return);
464         // Blocking a contact who is already a contact.
465         $return = core_message_external::block_contacts(array($user2->id));
466         $this->assertDebuggingCalled();
467         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
468         $this->assertEquals(array(), $return);
470         // Blocking multiple contacts.
471         $return = core_message_external::block_contacts(array($user3->id, $user4->id));
472         $this->assertDebuggingCalledCount(2);
473         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
474         $this->assertEquals(array(), $return);
476         // Blocking a non-existing user.
477         $return = core_message_external::block_contacts(array(99999));
478         $this->assertDebuggingCalled();
479         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
480         $this->assertCount(1, $return);
481         $return = array_pop($return);
482         $this->assertEquals($return['warningcode'], 'contactnotblocked');
483         $this->assertEquals($return['itemid'], 99999);
485         // Blocking contacts with valid and invalid parameters.
486         $return = core_message_external::block_contacts(array($user5->id, 99999));
487         $this->assertDebuggingCalledCount(2);
488         $return = external_api::clean_returnvalue(core_message_external::block_contacts_returns(), $return);
489         $this->assertCount(1, $return);
490         $return = array_pop($return);
491         $this->assertEquals($return['warningcode'], 'contactnotblocked');
492         $this->assertEquals($return['itemid'], 99999);
494         // Try to block a contact of another user contact list, should throw an exception.
495         // All assertions must be added before this point.
496         $this->expectException('required_capability_exception');
497         core_message_external::block_contacts(array($user2->id), $user3->id);
498     }
500     /**
501      * Test unblock_contacts.
502      */
503     public function test_unblock_contacts() {
504         $this->resetAfterTest(true);
506         $user1 = self::getDataGenerator()->create_user();
507         $user2 = self::getDataGenerator()->create_user();
508         $user3 = self::getDataGenerator()->create_user();
509         $user4 = self::getDataGenerator()->create_user();
510         $user5 = self::getDataGenerator()->create_user();
511         $user6 = self::getDataGenerator()->create_user();
512         $this->setUser($user1);
514         \core_message\api::add_contact($user1->id, $user3->id);
515         \core_message\api::add_contact($user1->id, $user4->id);
516         \core_message\api::add_contact($user1->id, $user5->id);
517         \core_message\api::add_contact($user1->id, $user6->id);
519         // Removing a non-contact.
520         $return = core_message_external::unblock_contacts(array($user2->id));
521         $this->assertDebuggingCalled();
522         $this->assertNull($return);
524         // Removing one contact.
525         $return = core_message_external::unblock_contacts(array($user3->id));
526         $this->assertDebuggingCalled();
527         $this->assertNull($return);
529         // Removing multiple contacts.
530         $return = core_message_external::unblock_contacts(array($user4->id, $user5->id));
531         $this->assertDebuggingCalledCount(2);
532         $this->assertNull($return);
534         // Removing contact from unexisting user.
535         $return = core_message_external::unblock_contacts(array(99999));
536         $this->assertDebuggingCalled();
537         $this->assertNull($return);
539         // Removing mixed valid and invalid data.
540         $return = core_message_external::unblock_contacts(array($user6->id, 99999));
541         $this->assertDebuggingCalledCount(2);
542         $this->assertNull($return);
544         // Try to unblock a contact of another user contact list, should throw an exception.
545         // All assertions must be added before this point.
546         $this->expectException('required_capability_exception');
547         core_message_external::unblock_contacts(array($user2->id), $user3->id);
548         $this->assertDebuggingCalled();
549     }
551     /**
552      * Test getting contact requests.
553      */
554     public function test_get_contact_requests() {
555         global $PAGE;
557         $this->resetAfterTest();
559         $user1 = self::getDataGenerator()->create_user();
560         $user2 = self::getDataGenerator()->create_user();
561         $user3 = self::getDataGenerator()->create_user();
563         $this->setUser($user1);
565         // Block one user, their request should not show up.
566         \core_message\api::block_user($user1->id, $user3->id);
568         \core_message\api::create_contact_request($user2->id, $user1->id);
569         \core_message\api::create_contact_request($user3->id, $user1->id);
571         $requests = core_message_external::get_contact_requests($user1->id);
572         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
574         $this->assertCount(1, $requests);
576         $request = reset($requests);
577         $userpicture = new \user_picture($user2);
578         $profileimageurl = $userpicture->get_url($PAGE)->out(false);
580         $this->assertEquals($user2->id, $request['id']);
581         $this->assertEquals(fullname($user2), $request['fullname']);
582         $this->assertArrayHasKey('profileimageurl', $request);
583         $this->assertArrayHasKey('profileimageurlsmall', $request);
584         $this->assertArrayHasKey('isonline', $request);
585         $this->assertArrayHasKey('showonlinestatus', $request);
586         $this->assertArrayHasKey('isblocked', $request);
587         $this->assertArrayHasKey('iscontact', $request);
588     }
590     /**
591      * Test getting contact requests when there are none.
592      */
593     public function test_get_contact_requests_no_requests() {
594         $this->resetAfterTest();
596         $user1 = self::getDataGenerator()->create_user();
598         $this->setUser($user1);
600         $requests = core_message_external::get_contact_requests($user1->id);
601         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
603         $this->assertEmpty($requests);
604     }
606     /**
607      * Test getting contact requests with limits.
608      */
609     public function test_get_contact_requests_with_limits() {
610         $this->resetAfterTest();
612         $user1 = self::getDataGenerator()->create_user();
613         $user2 = self::getDataGenerator()->create_user();
614         $user3 = self::getDataGenerator()->create_user();
616         $this->setUser($user1);
618         \core_message\api::create_contact_request($user2->id, $user1->id);
619         \core_message\api::create_contact_request($user3->id, $user1->id);
621         $requests = core_message_external::get_contact_requests($user1->id, 0, 1);
622         $requests = external_api::clean_returnvalue(core_message_external::get_contact_requests_returns(), $requests);
624         $this->assertCount(1, $requests);
625     }
627     /**
628      * Test getting contact requests with messaging disabled.
629      */
630     public function test_get_contact_requests_messaging_disabled() {
631         global $CFG;
633         $this->resetAfterTest();
635         // Create some skeleton data just so we can call the WS.
636         $user1 = self::getDataGenerator()->create_user();
638         $this->setUser($user1);
640         // Disable messaging.
641         $CFG->messaging = 0;
643         // Ensure an exception is thrown.
644         $this->expectException('moodle_exception');
645         core_message_external::get_contact_requests($user1->id);
646     }
648     /**
649      * Test getting contact requests with no permission.
650      */
651     public function test_get_contact_requests_no_permission() {
652         $this->resetAfterTest();
654         // Create some skeleton data just so we can call the WS.
655         $user1 = self::getDataGenerator()->create_user();
656         $user2 = self::getDataGenerator()->create_user();
657         $user3 = self::getDataGenerator()->create_user();
659         $this->setUser($user3);
661         // Ensure an exception is thrown.
662         $this->expectException('required_capability_exception');
663         core_message_external::create_contact_request($user1->id, $user2->id);
664     }
666     /**
667      * Test creating a contact request.
668      */
669     public function test_create_contact_request() {
670         global $CFG, $DB;
672         $this->resetAfterTest();
674         $user1 = self::getDataGenerator()->create_user();
675         $user2 = self::getDataGenerator()->create_user();
677         $this->setUser($user1);
679         // Allow users to message anyone site-wide.
680         $CFG->messagingallusers = 1;
682         $return = core_message_external::create_contact_request($user1->id, $user2->id);
683         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
684         $this->assertEquals([], $return['warnings']);
686         $request = $DB->get_records('message_contact_requests');
688         $this->assertCount(1, $request);
690         $request = reset($request);
692         $this->assertEquals($request->id, $return['request']['id']);
693         $this->assertEquals($request->userid, $return['request']['userid']);
694         $this->assertEquals($request->requesteduserid, $return['request']['requesteduserid']);
695         $this->assertEquals($request->timecreated, $return['request']['timecreated']);
696     }
698     /**
699      * Test creating a contact request when not allowed.
700      */
701     public function test_create_contact_request_not_allowed() {
702         global $CFG;
704         $this->resetAfterTest();
706         $user1 = self::getDataGenerator()->create_user();
707         $user2 = self::getDataGenerator()->create_user();
709         $this->setUser($user1);
711         $CFG->messagingallusers = 0;
713         $return = core_message_external::create_contact_request($user1->id, $user2->id);
714         $return = external_api::clean_returnvalue(core_message_external::create_contact_request_returns(), $return);
716         $warning = reset($return['warnings']);
718         $this->assertEquals('user', $warning['item']);
719         $this->assertEquals($user2->id, $warning['itemid']);
720         $this->assertEquals('cannotcreatecontactrequest', $warning['warningcode']);
721         $this->assertEquals('You are unable to create a contact request for this user', $warning['message']);
722     }
724     /**
725      * Test creating a contact request with messaging disabled.
726      */
727     public function test_create_contact_request_messaging_disabled() {
728         global $CFG;
730         $this->resetAfterTest();
732         // Create some skeleton data just so we can call the WS.
733         $user1 = self::getDataGenerator()->create_user();
734         $user2 = self::getDataGenerator()->create_user();
736         $this->setUser($user1);
738         // Disable messaging.
739         $CFG->messaging = 0;
741         // Ensure an exception is thrown.
742         $this->expectException('moodle_exception');
743         core_message_external::create_contact_request($user1->id, $user2->id);
744     }
746     /**
747      * Test creating a contact request with no permission.
748      */
749     public function test_create_contact_request_no_permission() {
750         $this->resetAfterTest();
752         // Create some skeleton data just so we can call the WS.
753         $user1 = self::getDataGenerator()->create_user();
754         $user2 = self::getDataGenerator()->create_user();
755         $user3 = self::getDataGenerator()->create_user();
757         $this->setUser($user3);
759         // Ensure an exception is thrown.
760         $this->expectException('required_capability_exception');
761         core_message_external::create_contact_request($user1->id, $user2->id);
762     }
764     /**
765      * Test confirming a contact request.
766      */
767     public function test_confirm_contact_request() {
768         global $DB;
770         $this->resetAfterTest();
772         $user1 = self::getDataGenerator()->create_user();
773         $user2 = self::getDataGenerator()->create_user();
775         $this->setUser($user1);
777         \core_message\api::create_contact_request($user1->id, $user2->id);
779         $this->setUser($user2);
781         $return = core_message_external::confirm_contact_request($user1->id, $user2->id);
782         $return = external_api::clean_returnvalue(core_message_external::confirm_contact_request_returns(), $return);
783         $this->assertEquals(array(), $return);
785         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
787         $contact = $DB->get_records('message_contacts');
789         $this->assertCount(1, $contact);
791         $contact = reset($contact);
793         $this->assertEquals($user1->id, $contact->userid);
794         $this->assertEquals($user2->id, $contact->contactid);
795     }
797     /**
798      * Test confirming a contact request with messaging disabled.
799      */
800     public function test_confirm_contact_request_messaging_disabled() {
801         global $CFG;
803         $this->resetAfterTest();
805         // Create some skeleton data just so we can call the WS.
806         $user1 = self::getDataGenerator()->create_user();
807         $user2 = self::getDataGenerator()->create_user();
809         $this->setUser($user1);
811         // Disable messaging.
812         $CFG->messaging = 0;
814         // Ensure an exception is thrown.
815         $this->expectException('moodle_exception');
816         core_message_external::confirm_contact_request($user1->id, $user2->id);
817     }
819     /**
820      * Test confirming a contact request with no permission.
821      */
822     public function test_confirm_contact_request_no_permission() {
823         $this->resetAfterTest();
825         // Create some skeleton data just so we can call the WS.
826         $user1 = self::getDataGenerator()->create_user();
827         $user2 = self::getDataGenerator()->create_user();
828         $user3 = self::getDataGenerator()->create_user();
830         $this->setUser($user3);
832         // Ensure an exception is thrown.
833         $this->expectException('required_capability_exception');
834         core_message_external::confirm_contact_request($user1->id, $user2->id);
835     }
837     /**
838      * Test declining a contact request.
839      */
840     public function test_decline_contact_request() {
841         global $DB;
843         $this->resetAfterTest();
845         $user1 = self::getDataGenerator()->create_user();
846         $user2 = self::getDataGenerator()->create_user();
848         $this->setUser($user1);
850         \core_message\api::create_contact_request($user1->id, $user2->id);
852         $this->setUser($user2);
854         $return = core_message_external::decline_contact_request($user1->id, $user2->id);
855         $return = external_api::clean_returnvalue(core_message_external::decline_contact_request_returns(), $return);
856         $this->assertEquals(array(), $return);
858         $this->assertEquals(0, $DB->count_records('message_contact_requests'));
859         $this->assertEquals(0, $DB->count_records('message_contacts'));
860     }
862     /**
863      * Test declining a contact request with messaging disabled.
864      */
865     public function test_decline_contact_request_messaging_disabled() {
866         global $CFG;
868         $this->resetAfterTest();
870         // Create some skeleton data just so we can call the WS.
871         $user1 = self::getDataGenerator()->create_user();
872         $user2 = self::getDataGenerator()->create_user();
874         $this->setUser($user1);
876         // Disable messaging.
877         $CFG->messaging = 0;
879         // Ensure an exception is thrown.
880         $this->expectException('moodle_exception');
881         core_message_external::decline_contact_request($user1->id, $user2->id);
882     }
884     /**
885      * Test declining a contact request with no permission.
886      */
887     public function test_decline_contact_request_no_permission() {
888         $this->resetAfterTest();
890         // Create some skeleton data just so we can call the WS.
891         $user1 = self::getDataGenerator()->create_user();
892         $user2 = self::getDataGenerator()->create_user();
893         $user3 = self::getDataGenerator()->create_user();
895         $this->setUser($user3);
897         // Ensure an exception is thrown.
898         $this->expectException('required_capability_exception');
899         core_message_external::decline_contact_request($user1->id, $user2->id);
900     }
902     /**
903      * Test blocking a user.
904      */
905     public function test_block_user() {
906         global $DB;
908         $this->resetAfterTest(true);
910         $user1 = self::getDataGenerator()->create_user();
911         $user2 = self::getDataGenerator()->create_user();
913         $this->setUser($user1);
915         // Blocking a user.
916         $return = core_message_external::block_user($user1->id, $user2->id);
917         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
918         $this->assertEquals(array(), $return);
920         // Get list of blocked users.
921         $record = $DB->get_record('message_users_blocked', []);
923         $this->assertEquals($user1->id, $record->userid);
924         $this->assertEquals($user2->id, $record->blockeduserid);
926         // Blocking a user who is already blocked.
927         $return = core_message_external::block_user($user1->id, $user2->id);
928         $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
929         $this->assertEquals(array(), $return);
931         $this->assertEquals(1, $DB->count_records('message_users_blocked'));
932     }
934     /**
935      * Test blocking a user with messaging disabled.
936      */
937     public function test_block_user_messaging_disabled() {
938         global $CFG;
940         $this->resetAfterTest();
942         // Create some skeleton data just so we can call the WS.
943         $user1 = self::getDataGenerator()->create_user();
944         $user2 = self::getDataGenerator()->create_user();
946         $this->setUser($user1);
948         // Disable messaging.
949         $CFG->messaging = 0;
951         // Ensure an exception is thrown.
952         $this->expectException('moodle_exception');
953         core_message_external::block_user($user1->id, $user2->id);
954     }
956     /**
957      * Test blocking a user with no permission.
958      */
959     public function test_block_user_no_permission() {
960         $this->resetAfterTest();
962         // Create some skeleton data just so we can call the WS.
963         $user1 = self::getDataGenerator()->create_user();
964         $user2 = self::getDataGenerator()->create_user();
965         $user3 = self::getDataGenerator()->create_user();
967         $this->setUser($user3);
969         // Ensure an exception is thrown.
970         $this->expectException('required_capability_exception');
971         core_message_external::block_user($user1->id, $user2->id);
972     }
974     /**
975      * Test unblocking a user.
976      */
977     public function test_unblock_user() {
978         global $DB;
980         $this->resetAfterTest(true);
982         $user1 = self::getDataGenerator()->create_user();
983         $user2 = self::getDataGenerator()->create_user();
985         $this->setUser($user1);
987         // Block the user.
988         \core_message\api::block_user($user1->id, $user2->id);
990         // Unblocking a user.
991         $return = core_message_external::unblock_user($user1->id, $user2->id);
992         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
993         $this->assertEquals(array(), $return);
995         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
997         // Unblocking a user who is already unblocked.
998         $return = core_message_external::unblock_user($user1->id, $user2->id);
999         $return = external_api::clean_returnvalue(core_message_external::unblock_user_returns(), $return);
1000         $this->assertEquals(array(), $return);
1002         $this->assertEquals(0, $DB->count_records('message_users_blocked'));
1003     }
1005     /**
1006      * Test unblocking a user with messaging disabled.
1007      */
1008     public function test_unblock_user_messaging_disabled() {
1009         global $CFG;
1011         $this->resetAfterTest();
1013         // Create some skeleton data just so we can call the WS.
1014         $user1 = self::getDataGenerator()->create_user();
1015         $user2 = self::getDataGenerator()->create_user();
1017         $this->setUser($user1);
1019         // Disable messaging.
1020         $CFG->messaging = 0;
1022         // Ensure an exception is thrown.
1023         $this->expectException('moodle_exception');
1024         core_message_external::unblock_user($user1->id, $user2->id);
1025     }
1027     /**
1028      * Test unblocking a user with no permission.
1029      */
1030     public function test_unblock_user_no_permission() {
1031         $this->resetAfterTest();
1033         // Create some skeleton data just so we can call the WS.
1034         $user1 = self::getDataGenerator()->create_user();
1035         $user2 = self::getDataGenerator()->create_user();
1036         $user3 = self::getDataGenerator()->create_user();
1038         $this->setUser($user3);
1040         // Ensure an exception is thrown.
1041         $this->expectException('required_capability_exception');
1042         core_message_external::unblock_user($user1->id, $user2->id);
1043     }
1045     /**
1046      * Test get_contacts.
1047      */
1048     public function test_get_contacts() {
1049         $this->resetAfterTest(true);
1051         $user1 = self::getDataGenerator()->create_user();
1052         $user_stranger = self::getDataGenerator()->create_user();
1053         $user_offline1 = self::getDataGenerator()->create_user();
1054         $user_offline2 = self::getDataGenerator()->create_user();
1055         $user_offline3 = self::getDataGenerator()->create_user();
1056         $user_online = new stdClass();
1057         $user_online->lastaccess = time();
1058         $user_online = self::getDataGenerator()->create_user($user_online);
1059         $user_blocked = self::getDataGenerator()->create_user();
1060         $noreplyuser = core_user::get_user(core_user::NOREPLY_USER);
1062         // Login as user1.
1063         $this->setUser($user1);
1064         \core_message\api::add_contact($user1->id, $user_offline1->id);
1065         \core_message\api::add_contact($user1->id, $user_offline2->id);
1066         \core_message\api::add_contact($user1->id, $user_offline3->id);
1067         \core_message\api::add_contact($user1->id, $user_online->id);
1069         // User_stranger sends a couple of messages to user1.
1070         $this->send_message($user_stranger, $user1, 'Hello there!');
1071         $this->send_message($user_stranger, $user1, 'How you goin?');
1072         $this->send_message($user_stranger, $user1, 'Cya!');
1073         $this->send_message($noreplyuser, $user1, 'I am not a real user');
1075         // User_blocked sends a message to user1.
1076         $this->send_message($user_blocked, $user1, 'Here, have some spam.');
1078         // Retrieve the contacts of the user.
1079         $this->setUser($user1);
1080         $contacts = core_message_external::get_contacts();
1081         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1082         $this->assertCount(3, $contacts['offline']);
1083         $this->assertCount(1, $contacts['online']);
1084         $this->assertCount(3, $contacts['strangers']);
1085         core_message_external::block_contacts(array($user_blocked->id));
1086         $this->assertDebuggingCalled();
1087         $contacts = core_message_external::get_contacts();
1088         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1089         $this->assertCount(3, $contacts['offline']);
1090         $this->assertCount(1, $contacts['online']);
1091         $this->assertCount(2, $contacts['strangers']);
1093         // Checking some of the fields returned.
1094         $stranger = array_pop($contacts['strangers']);
1096         $this->assertEquals(core_user::NOREPLY_USER, $stranger['id']);
1097         $this->assertEquals(1, $stranger['unread']);
1099         // Check that deleted users are not returned.
1100         delete_user($user_offline1);
1101         delete_user($user_stranger);
1102         delete_user($user_online);
1103         $contacts = core_message_external::get_contacts();
1104         $contacts = external_api::clean_returnvalue(core_message_external::get_contacts_returns(), $contacts);
1105         $this->assertCount(2, $contacts['offline']);
1106         $this->assertCount(0, $contacts['online']);
1107         $this->assertCount(1, $contacts['strangers']);
1108     }
1110     /**
1111      * Test search_contacts.
1112      * @expectedException moodle_exception
1113      */
1114     public function test_search_contacts() {
1115         global $DB;
1116         $this->resetAfterTest(true);
1118         $course1 = $this->getDataGenerator()->create_course();
1119         $course2 = $this->getDataGenerator()->create_course();
1121         $user1 = new stdClass();
1122         $user1->firstname = 'X';
1123         $user1->lastname = 'X';
1124         $user1 = $this->getDataGenerator()->create_user($user1);
1125         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1126         $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1128         $user2 = new stdClass();
1129         $user2->firstname = 'Eric';
1130         $user2->lastname = 'Cartman';
1131         $user2 = self::getDataGenerator()->create_user($user2);
1132         $user3 = new stdClass();
1133         $user3->firstname = 'Stan';
1134         $user3->lastname = 'Marsh';
1135         $user3 = self::getDataGenerator()->create_user($user3);
1136         self::getDataGenerator()->enrol_user($user3->id, $course1->id);
1137         $user4 = new stdClass();
1138         $user4->firstname = 'Kyle';
1139         $user4->lastname = 'Broflovski';
1140         $user4 = self::getDataGenerator()->create_user($user4);
1141         $user5 = new stdClass();
1142         $user5->firstname = 'Kenny';
1143         $user5->lastname = 'McCormick';
1144         $user5 = self::getDataGenerator()->create_user($user5);
1145         self::getDataGenerator()->enrol_user($user5->id, $course2->id);
1147         $this->setUser($user1);
1149         $results = core_message_external::search_contacts('r');
1150         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1151         $this->assertCount(5, $results); // Users 2 through 5 + admin
1153         $results = core_message_external::search_contacts('r', true);
1154         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1155         $this->assertCount(2, $results);
1157         $results = core_message_external::search_contacts('Kyle', false);
1158         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1159         $this->assertCount(1, $results);
1160         $result = reset($results);
1161         $this->assertEquals($user4->id, $result['id']);
1163         $results = core_message_external::search_contacts('y', false);
1164         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1165         $this->assertCount(2, $results);
1167         $results = core_message_external::search_contacts('y', true);
1168         $results = external_api::clean_returnvalue(core_message_external::search_contacts_returns(), $results);
1169         $this->assertCount(1, $results);
1170         $result = reset($results);
1171         $this->assertEquals($user5->id, $result['id']);
1173         // Empty query, will throw an exception.
1174         $results = core_message_external::search_contacts('');
1175     }
1177     /**
1178      * Test get_messages.
1179      */
1180     public function test_get_messages() {
1181         global $CFG, $DB;
1182         $this->resetAfterTest(true);
1184         $this->preventResetByRollback();
1185         // This mark the messages as read!.
1186         $sink = $this->redirectMessages();
1188         $user1 = self::getDataGenerator()->create_user();
1189         $user2 = self::getDataGenerator()->create_user();
1190         $user3 = self::getDataGenerator()->create_user();
1192         $course = self::getDataGenerator()->create_course();
1194         // Send a message from one user to another.
1195         message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1196         message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE);
1197         message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1198         message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1199         message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE);
1201         $this->setUser($user1);
1202         // Get read conversations from user1 to user2.
1203         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1204         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1205         $this->assertCount(1, $messages['messages']);
1207         // Delete the message.
1208         $message = array_shift($messages['messages']);
1209         \core_message\api::delete_message($user1->id, $message['id']);
1211         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0);
1212         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1213         $this->assertCount(0, $messages['messages']);
1215         // Get unread conversations from user1 to user2.
1216         $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0);
1217         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1218         $this->assertCount(0, $messages['messages']);
1220         // Get read messages send from user1.
1221         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1222         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1223         $this->assertCount(1, $messages['messages']);
1225         $this->setUser($user2);
1226         // Get read conversations from any user to user2.
1227         $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0);
1228         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1229         $this->assertCount(2, $messages['messages']);
1231         // Conversations from user3 to user2.
1232         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1233         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1234         $this->assertCount(1, $messages['messages']);
1236         // Delete the message.
1237         $message = array_shift($messages['messages']);
1238         \core_message\api::delete_message($user2->id, $message['id']);
1240         $messages = core_message_external::get_messages($user2->id, $user3->id, 'conversations', true, true, 0, 0);
1241         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1242         $this->assertCount(0, $messages['messages']);
1244         $this->setUser($user3);
1245         // Get read notifications received by user3.
1246         $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0);
1247         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1248         $this->assertCount(0, $messages['messages']);
1250         // Now, create some notifications...
1251         // We are creating fake notifications but based on real ones.
1253         // This one comes from a disabled plugin's provider and therefore is not sent.
1254         $eventdata = new \core\message\message();
1255         $eventdata->courseid          = $course->id;
1256         $eventdata->notification      = 1;
1257         $eventdata->modulename        = 'moodle';
1258         $eventdata->component         = 'enrol_paypal';
1259         $eventdata->name              = 'paypal_enrolment';
1260         $eventdata->userfrom          = get_admin();
1261         $eventdata->userto            = $user1;
1262         $eventdata->subject           = "Moodle: PayPal payment";
1263         $eventdata->fullmessage       = "Your PayPal payment is pending.";
1264         $eventdata->fullmessageformat = FORMAT_PLAIN;
1265         $eventdata->fullmessagehtml   = '';
1266         $eventdata->smallmessage      = '';
1267         message_send($eventdata);
1268         $this->assertDebuggingCalled('Attempt to send msg from a provider enrol_paypal/paypal_enrolment '.
1269             'that is inactive or not allowed for the user id='.$user1->id);
1271         // This one omits notification = 1.
1272         $message = new \core\message\message();
1273         $message->courseid          = $course->id;
1274         $message->component         = 'enrol_manual';
1275         $message->name              = 'expiry_notification';
1276         $message->userfrom          = $user2;
1277         $message->userto            = $user1;
1278         $message->subject           = 'Test: This is not a notification but otherwise is valid';
1279         $message->fullmessage       = 'Test: Full message';
1280         $message->fullmessageformat = FORMAT_MARKDOWN;
1281         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1282         $message->smallmessage      = $message->subject;
1283         $message->contexturlname    = $course->fullname;
1284         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1285         message_send($message);
1287         $message = new \core\message\message();
1288         $message->courseid          = $course->id;
1289         $message->notification      = 1;
1290         $message->component         = 'enrol_manual';
1291         $message->name              = 'expiry_notification';
1292         $message->userfrom          = $user2;
1293         $message->userto            = $user1;
1294         $message->subject           = 'Enrolment expired';
1295         $message->fullmessage       = 'Enrolment expired blah blah blah';
1296         $message->fullmessageformat = FORMAT_MARKDOWN;
1297         $message->fullmessagehtml   = markdown_to_html($message->fullmessage);
1298         $message->smallmessage      = $message->subject;
1299         $message->contexturlname    = $course->fullname;
1300         $message->contexturl        = (string)new moodle_url('/course/view.php', array('id' => $course->id));
1301         message_send($message);
1303         $userfrom = core_user::get_noreply_user();
1304         $userfrom->maildisplay = true;
1305         $eventdata = new \core\message\message();
1306         $eventdata->courseid          = $course->id;
1307         $eventdata->component         = 'moodle';
1308         $eventdata->name              = 'badgecreatornotice';
1309         $eventdata->userfrom          = $userfrom;
1310         $eventdata->userto            = $user1;
1311         $eventdata->notification      = 1;
1312         $eventdata->subject           = 'New badge';
1313         $eventdata->fullmessage       = format_text_email($eventdata->subject, FORMAT_HTML);
1314         $eventdata->fullmessageformat = FORMAT_PLAIN;
1315         $eventdata->fullmessagehtml   = $eventdata->subject;
1316         $eventdata->smallmessage      = $eventdata->subject;
1317         message_send($eventdata);
1319         $eventdata = new \core\message\message();
1320         $eventdata->courseid         = $course->id;
1321         $eventdata->name             = 'submission';
1322         $eventdata->component        = 'mod_feedback';
1323         $eventdata->userfrom         = $user1;
1324         $eventdata->userto           = $user2;
1325         $eventdata->subject          = 'Feedback submitted';
1326         $eventdata->fullmessage      = 'Feedback submitted from an user';
1327         $eventdata->fullmessageformat = FORMAT_PLAIN;
1328         $eventdata->fullmessagehtml  = '<strong>Feedback submitted</strong>';
1329         $eventdata->smallmessage     = '';
1330         message_send($eventdata);
1332         $this->setUser($user1);
1333         // Get read notifications from any user to user1.
1334         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0);
1335         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1336         $this->assertCount(3, $messages['messages']);
1338         // Get one read notifications from any user to user1.
1339         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1);
1340         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1341         $this->assertCount(1, $messages['messages']);
1343         // Get unread notifications from any user to user1.
1344         $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0);
1345         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1346         $this->assertCount(0, $messages['messages']);
1348         // Get read both type of messages from any user to user1.
1349         $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0);
1350         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1351         $this->assertCount(4, $messages['messages']);
1353         // Get read notifications from no-reply-user to user1.
1354         $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0);
1355         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1356         $this->assertCount(1, $messages['messages']);
1358         // Get notifications send by user1 to any user.
1359         $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0);
1360         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1361         $this->assertCount(1, $messages['messages']);
1363         // Test warnings.
1364         $CFG->messaging = 0;
1366         $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0);
1367         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1368         $this->assertCount(1, $messages['warnings']);
1370         // Test exceptions.
1372         // Messaging disabled.
1373         try {
1374             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1375             $this->fail('Exception expected due messaging disabled.');
1376         } catch (moodle_exception $e) {
1377             $this->assertEquals('disabled', $e->errorcode);
1378         }
1380         $CFG->messaging = 1;
1382         // Invalid users.
1383         try {
1384             $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0);
1385             $this->fail('Exception expected due invalid users.');
1386         } catch (moodle_exception $e) {
1387             $this->assertEquals('accessdenied', $e->errorcode);
1388         }
1390         // Invalid user ids.
1391         try {
1392             $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0);
1393             $this->fail('Exception expected due invalid users.');
1394         } catch (moodle_exception $e) {
1395             $this->assertEquals('invaliduser', $e->errorcode);
1396         }
1398         // Invalid users (permissions).
1399         $this->setUser($user2);
1400         try {
1401             $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0);
1402             $this->fail('Exception expected due invalid user.');
1403         } catch (moodle_exception $e) {
1404             $this->assertEquals('accessdenied', $e->errorcode);
1405         }
1407     }
1409     /**
1410      * Test get_messages where we want all messages from a user, sent to any user.
1411      */
1412     public function test_get_messages_useridto_all() {
1413         $this->resetAfterTest(true);
1415         $user1 = self::getDataGenerator()->create_user();
1416         $user2 = self::getDataGenerator()->create_user();
1417         $user3 = self::getDataGenerator()->create_user();
1419         $this->setUser($user1);
1421         // Send a message from user 1 to two other users.
1422         $this->send_message($user1, $user2, 'some random text 1', 0, 1);
1423         $this->send_message($user1, $user3, 'some random text 2', 0, 2);
1425         // Get messages sent from user 1.
1426         $messages = core_message_external::get_messages(0, $user1->id, 'conversations', false, false, 0, 0);
1427         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1429         // Confirm the data is correct.
1430         $messages = $messages['messages'];
1431         $this->assertCount(2, $messages);
1433         $message1 = array_shift($messages);
1434         $message2 = array_shift($messages);
1436         $this->assertEquals($user1->id, $message1['useridfrom']);
1437         $this->assertEquals($user2->id, $message1['useridto']);
1439         $this->assertEquals($user1->id, $message2['useridfrom']);
1440         $this->assertEquals($user3->id, $message2['useridto']);
1441     }
1443     /**
1444      * Test get_messages where we want all messages to a user, sent by any user.
1445      */
1446     public function test_get_messages_useridfrom_all() {
1447         $this->resetAfterTest();
1449         $user1 = self::getDataGenerator()->create_user();
1450         $user2 = self::getDataGenerator()->create_user();
1451         $user3 = self::getDataGenerator()->create_user();
1453         $this->setUser($user1);
1455         // Send a message to user 1 from two other users.
1456         $this->send_message($user2, $user1, 'some random text 1', 0, 1);
1457         $this->send_message($user3, $user1, 'some random text 2', 0, 2);
1459         // Get messages sent to user 1.
1460         $messages = core_message_external::get_messages($user1->id, 0, 'conversations', false, false, 0, 0);
1461         $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
1463         // Confirm the data is correct.
1464         $messages = $messages['messages'];
1465         $this->assertCount(2, $messages);
1467         $message1 = array_shift($messages);
1468         $message2 = array_shift($messages);
1470         $this->assertEquals($user2->id, $message1['useridfrom']);
1471         $this->assertEquals($user1->id, $message1['useridto']);
1473         $this->assertEquals($user3->id, $message2['useridfrom']);
1474         $this->assertEquals($user1->id, $message2['useridto']);
1475     }
1477     /**
1478      * Test get_blocked_users.
1479      */
1480     public function test_get_blocked_users() {
1481         $this->resetAfterTest(true);
1483         $user1 = self::getDataGenerator()->create_user();
1484         $userstranger = self::getDataGenerator()->create_user();
1485         $useroffline1 = self::getDataGenerator()->create_user();
1486         $useroffline2 = self::getDataGenerator()->create_user();
1487         $userblocked = self::getDataGenerator()->create_user();
1489         // Login as user1.
1490         $this->setUser($user1);
1492         \core_message\api::add_contact($user1->id, $useroffline1->id);
1493         \core_message\api::add_contact($user1->id, $useroffline2->id);
1495         // The userstranger sends a couple of messages to user1.
1496         $this->send_message($userstranger, $user1, 'Hello there!');
1497         $this->send_message($userstranger, $user1, 'How you goin?');
1499         // The userblocked sends a message to user1.
1500         // Note that this user is not blocked at this point.
1501         $this->send_message($userblocked, $user1, 'Here, have some spam.');
1503         // Retrieve the list of blocked users.
1504         $this->setUser($user1);
1505         $blockedusers = core_message_external::get_blocked_users($user1->id);
1506         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1507         $this->assertCount(0, $blockedusers['users']);
1509         // Block the $userblocked and retrieve again the list.
1510         core_message_external::block_contacts(array($userblocked->id));
1511         $this->assertDebuggingCalled();
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(1, $blockedusers['users']);
1516         // Remove the $userblocked and check that the list now is empty.
1517         delete_user($userblocked);
1518         $blockedusers = core_message_external::get_blocked_users($user1->id);
1519         $blockedusers = external_api::clean_returnvalue(core_message_external::get_blocked_users_returns(), $blockedusers);
1520         $this->assertCount(0, $blockedusers['users']);
1521     }
1523     /**
1524      * Test mark_message_read.
1525      */
1526     public function test_mark_message_read() {
1527         $this->resetAfterTest(true);
1529         $user1 = self::getDataGenerator()->create_user();
1530         $user2 = self::getDataGenerator()->create_user();
1531         $user3 = self::getDataGenerator()->create_user();
1533         // Login as user1.
1534         $this->setUser($user1);
1535         \core_message\api::add_contact($user1->id, $user2->id);
1536         \core_message\api::add_contact($user1->id, $user3->id);
1538         // The user2 sends a couple of messages to user1.
1539         $this->send_message($user2, $user1, 'Hello there!');
1540         $this->send_message($user2, $user1, 'How you goin?');
1541         $this->send_message($user3, $user1, 'How you goin?');
1542         $this->send_message($user3, $user2, 'How you goin?');
1544         // Retrieve all messages sent by user2 (they are currently unread).
1545         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1547         $messageids = array();
1548         foreach ($lastmessages as $m) {
1549             $messageid = core_message_external::mark_message_read($m->id, time());
1550             $messageids[] = external_api::clean_returnvalue(core_message_external::mark_message_read_returns(), $messageid);
1551         }
1553         // Retrieve all messages sent (they are currently read).
1554         $lastmessages = message_get_messages($user1->id, $user2->id, 0, true);
1555         $this->assertCount(2, $lastmessages);
1556         $this->assertArrayHasKey($messageids[0]['messageid'], $lastmessages);
1557         $this->assertArrayHasKey($messageids[1]['messageid'], $lastmessages);
1559         // Retrieve all messages sent by any user (that are currently unread).
1560         $lastmessages = message_get_messages($user1->id, 0, 0, false);
1561         $this->assertCount(1, $lastmessages);
1563         // Invalid message ids.
1564         try {
1565             $messageid = core_message_external::mark_message_read(1337, time());
1566             $this->fail('Exception expected due invalid messageid.');
1567         } catch (dml_missing_record_exception $e) {
1568             $this->assertEquals('invalidrecordunknown', $e->errorcode);
1569         }
1571         // A message to a different user.
1572         $lastmessages = message_get_messages($user2->id, $user3->id, 0, false);
1573         $messageid = array_pop($lastmessages)->id;
1574         try {
1575             $messageid = core_message_external::mark_message_read($messageid, time());
1576             $this->fail('Exception expected due invalid messageid.');
1577         } catch (invalid_parameter_exception $e) {
1578             $this->assertEquals('invalidparameter', $e->errorcode);
1579         }
1580     }
1582     /**
1583      * Test mark_notification_read.
1584      */
1585     public function test_mark_notification_read() {
1586         $this->resetAfterTest(true);
1588         $user1 = self::getDataGenerator()->create_user();
1589         $user2 = self::getDataGenerator()->create_user();
1590         $user3 = self::getDataGenerator()->create_user();
1592         // Login as user1.
1593         $this->setUser($user1);
1594         \core_message\api::add_contact($user1->id, $user2->id);
1595         \core_message\api::add_contact($user1->id, $user3->id);
1597         // The user2 sends a couple of notifications to user1.
1598         $this->send_message($user2, $user1, 'Hello there!', 1);
1599         $this->send_message($user2, $user1, 'How you goin?', 1);
1600         $this->send_message($user3, $user1, 'How you goin?', 1);
1601         $this->send_message($user3, $user2, 'How you goin?', 1);
1603         // Retrieve all notifications sent by user2 (they are currently unread).
1604         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, false);
1606         $notificationids = array();
1607         foreach ($lastnotifications as $n) {
1608             $notificationid = core_message_external::mark_notification_read($n->id, time());
1609             $notificationids[] = external_api::clean_returnvalue(core_message_external::mark_notification_read_returns(),
1610                 $notificationid);
1611         }
1613         // Retrieve all notifications sent (they are currently read).
1614         $lastnotifications = message_get_messages($user1->id, $user2->id, 1, true);
1615         $this->assertCount(2, $lastnotifications);
1616         $this->assertArrayHasKey($notificationids[1]['notificationid'], $lastnotifications);
1617         $this->assertArrayHasKey($notificationids[0]['notificationid'], $lastnotifications);
1619         // Retrieve all notifications sent by any user (that are currently unread).
1620         $lastnotifications = message_get_messages($user1->id, 0, 1, false);
1621         $this->assertCount(1, $lastnotifications);
1623         // Invalid notification ids.
1624         try {
1625             $notificationid = core_message_external::mark_notification_read(1337, time());
1626             $this->fail('Exception expected due invalid notificationid.');
1627         } catch (dml_missing_record_exception $e) {
1628             $this->assertEquals('invalidrecord', $e->errorcode);
1629         }
1631         // A notification to a different user.
1632         $lastnotifications = message_get_messages($user2->id, $user3->id, 1, false);
1633         $notificationid = array_pop($lastnotifications)->id;
1634         try {
1635             $notificationid = core_message_external::mark_notification_read($notificationid, time());
1636             $this->fail('Exception expected due invalid notificationid.');
1637         } catch (invalid_parameter_exception $e) {
1638             $this->assertEquals('invalidparameter', $e->errorcode);
1639         }
1640     }
1642     /**
1643      * Test delete_message.
1644      */
1645     public function test_delete_message() {
1646         global $DB;
1647         $this->resetAfterTest(true);
1649         $user1 = self::getDataGenerator()->create_user();
1650         $user2 = self::getDataGenerator()->create_user();
1651         $user3 = self::getDataGenerator()->create_user();
1652         $user4 = self::getDataGenerator()->create_user();
1654         // Login as user1.
1655         $this->setUser($user1);
1656         \core_message\api::add_contact($user1->id, $user2->id);
1657         \core_message\api::add_contact($user1->id, $user3->id);
1659         // User user1 does not interchange messages with user3.
1660         $m1to2 = message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE);
1661         $m2to3 = message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE);
1662         $m3to2 = message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE);
1663         $m3to4 = message_post_message($user3, $user4, 'some random text 4', FORMAT_MOODLE);
1665         // Retrieve all messages sent by user2 (they are currently unread).
1666         $lastmessages = message_get_messages($user1->id, $user2->id, 0, false);
1668         // Delete a message not read, as a user from.
1669         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1670         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1671         $this->assertTrue($result['status']);
1672         $this->assertCount(0, $result['warnings']);
1673         $mua = $DB->get_record('message_user_actions', array('messageid' => $m1to2, 'userid' => $user1->id));
1674         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua->action);
1676         // Try to delete the same message again.
1677         $result = core_message_external::delete_message($m1to2, $user1->id, false);
1678         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1679         $this->assertFalse($result['status']);
1681         // Try to delete a message that does not belong to me.
1682         try {
1683             $messageid = core_message_external::delete_message($m2to3, $user3->id, false);
1684             $this->fail('Exception expected due invalid messageid.');
1685         } catch (moodle_exception $e) {
1686             $this->assertEquals('You do not have permission to delete this message', $e->errorcode);
1687         }
1689         $this->setUser($user3);
1690         // Delete a message not read, as a user to.
1691         $result = core_message_external::delete_message($m2to3, $user3->id, false);
1692         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1693         $this->assertTrue($result['status']);
1694         $this->assertCount(0, $result['warnings']);
1695         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m2to3, 'userid' => $user3->id,
1696             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1698         // Delete a message read.
1699         $message = $DB->get_record('messages', ['id' => $m3to2]);
1700         \core_message\api::mark_message_as_read($user3->id, $message, time());
1701         $result = core_message_external::delete_message($m3to2, $user3->id);
1702         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1703         $this->assertTrue($result['status']);
1704         $this->assertCount(0, $result['warnings']);
1705         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to2, 'userid' => $user3->id,
1706             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1708         // Invalid message ids.
1709         try {
1710             $result = core_message_external::delete_message(-1, $user1->id);
1711             $this->fail('Exception expected due invalid messageid.');
1712         } catch (dml_missing_record_exception $e) {
1713             $this->assertEquals('invalidrecord', $e->errorcode);
1714         }
1716         // Invalid user.
1717         try {
1718             $result = core_message_external::delete_message($m1to2, -1, false);
1719             $this->fail('Exception expected due invalid user.');
1720         } catch (moodle_exception $e) {
1721             $this->assertEquals('invaliduser', $e->errorcode);
1722         }
1724         // Not active user.
1725         delete_user($user2);
1726         try {
1727             $result = core_message_external::delete_message($m1to2, $user2->id, false);
1728             $this->fail('Exception expected due invalid user.');
1729         } catch (moodle_exception $e) {
1730             $this->assertEquals('userdeleted', $e->errorcode);
1731         }
1733         // Now, as an admin, try to delete any message.
1734         $this->setAdminUser();
1735         $result = core_message_external::delete_message($m3to4, $user4->id, false);
1736         $result = external_api::clean_returnvalue(core_message_external::delete_message_returns(), $result);
1737         $this->assertTrue($result['status']);
1738         $this->assertCount(0, $result['warnings']);
1739         $this->assertTrue($DB->record_exists('message_user_actions', array('messageid' => $m3to4, 'userid' => $user4->id,
1740             'action' => \core_message\api::MESSAGE_ACTION_DELETED)));
1742     }
1744     public function test_mark_all_notifications_as_read_invalid_user_exception() {
1745         $this->resetAfterTest(true);
1747         $this->expectException('moodle_exception');
1748         core_message_external::mark_all_notifications_as_read(-2132131, 0);
1749     }
1751     public function test_mark_all_notifications_as_read_access_denied_exception() {
1752         $this->resetAfterTest(true);
1754         $sender = $this->getDataGenerator()->create_user();
1755         $user = $this->getDataGenerator()->create_user();
1757         $this->setUser($user);
1758         $this->expectException('moodle_exception');
1759         core_message_external::mark_all_notifications_as_read($sender->id, 0);
1760     }
1762     public function test_mark_all_notifications_as_read_missing_from_user_exception() {
1763         $this->resetAfterTest(true);
1765         $sender = $this->getDataGenerator()->create_user();
1767         $this->setUser($sender);
1768         $this->expectException('moodle_exception');
1769         core_message_external::mark_all_notifications_as_read($sender->id, 99999);
1770     }
1772     public function test_mark_all_notifications_as_read() {
1773         global $DB;
1775         $this->resetAfterTest(true);
1777         $sender1 = $this->getDataGenerator()->create_user();
1778         $sender2 = $this->getDataGenerator()->create_user();
1779         $sender3 = $this->getDataGenerator()->create_user();
1780         $recipient = $this->getDataGenerator()->create_user();
1782         $this->setUser($recipient);
1784         $this->send_message($sender1, $recipient, 'Notification', 1);
1785         $this->send_message($sender1, $recipient, 'Notification', 1);
1786         $this->send_message($sender2, $recipient, 'Notification', 1);
1787         $this->send_message($sender2, $recipient, 'Notification', 1);
1788         $this->send_message($sender3, $recipient, 'Notification', 1);
1789         $this->send_message($sender3, $recipient, 'Notification', 1);
1791         core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id);
1792         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1793         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1795         $this->assertCount(2, $readnotifications);
1796         $this->assertCount(4, $unreadnotifications);
1798         core_message_external::mark_all_notifications_as_read($recipient->id, 0);
1799         $readnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NOT NULL', [$recipient->id]);
1800         $unreadnotifications = $DB->get_records_select('notifications', 'useridto = ? AND timeread IS NULL', [$recipient->id]);
1802         $this->assertCount(6, $readnotifications);
1803         $this->assertCount(0, $unreadnotifications);
1804     }
1806     /**
1807      * Test get_user_notification_preferences
1808      */
1809     public function test_get_user_notification_preferences() {
1810         $this->resetAfterTest(true);
1812         $user = self::getDataGenerator()->create_user();
1813         $this->setUser($user);
1815         // Set a couple of preferences to test.
1816         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
1817         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
1819         $prefs = core_message_external::get_user_notification_preferences();
1820         $prefs = external_api::clean_returnvalue(core_message_external::get_user_notification_preferences_returns(), $prefs);
1821         // Check processors.
1822         $this->assertGreaterThanOrEqual(2, count($prefs['preferences']['processors']));
1823         $this->assertEquals($user->id, $prefs['preferences']['userid']);
1825         // Check components.
1826         $this->assertGreaterThanOrEqual(8, count($prefs['preferences']['components']));
1828         // Check some preferences that we previously set.
1829         $found = 0;
1830         foreach ($prefs['preferences']['components'] as $component) {
1831             foreach ($component['notifications'] as $prefdata) {
1832                 if ($prefdata['preferencekey'] != 'message_provider_mod_assign_assign_notification') {
1833                     continue;
1834                 }
1835                 foreach ($prefdata['processors'] as $processor) {
1836                     if ($processor['name'] == 'popup') {
1837                         $this->assertTrue($processor['loggedin']['checked']);
1838                         $found++;
1839                     } else if ($processor['name'] == 'email') {
1840                         $this->assertTrue($processor['loggedoff']['checked']);
1841                         $found++;
1842                     }
1843                 }
1844             }
1845         }
1846         $this->assertEquals(2, $found);
1847     }
1849     /**
1850      * Test get_user_notification_preferences permissions
1851      */
1852     public function test_get_user_notification_preferences_permissions() {
1853         $this->resetAfterTest(true);
1855         $user = self::getDataGenerator()->create_user();
1856         $otheruser = self::getDataGenerator()->create_user();
1857         $this->setUser($user);
1859         $this->expectException('moodle_exception');
1860         $prefs = core_message_external::get_user_notification_preferences($otheruser->id);
1861     }
1863     /**
1864      * Tests searching users in a course.
1865      */
1866     public function test_data_for_messagearea_search_users_in_course() {
1867         $this->resetAfterTest(true);
1869         // Create some users.
1870         $user1 = new stdClass();
1871         $user1->firstname = 'User';
1872         $user1->lastname = 'One';
1873         $user1 = self::getDataGenerator()->create_user($user1);
1875         // The person doing the search.
1876         $this->setUser($user1);
1878         // Set the second user's status to online by setting their last access to now.
1879         $user2 = new stdClass();
1880         $user2->firstname = 'User';
1881         $user2->lastname = 'Two';
1882         $user2->lastaccess = time();
1883         $user2 = self::getDataGenerator()->create_user($user2);
1885         // Block the second user.
1886         \core_message\api::block_user($user1->id, $user2->id);
1888         $user3 = new stdClass();
1889         $user3->firstname = 'User';
1890         $user3->lastname = 'Three';
1891         $user3 = self::getDataGenerator()->create_user($user3);
1893         // Create a course.
1894         $course1 = new stdClass();
1895         $course1->fullname = 'Course';
1896         $course1->shortname = 'One';
1897         $course1 = $this->getDataGenerator()->create_course();
1899         // Enrol the user we are doing the search for and one user in the course.
1900         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1901         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1903         // Perform a search.
1904         $result = core_message_external::data_for_messagearea_search_users_in_course($user1->id, $course1->id, 'User');
1906         // We need to execute the return values cleaning process to simulate the web service.
1907         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_in_course_returns(),
1908             $result);
1910         // Check that we only retrieved a user that was enrolled, and that the user performing the search was not returned.
1911         $users = $result['contacts'];
1912         $this->assertCount(1, $users);
1914         $user = $users[0];
1915         $this->assertEquals($user2->id, $user['userid']);
1916         $this->assertEquals(fullname($user2), $user['fullname']);
1917         $this->assertFalse($user['ismessaging']);
1918         $this->assertFalse($user['sentfromcurrentuser']);
1919         $this->assertNull($user['lastmessage']);
1920         $this->assertNull($user['messageid']);
1921         $this->assertNull($user['isonline']);
1922         $this->assertFalse($user['isread']);
1923         $this->assertTrue($user['isblocked']);
1924         $this->assertNull($user['unreadcount']);
1925     }
1927     /**
1928      * Tests searching users in course as another user.
1929      */
1930     public function test_data_for_messagearea_search_users_in_course_as_other_user() {
1931         $this->resetAfterTest(true);
1933         // The person doing the search for another user.
1934         $this->setAdminUser();
1936         // Create some users.
1937         $user1 = new stdClass();
1938         $user1->firstname = 'User';
1939         $user1->lastname = 'One';
1940         $user1 = self::getDataGenerator()->create_user($user1);
1942         $user2 = new stdClass();
1943         $user2->firstname = 'User';
1944         $user2->lastname = 'Two';
1945         $user2 = self::getDataGenerator()->create_user($user2);
1947         $user3 = new stdClass();
1948         $user3->firstname = 'User';
1949         $user3->lastname = 'Three';
1950         $user3 = self::getDataGenerator()->create_user($user3);
1952         // Create a course.
1953         $course1 = new stdClass();
1954         $course1->fullname = 'Course';
1955         $course1->shortname = 'One';
1956         $course1 = $this->getDataGenerator()->create_course();
1958         // Enrol the user we are doing the search for and one user in the course.
1959         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1960         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1962         // Perform a search.
1963         $result = core_message_external::data_for_messagearea_search_users_in_course($user1->id, $course1->id, 'User');
1965         // We need to execute the return values cleaning process to simulate the web service server.
1966         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_in_course_returns(),
1967             $result);
1969         // Check that we got the user enrolled, and that the user we are performing the search on behalf of was not returned.
1970         $users = $result['contacts'];
1971         $this->assertCount(1, $users);
1973         $user = $users[0];
1974         $this->assertEquals($user2->id, $user['userid']);
1975         $this->assertEquals(fullname($user2), $user['fullname']);
1976         $this->assertFalse($user['ismessaging']);
1977         $this->assertFalse($user['sentfromcurrentuser']);
1978         $this->assertNull($user['lastmessage']);
1979         $this->assertNull($user['messageid']);
1980         $this->assertFalse($user['isonline']);
1981         $this->assertFalse($user['isread']);
1982         $this->assertFalse($user['isblocked']);
1983         $this->assertNull($user['unreadcount']);
1984     }
1986     /**
1987      * Tests searching users in course as another user without the proper capabilities.
1988      */
1989     public function test_data_for_messagearea_search_users_in_course_as_other_user_without_cap() {
1990         $this->resetAfterTest(true);
1992         // Create some users.
1993         $user1 = self::getDataGenerator()->create_user();
1994         $user2 = self::getDataGenerator()->create_user();
1996         // The person doing the search for another user.
1997         $this->setUser($user1);
1999         // Create a course.
2000         $course = $this->getDataGenerator()->create_course();
2002         // Ensure an exception is thrown.
2003         $this->expectException('moodle_exception');
2004         core_message_external::data_for_messagearea_search_users_in_course($user2->id, $course->id, 'User');
2005         $this->assertDebuggingCalled();
2006     }
2008     /**
2009      * Tests searching users in course with messaging disabled.
2010      */
2011     public function test_data_for_messagearea_search_users_in_course_messaging_disabled() {
2012         global $CFG;
2014         $this->resetAfterTest(true);
2016         // Create some skeleton data just so we can call the WS..
2017         $user = self::getDataGenerator()->create_user();
2018         $course = $this->getDataGenerator()->create_course();
2020         // The person doing the search for another user.
2021         $this->setUser($user);
2023         // Disable messaging.
2024         $CFG->messaging = 0;
2026         // Ensure an exception is thrown.
2027         $this->expectException('moodle_exception');
2028         core_message_external::data_for_messagearea_search_users_in_course($user->id, $course->id, 'User');
2029         $this->assertDebuggingCalled();
2030     }
2032     /**
2033      * Tests searching users.
2034      */
2035     public function test_data_for_messagearea_search_users() {
2036         $this->resetAfterTest(true);
2038         // Create some users.
2039         $user1 = new stdClass();
2040         $user1->firstname = 'User';
2041         $user1->lastname = 'One';
2042         $user1 = self::getDataGenerator()->create_user($user1);
2044         // Set as the user performing the search.
2045         $this->setUser($user1);
2047         $user2 = new stdClass();
2048         $user2->firstname = 'User search';
2049         $user2->lastname = 'Two';
2050         $user2 = self::getDataGenerator()->create_user($user2);
2052         $user3 = new stdClass();
2053         $user3->firstname = 'User search';
2054         $user3->lastname = 'Three';
2055         $user3 = self::getDataGenerator()->create_user($user3);
2057         $user4 = new stdClass();
2058         $user4->firstname = 'User';
2059         $user4->lastname = 'Four';
2060         $user4 = self::getDataGenerator()->create_user($user4);
2062         $user5 = new stdClass();
2063         $user5->firstname = 'User search';
2064         $user5->lastname = 'Five';
2065         $user5 = self::getDataGenerator()->create_user($user5);
2067         $user6 = new stdClass();
2068         $user6->firstname = 'User';
2069         $user6->lastname = 'Six';
2070         $user6 = self::getDataGenerator()->create_user($user6);
2072         // Create some courses.
2073         $course1 = new stdClass();
2074         $course1->fullname = 'Course search';
2075         $course1->shortname = 'One';
2076         $course1 = $this->getDataGenerator()->create_course($course1);
2078         $course2 = new stdClass();
2079         $course2->fullname = 'Course';
2080         $course2->shortname = 'Two';
2081         $course2 = $this->getDataGenerator()->create_course($course2);
2083         $course3 = new stdClass();
2084         $course3->fullname = 'Course';
2085         $course3->shortname = 'Three search';
2086         $course3 = $this->getDataGenerator()->create_course($course3);
2088         $course4 = new stdClass();
2089         $course4->fullname = 'Course Four';
2090         $course4->shortname = 'CF100';
2091         $course4 = $this->getDataGenerator()->create_course($course4);
2093         $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
2094         $this->getDataGenerator()->enrol_user($user1->id, $course2->id, 'student');
2095         $this->getDataGenerator()->enrol_user($user1->id, $course3->id, 'student');
2097         // Add some users as contacts.
2098         \core_message\api::add_contact($user1->id, $user2->id);
2099         \core_message\api::add_contact($user1->id, $user3->id);
2100         \core_message\api::add_contact($user1->id, $user4->id);
2102         // Perform a search $CFG->messagingallusers setting enabled.
2103         set_config('messagingallusers', 1);
2104         $result = core_message_external::data_for_messagearea_search_users($user1->id, 'search');
2106         // We need to execute the return values cleaning process to simulate the web service server.
2107         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_returns(),
2108             $result);
2110         // Confirm that we returns contacts, courses and non-contacts.
2111         $contacts = $result['contacts'];
2112         $courses = $result['courses'];
2113         $noncontacts = $result['noncontacts'];
2115         // Check that we retrieved the correct contacts.
2116         $this->assertCount(2, $contacts);
2117         $this->assertEquals($user3->id, $contacts[0]['userid']);
2118         $this->assertEquals($user2->id, $contacts[1]['userid']);
2120         // Check that we retrieved the correct courses.
2121         $this->assertCount(2, $courses);
2122         $this->assertEquals($course3->id, $courses[0]['id']);
2123         $this->assertEquals($course1->id, $courses[1]['id']);
2125         // Check that we retrieved the correct non-contacts.
2126         $this->assertCount(1, $noncontacts);
2127         $this->assertEquals($user5->id, $noncontacts[0]['userid']);
2128     }
2130     /**
2131      * Tests searching users as another user.
2132      */
2133     public function test_data_for_messagearea_search_users_as_other_user() {
2134         $this->resetAfterTest(true);
2136         // The person doing the search.
2137         $this->setAdminUser();
2139         // Create some users.
2140         $user1 = new stdClass();
2141         $user1->firstname = 'User';
2142         $user1->lastname = 'One';
2143         $user1 = self::getDataGenerator()->create_user($user1);
2145         $user2 = new stdClass();
2146         $user2->firstname = 'User search';
2147         $user2->lastname = 'Two';
2148         $user2 = self::getDataGenerator()->create_user($user2);
2150         $user3 = new stdClass();
2151         $user3->firstname = 'User search';
2152         $user3->lastname = 'Three';
2153         $user3 = self::getDataGenerator()->create_user($user3);
2155         $user4 = new stdClass();
2156         $user4->firstname = 'User';
2157         $user4->lastname = 'Four';
2158         $user4 = self::getDataGenerator()->create_user($user4);
2160         $user5 = new stdClass();
2161         $user5->firstname = 'User search';
2162         $user5->lastname = 'Five';
2163         $user5 = self::getDataGenerator()->create_user($user5);
2165         $user6 = new stdClass();
2166         $user6->firstname = 'User';
2167         $user6->lastname = 'Six';
2168         $user6 = self::getDataGenerator()->create_user($user6);
2170         // Create some courses.
2171         $course1 = new stdClass();
2172         $course1->fullname = 'Course search';
2173         $course1->shortname = 'One';
2174         $course1 = $this->getDataGenerator()->create_course($course1);
2176         $course2 = new stdClass();
2177         $course2->fullname = 'Course';
2178         $course2->shortname = 'Two';
2179         $course2 = $this->getDataGenerator()->create_course($course2);
2181         $course3 = new stdClass();
2182         $course3->fullname = 'Course';
2183         $course3->shortname = 'Three search';
2184         $course3 = $this->getDataGenerator()->create_course($course3);
2186         // Add some users as contacts.
2187         \core_message\api::add_contact($user1->id, $user2->id);
2188         \core_message\api::add_contact($user1->id, $user3->id);
2189         \core_message\api::add_contact($user1->id, $user4->id);
2191         // Perform a search $CFG->messagingallusers setting enabled.
2192         set_config('messagingallusers', 1);
2193         $result = core_message_external::data_for_messagearea_search_users($user1->id, 'search');
2195         // We need to execute the return values cleaning process to simulate the web service server.
2196         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_users_returns(),
2197             $result);
2199         // Confirm that we returns contacts, courses and non-contacts.
2200         $contacts = $result['contacts'];
2201         $courses = $result['courses'];
2202         $noncontacts = $result['noncontacts'];
2204         // Check that we retrieved the correct contacts.
2205         $this->assertCount(2, $contacts);
2206         $this->assertEquals($user3->id, $contacts[0]['userid']);
2207         $this->assertEquals($user2->id, $contacts[1]['userid']);
2209         // Check that we retrieved the correct courses.
2210         $this->assertCount(0, $courses);
2212         // Check that we retrieved the correct non-contacts.
2213         $this->assertCount(1, $noncontacts);
2214         $this->assertEquals($user5->id, $noncontacts[0]['userid']);
2215     }
2217     /**
2218      * Tests searching users as another user without the proper capabilities.
2219      */
2220     public function test_data_for_messagearea_search_users_as_other_user_without_cap() {
2221         $this->resetAfterTest(true);
2223         // Create some users.
2224         $user1 = self::getDataGenerator()->create_user();
2225         $user2 = self::getDataGenerator()->create_user();
2227         // The person doing the search for another user.
2228         $this->setUser($user1);
2230         // Ensure an exception is thrown.
2231         $this->expectException('moodle_exception');
2232         core_message_external::data_for_messagearea_search_users($user2->id, 'User');
2233         $this->assertDebuggingCalled();
2234     }
2236     /**
2237      * Tests searching users with messaging disabled.
2238      */
2239     public function test_data_for_messagearea_search_users_messaging_disabled() {
2240         global $CFG;
2242         $this->resetAfterTest(true);
2244         // Create some skeleton data just so we can call the WS.
2245         $user = self::getDataGenerator()->create_user();
2247         // The person doing the search.
2248         $this->setUser($user);
2250         // Disable messaging.
2251         $CFG->messaging = 0;
2253         // Ensure an exception is thrown.
2254         $this->expectException('moodle_exception');
2255         core_message_external::data_for_messagearea_search_users($user->id, 'User');
2256         $this->assertDebuggingCalled();
2257     }
2259     /**
2260      * Tests searching for users when site-wide messaging is disabled.
2261      *
2262      * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
2263      * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
2264      * profile.
2265      */
2266     public function test_message_search_users_messagingallusers_disabled() {
2267         $this->resetAfterTest();
2269         // Create some users.
2270         $users = [];
2271         foreach (range(1, 7) as $i) {
2272             $user = new stdClass();
2273             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2274             $user->lastname = $i;
2275             $user = $this->getDataGenerator()->create_user($user);
2276             $users[$i] = $user;
2277         }
2279         // Enrol a few users in the same course, but leave them as non-contacts.
2280         $course1 = $this->getDataGenerator()->create_course();
2281         $this->setAdminUser();
2282         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2283         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2284         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2286         // Add some other users as contacts.
2287         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2288         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2289         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2291         // Create individual conversations between some users, one contact and one non-contact.
2292         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2293             [$users[1]->id, $users[2]->id]);
2294         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2295             [$users[6]->id, $users[1]->id]);
2297         // Create a group conversation between 4 users, including a contact and a non-contact.
2298         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2299             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
2301         // Set as the user performing the search.
2302         $this->setUser($users[1]);
2304         // Perform a search with $CFG->messagingallusers disabled.
2305         set_config('messagingallusers', 0);
2306         $result = core_message_external::message_search_users($users[1]->id, 'search');
2307         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2309         // Confirm that we returns contacts and non-contacts.
2310         $this->assertArrayHasKey('contacts', $result);
2311         $this->assertArrayHasKey('noncontacts', $result);
2312         $contacts = $result['contacts'];
2313         $noncontacts = $result['noncontacts'];
2315         // Check that we retrieved the correct contacts.
2316         $this->assertCount(2, $contacts);
2317         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2318         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2320         // Verify the correct conversations were returned for the contacts.
2321         $this->assertCount(2, $contacts[0]['conversations']);
2322         // We can't rely on the ordering of conversations within the results, so sort by id first.
2323         usort($contacts[0]['conversations'], function($a, $b) {
2324             return $a['id'] < $b['id'];
2325         });
2326         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2327         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2329         $this->assertCount(0, $contacts[1]['conversations']);
2331         // Check that we retrieved the correct non-contacts.
2332         // When site wide messaging is disabled, we expect to see only those users whose profiles we can view.
2333         $this->assertCount(2, $noncontacts);
2334         $this->assertEquals($users[6]->id, $noncontacts[0]['id']);
2335         $this->assertEquals($users[7]->id, $noncontacts[1]['id']);
2337         // Verify the correct conversations were returned for the non-contacts.
2338         $this->assertCount(1, $noncontacts[0]['conversations']);
2339         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[0]['conversations'][0]['type']);
2341         $this->assertCount(1, $noncontacts[1]['conversations']);
2342         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[1]['conversations'][0]['type']);
2343     }
2345     /**
2346      * Tests searching for users when site-wide messaging is enabled.
2347      *
2348      * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user
2349      * can view their respective profile.
2350      */
2351     public function test_message_search_users_messagingallusers_enabled() {
2352         $this->resetAfterTest();
2354         // Create some users.
2355         $users = [];
2356         foreach (range(1, 8) as $i) {
2357             $user = new stdClass();
2358             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2359             $user->lastname = $i;
2360             $user = $this->getDataGenerator()->create_user($user);
2361             $users[$i] = $user;
2362         }
2364         // Enrol a few users in the same course, but leave them as non-contacts.
2365         $course1 = $this->getDataGenerator()->create_course();
2366         $this->setAdminUser();
2367         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2368         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2369         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2371         // Add some other users as contacts.
2372         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2373         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2374         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2376         // Create individual conversations between some users, one contact and one non-contact.
2377         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2378             [$users[1]->id, $users[2]->id]);
2379         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2380             [$users[6]->id, $users[1]->id]);
2382         // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
2383         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2384             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
2386         // Set as the user performing the search.
2387         $this->setUser($users[1]);
2389         // Perform a search with $CFG->messagingallusers enabled.
2390         set_config('messagingallusers', 1);
2391         $result = core_message_external::message_search_users($users[1]->id, 'search');
2392         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2394         // Confirm that we returns contacts and non-contacts.
2395         $this->assertArrayHasKey('contacts', $result);
2396         $this->assertArrayHasKey('noncontacts', $result);
2397         $contacts = $result['contacts'];
2398         $noncontacts = $result['noncontacts'];
2400         // Check that we retrieved the correct contacts.
2401         $this->assertCount(2, $contacts);
2402         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2403         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2405         // Verify the correct conversations were returned for the contacts.
2406         $this->assertCount(2, $contacts[0]['conversations']);
2407         // We can't rely on the ordering of conversations within the results, so sort by id first.
2408         usort($contacts[0]['conversations'], function($a, $b) {
2409             return $a['id'] < $b['id'];
2410         });
2411         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]['conversations'][0]['type']);
2412         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]['conversations'][1]['type']);
2414         $this->assertCount(0, $contacts[1]['conversations']);
2416         // Check that we retrieved the correct non-contacts.
2417         // If site wide messaging is enabled, we expect to be able to search for any users.
2418         $this->assertCount(4, $noncontacts);
2419         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2420         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2421         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2422         $this->assertEquals($users[8]->id, $noncontacts[3]['id']);
2424         // Verify the correct conversations were returned for the non-contacts.
2425         $this->assertCount(0, $noncontacts[0]['conversations']);
2427         $this->assertCount(1, $noncontacts[1]['conversations']);
2428         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $noncontacts[1]['conversations'][0]['type']);
2430         $this->assertCount(1, $noncontacts[2]['conversations']);
2431         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]['conversations'][0]['type']);
2433         $this->assertCount(1, $noncontacts[3]['conversations']);
2434         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[3]['conversations'][0]['type']);
2435     }
2437     /**
2438      * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
2439      */
2440     public function test_message_search_users_with_empty_result() {
2441         $this->resetAfterTest();
2443         // Create some users, but make sure neither will match the search term.
2444         $user1 = new stdClass();
2445         $user1->firstname = 'User';
2446         $user1->lastname = 'One';
2447         $user1 = $this->getDataGenerator()->create_user($user1);
2448         $user2 = new stdClass();
2449         $user2->firstname = 'User';
2450         $user2->lastname = 'Two';
2451         $user2 = $this->getDataGenerator()->create_user($user2);
2453         // Perform a search as user1.
2454         $this->setUser($user1);
2455         $result = core_message_external::message_search_users($user1->id, 'search');
2456         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2458         // Check results are empty.
2459         $this->assertCount(0, $result['contacts']);
2460         $this->assertCount(0, $result['noncontacts']);
2461     }
2463     /**
2464      * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
2465      */
2466     public function test_message_search_users_limit_offset() {
2467         $this->resetAfterTest();
2469         // Create 20 users.
2470         $users = [];
2471         foreach (range(1, 20) as $i) {
2472             $user = new stdClass();
2473             $user->firstname = "User search";
2474             $user->lastname = $i;
2475             $user = $this->getDataGenerator()->create_user($user);
2476             $users[$i] = $user;
2477         }
2479         // Enrol the first 9 users in the same course, but leave them as non-contacts.
2480         $this->setAdminUser();
2481         $course1 = $this->getDataGenerator()->create_course();
2482         foreach (range(1, 9) as $i) {
2483             $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
2484         }
2486         // Add 5 users, starting at the 11th user, as contacts for user1.
2487         foreach (range(11, 15) as $i) {
2488             \core_message\api::add_contact($users[1]->id, $users[$i]->id);
2489         }
2491         // Set as the user performing the search.
2492         $this->setUser($users[1]);
2494         // Search using a limit of 3.
2495         // This tests the case where we have more results than the limit for both contacts and non-contacts.
2496         $result = core_message_external::message_search_users($users[1]->id, 'search', 0, 3);
2497         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2498         $contacts = $result['contacts'];
2499         $noncontacts = $result['noncontacts'];
2501         // Check that we retrieved the correct contacts.
2502         $this->assertCount(3, $contacts);
2503         $this->assertEquals($users[11]->id, $contacts[0]['id']);
2504         $this->assertEquals($users[12]->id, $contacts[1]['id']);
2505         $this->assertEquals($users[13]->id, $contacts[2]['id']);
2507         // Check that we retrieved the correct non-contacts.
2508         $this->assertCount(3, $noncontacts);
2509         $this->assertEquals($users[2]->id, $noncontacts[0]['id']);
2510         $this->assertEquals($users[3]->id, $noncontacts[1]['id']);
2511         $this->assertEquals($users[4]->id, $noncontacts[2]['id']);
2513         // Now, offset to get the next batch of results.
2514         // We expect to see 2 contacts, and 3 non-contacts.
2515         $result = core_message_external::message_search_users($users[1]->id, 'search', 3, 3);
2516         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2517         $contacts = $result['contacts'];
2518         $noncontacts = $result['noncontacts'];
2519         $this->assertCount(2, $contacts);
2520         $this->assertEquals($users[14]->id, $contacts[0]['id']);
2521         $this->assertEquals($users[15]->id, $contacts[1]['id']);
2523         $this->assertCount(3, $noncontacts);
2524         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2525         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2526         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2528         // Now, offset to get the next batch of results.
2529         // We expect to see 0 contacts, and 2 non-contacts.
2530         $result = core_message_external::message_search_users($users[1]->id, 'search', 6, 3);
2531         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2532         $contacts = $result['contacts'];
2533         $noncontacts = $result['noncontacts'];
2534         $this->assertCount(0, $contacts);
2536         $this->assertCount(2, $noncontacts);
2537         $this->assertEquals($users[8]->id, $noncontacts[0]['id']);
2538         $this->assertEquals($users[9]->id, $noncontacts[1]['id']);
2539     }
2541     /**
2542      * Tests searching users as another user having the 'moodle/user:viewdetails' capability.
2543      */
2544     public function test_message_search_users_with_cap() {
2545         $this->resetAfterTest();
2546         global $DB;
2548         // Create some users.
2549         $users = [];
2550         foreach (range(1, 8) as $i) {
2551             $user = new stdClass();
2552             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
2553             $user->lastname = $i;
2554             $user = $this->getDataGenerator()->create_user($user);
2555             $users[$i] = $user;
2556         }
2558         // Enrol a few users in the same course, but leave them as non-contacts.
2559         $course1 = $this->getDataGenerator()->create_course();
2560         $this->setAdminUser();
2561         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
2562         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
2563         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
2565         // Add some other users as contacts.
2566         \core_message\api::add_contact($users[1]->id, $users[2]->id);
2567         \core_message\api::add_contact($users[3]->id, $users[1]->id);
2568         \core_message\api::add_contact($users[1]->id, $users[4]->id);
2570         // Set as the user performing the search.
2571         $this->setUser($users[1]);
2573         // Grant the authenticated user role the capability 'user:viewdetails' at site context.
2574         $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
2575         assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
2577         // Perform a search with $CFG->messagingallusers disabled.
2578         set_config('messagingallusers', 0);
2579         $result = core_message_external::message_search_users($users[1]->id, 'search');
2580         $result = external_api::clean_returnvalue(core_message_external::message_search_users_returns(), $result);
2581         $contacts = $result['contacts'];
2582         $noncontacts = $result['noncontacts'];
2584         // Check that we retrieved the correct contacts.
2585         $this->assertCount(2, $contacts);
2586         $this->assertEquals($users[2]->id, $contacts[0]['id']);
2587         $this->assertEquals($users[3]->id, $contacts[1]['id']);
2589         // Check that we retrieved the correct non-contacts.
2590         // Site-wide messaging is disabled, but since we can see all users, we expect to be able to search for any users.
2591         $this->assertCount(4, $noncontacts);
2592         $this->assertEquals($users[5]->id, $noncontacts[0]['id']);
2593         $this->assertEquals($users[6]->id, $noncontacts[1]['id']);
2594         $this->assertEquals($users[7]->id, $noncontacts[2]['id']);
2595         $this->assertEquals($users[8]->id, $noncontacts[3]['id']);
2596     }
2598     /**
2599      * Tests searching users as another user without the 'moodle/user:viewdetails' capability.
2600      */
2601     public function test_message_search_users_without_cap() {
2602         $this->resetAfterTest();
2604         // Create some users.
2605         $user1 = $this->getDataGenerator()->create_user();
2606         $user2 = $this->getDataGenerator()->create_user();
2608         // The person doing the search for another user.
2609         $this->setUser($user1);
2611         // Ensure an exception is thrown.
2612         $this->expectException('moodle_exception');
2613         core_message_external::message_search_users($user2->id, 'User');
2614         $this->assertDebuggingCalled();
2615     }
2617     /**
2618      * Tests searching users with messaging disabled.
2619      */
2620     public function test_message_search_users_messaging_disabled() {
2621         $this->resetAfterTest();
2623         // Create some skeleton data just so we can call the WS.
2624         $user = $this->getDataGenerator()->create_user();
2626         // The person doing the search.
2627         $this->setUser($user);
2629         // Disable messaging.
2630         set_config('messaging', 0);
2632         // Ensure an exception is thrown.
2633         $this->expectException('moodle_exception');
2634         core_message_external::message_search_users($user->id, 'User');
2635     }
2637     /**
2638      * Tests searching messages.
2639      */
2640     public function test_messagearea_search_messages() {
2641         $this->resetAfterTest(true);
2643         // Create some users.
2644         $user1 = self::getDataGenerator()->create_user();
2645         $user2 = self::getDataGenerator()->create_user();
2647         // The person doing the search.
2648         $this->setUser($user1);
2650         // Send some messages back and forth.
2651         $time = time();
2652         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2653         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2654         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2655         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2656         $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2658         // Perform a search.
2659         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2661         // We need to execute the return values cleaning process to simulate the web service server.
2662         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(), $result);
2664         // Confirm the data is correct.
2665         $messages = $result['contacts'];
2666         $this->assertCount(2, $messages);
2668         $message1 = $messages[0];
2669         $message2 = $messages[1];
2671         $this->assertEquals($user2->id, $message1['userid']);
2672         $this->assertEquals(fullname($user2), $message1['fullname']);
2673         $this->assertTrue($message1['ismessaging']);
2674         $this->assertFalse($message1['sentfromcurrentuser']);
2675         $this->assertEquals('Word.', $message1['lastmessage']);
2676         $this->assertNotEmpty($message1['messageid']);
2677         $this->assertNull($message1['isonline']);
2678         $this->assertFalse($message1['isread']);
2679         $this->assertFalse($message1['isblocked']);
2680         $this->assertNull($message1['unreadcount']);
2681         $this->assertEquals($convid, $message1['conversationid']);
2683         $this->assertEquals($user2->id, $message2['userid']);
2684         $this->assertEquals(fullname($user2), $message2['fullname']);
2685         $this->assertTrue($message2['ismessaging']);
2686         $this->assertTrue($message2['sentfromcurrentuser']);
2687         $this->assertEquals('Yo!', $message2['lastmessage']);
2688         $this->assertNotEmpty($message2['messageid']);
2689         $this->assertNull($message2['isonline']);
2690         $this->assertTrue($message2['isread']);
2691         $this->assertFalse($message2['isblocked']);
2692         $this->assertNull($message2['unreadcount']);
2693         $this->assertEquals($convid, $message2['conversationid']);
2694     }
2696     /**
2697      * Tests searching messages as another user.
2698      */
2699     public function test_messagearea_search_messages_as_other_user() {
2700         $this->resetAfterTest(true);
2702         // The person doing the search.
2703         $this->setAdminUser();
2705         // Create some users.
2706         $user1 = self::getDataGenerator()->create_user();
2707         $user2 = self::getDataGenerator()->create_user();
2709         // Send some messages back and forth.
2710         $time = time();
2711         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2712         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2713         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2714         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2716         // Perform a search.
2717         $result = core_message_external::data_for_messagearea_search_messages($user1->id, 'o');
2719         // We need to execute the return values cleaning process to simulate the web service server.
2720         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_search_messages_returns(),
2721             $result);
2723         // Confirm the data is correct.
2724         $messages = $result['contacts'];
2725         $this->assertCount(2, $messages);
2727         $message1 = $messages[0];
2728         $message2 = $messages[1];
2730         $this->assertEquals($user2->id, $message1['userid']);
2731         $this->assertEquals(fullname($user2), $message1['fullname']);
2732         $this->assertTrue($message1['ismessaging']);
2733         $this->assertFalse($message1['sentfromcurrentuser']);
2734         $this->assertEquals('Word.', $message1['lastmessage']);
2735         $this->assertNotEmpty($message1['messageid']);
2736         $this->assertFalse($message1['isonline']);
2737         $this->assertFalse($message1['isread']);
2738         $this->assertFalse($message1['isblocked']);
2739         $this->assertNull($message1['unreadcount']);
2741         $this->assertEquals($user2->id, $message2['userid']);
2742         $this->assertEquals(fullname($user2), $message2['fullname']);
2743         $this->assertTrue($message2['ismessaging']);
2744         $this->assertTrue($message2['sentfromcurrentuser']);
2745         $this->assertEquals('Yo!', $message2['lastmessage']);
2746         $this->assertNotEmpty($message2['messageid']);
2747         $this->assertFalse($message2['isonline']);
2748         $this->assertTrue($message2['isread']);
2749         $this->assertFalse($message2['isblocked']);
2750         $this->assertNull($message2['unreadcount']);
2751     }
2753     /**
2754      * Tests searching messages as another user without the proper capabilities.
2755      */
2756     public function test_messagearea_search_messages_as_other_user_without_cap() {
2757         $this->resetAfterTest(true);
2759         // Create some users.
2760         $user1 = self::getDataGenerator()->create_user();
2761         $user2 = self::getDataGenerator()->create_user();
2763         // The person doing the search for another user.
2764         $this->setUser($user1);
2766         // Ensure an exception is thrown.
2767         $this->expectException('moodle_exception');
2768         core_message_external::data_for_messagearea_search_messages($user2->id, 'Search');
2769     }
2771     /**
2772      * Tests searching messages with messaging disabled
2773      */
2774     public function test_messagearea_search_messages_messaging_disabled() {
2775         global $CFG;
2777         $this->resetAfterTest(true);
2779         // Create some skeleton data just so we can call the WS.
2780         $user = self::getDataGenerator()->create_user();
2782         // The person doing the search .
2783         $this->setUser($user);
2785         // Disable messaging.
2786         $CFG->messaging = 0;
2788         // Ensure an exception is thrown.
2789         $this->expectException('moodle_exception');
2790         core_message_external::data_for_messagearea_search_messages($user->id, 'Search');
2791     }
2793     /**
2794      * Tests retrieving conversations.
2795      */
2796     public function test_messagearea_conversations() {
2797         $this->resetAfterTest(true);
2799         // Create some users.
2800         $user1 = self::getDataGenerator()->create_user();
2801         $user2 = self::getDataGenerator()->create_user();
2802         $user3 = self::getDataGenerator()->create_user();
2803         $user4 = self::getDataGenerator()->create_user();
2805         // The person retrieving the conversations.
2806         $this->setUser($user1);
2808         // Send some messages back and forth, have some different conversations with different users.
2809         $time = time();
2810         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2811         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2812         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2813         $messageid1 = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2815         $this->send_message($user1, $user3, 'Booyah', 0, $time + 4);
2816         $this->send_message($user3, $user1, 'Whaaat?', 0, $time + 5);
2817         $this->send_message($user1, $user3, 'Nothing.', 0, $time + 6);
2818         $messageid2 = $this->send_message($user3, $user1, 'Cool.', 0, $time + 7);
2820         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 8);
2821         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 9);
2822         $messageid3 = $this->send_message($user1, $user4, 'Dope.', 0, $time + 10);
2824         // Retrieve the conversations.
2825         $result = core_message_external::data_for_messagearea_conversations($user1->id);
2827         // We need to execute the return values cleaning process to simulate the web service server.
2828         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_conversations_returns(),
2829             $result);
2831         // Confirm the data is correct.
2832         $messages = $result['contacts'];
2833         $this->assertCount(3, $messages);
2835         $message1 = $messages[0];
2836         $message2 = $messages[1];
2837         $message3 = $messages[2];
2839         $this->assertEquals($user4->id, $message1['userid']);
2840         $this->assertTrue($message1['ismessaging']);
2841         $this->assertTrue($message1['sentfromcurrentuser']);
2842         $this->assertEquals('Dope.', $message1['lastmessage']);
2843         $this->assertEquals($messageid3, $message1['messageid']);
2844         $this->assertNull($message1['isonline']);
2845         $this->assertFalse($message1['isread']);
2846         $this->assertFalse($message1['isblocked']);
2847         $this->assertEquals(1, $message1['unreadcount']);
2849         $this->assertEquals($user3->id, $message2['userid']);
2850         $this->assertTrue($message2['ismessaging']);
2851         $this->assertFalse($message2['sentfromcurrentuser']);
2852         $this->assertEquals('Cool.', $message2['lastmessage']);
2853         $this->assertEquals($messageid2, $message2['messageid']);
2854         $this->assertNull($message2['isonline']);
2855         $this->assertFalse($message2['isread']);
2856         $this->assertFalse($message2['isblocked']);
2857         $this->assertEquals(2, $message2['unreadcount']);
2859         $this->assertEquals($user2->id, $message3['userid']);
2860         $this->assertTrue($message3['ismessaging']);
2861         $this->assertFalse($message3['sentfromcurrentuser']);
2862         $this->assertEquals('Word.', $message3['lastmessage']);
2863         $this->assertEquals($messageid1, $message3['messageid']);
2864         $this->assertNull($message3['isonline']);
2865         $this->assertFalse($message3['isread']);
2866         $this->assertFalse($message3['isblocked']);
2867         $this->assertEquals(2, $message3['unreadcount']);
2868     }
2870     /**
2871      * Tests retrieving conversations as another user.
2872      */
2873     public function test_messagearea_conversations_as_other_user() {
2874         $this->resetAfterTest(true);
2876         // Set as admin.
2877         $this->setAdminUser();
2879         // Create some users.
2880         $user1 = self::getDataGenerator()->create_user();
2881         $user2 = self::getDataGenerator()->create_user();
2882         $user3 = self::getDataGenerator()->create_user();
2883         $user4 = self::getDataGenerator()->create_user();
2885         // Send some messages back and forth, have some different conversations with different users.
2886         $time = time();
2887         $this->send_message($user1, $user2, 'Yo!', 0, $time);
2888         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
2889         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
2890         $messageid1 = $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
2892         $this->send_message($user1, $user3, 'Booyah', 0, $time + 4);
2893         $this->send_message($user3, $user1, 'Whaaat?', 0, $time + 5);
2894         $this->send_message($user1, $user3, 'Nothing.', 0, $time + 6);
2895         $messageid2 = $this->send_message($user3, $user1, 'Cool.', 0, $time + 7);
2897         $this->send_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 8);
2898         $this->send_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 9);
2899         $messageid3 = $this->send_message($user1, $user4, 'Dope.', 0, $time + 10);
2901         // Retrieve the conversations.
2902         $result = core_message_external::data_for_messagearea_conversations($user1->id);
2904         // We need to execute the return values cleaning process to simulate the web service server.
2905         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_conversations_returns(),
2906             $result);
2908         // Confirm the data is correct.
2909         $messages = $result['contacts'];
2910         $this->assertCount(3, $messages);
2912         $message1 = $messages[0];
2913         $message2 = $messages[1];
2914         $message3 = $messages[2];
2916         $this->assertEquals($user4->id, $message1['userid']);
2917         $this->assertTrue($message1['ismessaging']);
2918         $this->assertTrue($message1['sentfromcurrentuser']);
2919         $this->assertEquals('Dope.', $message1['lastmessage']);
2920         $this->assertEquals($messageid3, $message1['messageid']);
2921         $this->assertFalse($message1['isonline']);
2922         $this->assertFalse($message1['isread']);
2923         $this->assertFalse($message1['isblocked']);
2924         $this->assertEquals(1, $message1['unreadcount']);
2926         $this->assertEquals($user3->id, $message2['userid']);
2927         $this->assertTrue($message2['ismessaging']);
2928         $this->assertFalse($message2['sentfromcurrentuser']);
2929         $this->assertEquals('Cool.', $message2['lastmessage']);
2930         $this->assertEquals($messageid2, $message2['messageid']);
2931         $this->assertFalse($message2['isonline']);
2932         $this->assertFalse($message2['isread']);
2933         $this->assertFalse($message2['isblocked']);
2934         $this->assertEquals(2, $message2['unreadcount']);
2936         $this->assertEquals($user2->id, $message3['userid']);
2937         $this->assertTrue($message3['ismessaging']);
2938         $this->assertFalse($message3['sentfromcurrentuser']);
2939         $this->assertEquals('Word.', $message3['lastmessage']);
2940         $this->assertEquals($messageid1, $message3['messageid']);
2941         $this->assertFalse($message3['isonline']);
2942         $this->assertFalse($message3['isread']);
2943         $this->assertFalse($message3['isblocked']);
2944         $this->assertEquals(2, $message3['unreadcount']);
2945     }
2947     /**
2948      * Tests retrieving conversations as another user without the proper capabilities.
2949      */
2950     public function test_messagearea_conversations_as_other_user_without_cap() {
2951         $this->resetAfterTest(true);
2953         // Create some users.
2954         $user1 = self::getDataGenerator()->create_user();
2955         $user2 = self::getDataGenerator()->create_user();
2957         // The person retrieving the conversations for another user.
2958         $this->setUser($user1);
2960         // Ensure an exception is thrown.
2961         $this->expectException('moodle_exception');
2962         core_message_external::data_for_messagearea_conversations($user2->id);
2963     }
2965     /**
2966      * Tests retrieving conversations with messaging disabled.
2967      */
2968     public function test_messagearea_conversations_messaging_disabled() {
2969         global $CFG;
2971         $this->resetAfterTest(true);
2973         // Create some skeleton data just so we can call the WS.
2974         $user = self::getDataGenerator()->create_user();
2976         // The person retrieving the conversations.
2977         $this->setUser($user);
2979         // Disable messaging.
2980         $CFG->messaging = 0;
2982         // Ensure an exception is thrown.
2983         $this->expectException('moodle_exception');
2984         core_message_external::data_for_messagearea_conversations($user->id);
2985     }
2987     /**
2988      * Tests retrieving contacts.
2989      */
2990     public function test_messagearea_contacts() {
2991         $this->resetAfterTest(true);
2993         // Create some users.
2994         $user1 = self::getDataGenerator()->create_user();
2996         // Set as the user.
2997         $this->setUser($user1);
2999         $user2 = new stdClass();
3000         $user2->firstname = 'User';
3001         $user2->lastname = 'A';
3002         $user2 = self::getDataGenerator()->create_user($user2);
3004         $user3 = new stdClass();
3005         $user3->firstname = 'User';
3006         $user3->lastname = 'B';
3007         $user3 = self::getDataGenerator()->create_user($user3);
3009         $user4 = new stdClass();
3010         $user4->firstname = 'User';
3011         $user4->lastname = 'C';
3012         $user4 = self::getDataGenerator()->create_user($user4);
3014         $user5 = new stdClass();
3015         $user5->firstname = 'User';
3016         $user5->lastname = 'D';
3017         $user5 = self::getDataGenerator()->create_user($user5);
3019         // Add some users as contacts.
3020         \core_message\api::add_contact($user1->id, $user2->id);
3021         \core_message\api::add_contact($user1->id, $user3->id);
3022         \core_message\api::add_contact($user1->id, $user4->id);
3024         // Retrieve the contacts.
3025         $result = core_message_external::data_for_messagearea_contacts($user1->id);
3027         // We need to execute the return values cleaning process to simulate the web service server.
3028         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_contacts_returns(),
3029             $result);
3031         // Confirm the data is correct.
3032         $contacts = $result['contacts'];
3033         usort($contacts, ['static', 'sort_contacts']);
3034         $this->assertCount(3, $contacts);
3036         $contact1 = $contacts[0];
3037         $contact2 = $contacts[1];
3038         $contact3 = $contacts[2];
3040         $this->assertEquals($user2->id, $contact1['userid']);
3041         $this->assertFalse($contact1['ismessaging']);
3042         $this->assertFalse($contact1['sentfromcurrentuser']);
3043         $this->assertNull($contact1['lastmessage']);
3044         $this->assertNull($contact1['messageid']);
3045         $this->assertNull($contact1['isonline']);
3046         $this->assertFalse($contact1['isread']);
3047         $this->assertFalse($contact1['isblocked']);
3048         $this->assertNull($contact1['unreadcount']);
3050         $this->assertEquals($user3->id, $contact2['userid']);
3051         $this->assertFalse($contact2['ismessaging']);
3052         $this->assertFalse($contact2['sentfromcurrentuser']);
3053         $this->assertNull($contact2['lastmessage']);
3054         $this->assertNull($contact2['messageid']);
3055         $this->assertNull($contact2['isonline']);
3056         $this->assertFalse($contact2['isread']);
3057         $this->assertFalse($contact2['isblocked']);
3058         $this->assertNull($contact2['unreadcount']);
3060         $this->assertEquals($user4->id, $contact3['userid']);
3061         $this->assertFalse($contact3['ismessaging']);
3062         $this->assertFalse($contact3['sentfromcurrentuser']);
3063         $this->assertNull($contact3['lastmessage']);
3064         $this->assertNull($contact3['messageid']);
3065         $this->assertNull($contact3['isonline']);
3066         $this->assertFalse($contact3['isread']);
3067         $this->assertFalse($contact3['isblocked']);
3068         $this->assertNull($contact3['unreadcount']);
3069     }
3071     /**
3072      * Tests retrieving contacts as another user.
3073      */
3074     public function test_messagearea_contacts_as_other_user() {
3075         $this->resetAfterTest(true);
3077         $this->setAdminUser();
3079         // Create some users.
3080         $user1 = self::getDataGenerator()->create_user();
3082         $user2 = new stdClass();
3083         $user2->firstname = 'User';
3084         $user2->lastname = 'A';
3085         $user2 = self::getDataGenerator()->create_user($user2);
3087         $user3 = new stdClass();
3088         $user3->firstname = 'User';
3089         $user3->lastname = 'B';
3090         $user3 = self::getDataGenerator()->create_user($user3);
3092         $user4 = new stdClass();
3093         $user4->firstname = 'User';
3094         $user4->lastname = 'C';
3095         $user4 = self::getDataGenerator()->create_user($user4);
3097         $user5 = new stdClass();
3098         $user5->firstname = 'User';
3099         $user5->lastname = 'D';
3100         $user5 = self::getDataGenerator()->create_user($user5);
3102         // Add some users as contacts.
3103         \core_message\api::add_contact($user1->id, $user2->id);
3104         \core_message\api::add_contact($user1->id, $user3->id);
3105         \core_message\api::add_contact($user1->id, $user4->id);
3107         // Retrieve the contacts.
3108         $result = core_message_external::data_for_messagearea_contacts($user1->id);
3110         // We need to execute the return values cleaning process to simulate the web service server.
3111         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_contacts_returns(),
3112             $result);
3114         // Confirm the data is correct.
3115         $contacts = $result['contacts'];
3116         usort($contacts, ['static', 'sort_contacts']);
3117         $this->assertCount(3, $contacts);
3119         $contact1 = $contacts[0];
3120         $contact2 = $contacts[1];
3121         $contact3 = $contacts[2];
3123         $this->assertEquals($user2->id, $contact1['userid']);
3124         $this->assertFalse($contact1['ismessaging']);
3125         $this->assertFalse($contact1['sentfromcurrentuser']);
3126         $this->assertNull($contact1['lastmessage']);
3127         $this->assertNull($contact1['messageid']);
3128         $this->assertFalse($contact1['isonline']);
3129         $this->assertFalse($contact1['isread']);
3130         $this->assertFalse($contact1['isblocked']);
3131         $this->assertNull($contact1['unreadcount']);
3133         $this->assertEquals($user3->id, $contact2['userid']);
3134         $this->assertFalse($contact2['ismessaging']);
3135         $this->assertFalse($contact2['sentfromcurrentuser']);
3136         $this->assertNull($contact2['lastmessage']);
3137         $this->assertNull($contact2['messageid']);
3138         $this->assertFalse($contact2['isonline']);
3139         $this->assertFalse($contact2['isread']);
3140         $this->assertFalse($contact2['isblocked']);
3141         $this->assertNull($contact2['unreadcount']);
3143         $this->assertEquals($user4->id, $contact3['userid']);
3144         $this->assertFalse($contact3['ismessaging']);
3145         $this->assertFalse($contact3['sentfromcurrentuser']);
3146         $this->assertNull($contact3['lastmessage']);
3147         $this->assertNull($contact3['messageid']);
3148         $this->assertFalse($contact3['isonline']);
3149         $this->assertFalse($contact3['isread']);
3150         $this->assertFalse($contact3['isblocked']);
3151         $this->assertNull($contact3['unreadcount']);
3152     }
3154     /**
3155      * Tests retrieving contacts as another user without the proper capabilities.
3156      */
3157     public function test_messagearea_contacts_as_other_user_without_cap() {
3158         $this->resetAfterTest(true);
3160         // Create some users.
3161         $user1 = self::getDataGenerator()->create_user();
3162         $user2 = self::getDataGenerator()->create_user();
3164         // The person retrieving the contacts for another user.
3165         $this->setUser($user1);
3167         // Perform the WS call and ensure an exception is thrown.
3168         $this->expectException('moodle_exception');
3169         core_message_external::data_for_messagearea_contacts($user2->id);
3170     }
3172     /**
3173      * Tests retrieving contacts with messaging disabled.
3174      */
3175     public function test_messagearea_contacts_messaging_disabled() {
3176         global $CFG;
3178         $this->resetAfterTest(true);
3180         // Create some skeleton data just so we can call the WS.
3181         $user = self::getDataGenerator()->create_user();
3183         // The person retrieving the contacts.
3184         $this->setUser($user);
3186         // Disable messaging.
3187         $CFG->messaging = 0;
3189         // Perform the WS call and ensure we are shown that it is disabled.
3190         $this->expectException('moodle_exception');
3191         core_message_external::data_for_messagearea_contacts($user->id);
3192     }
3194     /**
3195      * Tests retrieving messages.
3196      */
3197     public function test_messagearea_messages() {
3198         $this->resetAfterTest(true);
3200         // Create some users.
3201         $user1 = self::getDataGenerator()->create_user();
3202         $user2 = self::getDataGenerator()->create_user();
3204         // The person asking for the messages.
3205         $this->setUser($user1);
3207         // Send some messages back and forth.
3208         $time = time();
3209         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3210         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3211         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3212         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3214         // Retrieve the messages.
3215         $result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id);
3217         // We need to execute the return values cleaning process to simulate the web service server.
3218         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_messages_returns(),
3219             $result);
3221         // Check the results are correct.
3222         $this->assertTrue($result['iscurrentuser']);
3223         $this->assertEquals($user1->id, $result['currentuserid']);
3224         $this->assertEquals($user2->id, $result['otheruserid']);
3225         $this->assertEquals(fullname($user2), $result['otheruserfullname']);
3226         $this->assertNull($result['isonline']);
3228         // Confirm the message data is correct.
3229         $messages = $result['messages'];
3230         $this->assertCount(4, $messages);
3232         $message1 = $messages[0];
3233         $message2 = $messages[1];
3234         $message3 = $messages[2];
3235         $message4 = $messages[3];
3237         $this->assertEquals($user1->id, $message1['useridfrom']);
3238         $this->assertEquals($user2->id, $message1['useridto']);
3239         $this->assertTrue($message1['displayblocktime']);
3240         $this->assertContains('Yo!', $message1['text']);
3242         $this->assertEquals($user2->id, $message2['useridfrom']);
3243         $this->assertEquals($user1->id, $message2['useridto']);
3244         $this->assertFalse($message2['displayblocktime']);
3245         $this->assertContains('Sup mang?', $message2['text']);
3247         $this->assertEquals($user1->id, $message3['useridfrom']);
3248         $this->assertEquals($user2->id, $message3['useridto']);
3249         $this->assertFalse($message3['displayblocktime']);
3250         $this->assertContains('Writing PHPUnit tests!', $message3['text']);
3252         $this->assertEquals($user2->id, $message4['useridfrom']);
3253         $this->assertEquals($user1->id, $message4['useridto']);
3254         $this->assertFalse($message4['displayblocktime']);
3255         $this->assertContains('Word.', $message4['text']);
3256     }
3258     /**
3259      * Tests retrieving messages.
3260      */
3261     public function test_messagearea_messages_timefrom() {
3262         $this->resetAfterTest(true);
3264         // Create some users.
3265         $user1 = self::getDataGenerator()->create_user();
3266         $user2 = self::getDataGenerator()->create_user();
3268         // The person asking for the messages.
3269         $this->setUser($user1);
3271         // Send some messages back and forth.
3272         $time = time();
3273         $this->send_message($user1, $user2, 'Message 1', 0, $time - 4);
3274         $this->send_message($user2, $user1, 'Message 2', 0, $time - 3);
3275         $this->send_message($user1, $user2, 'Message 3', 0, $time - 2);
3276         $this->send_message($user2, $user1, 'Message 4', 0, $time - 1);
3278         // Retrieve the messages from $time - 3, which should be the 3 most recent messages.
3279         $result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id, 0, 0, false, $time - 3);
3281         // We need to execute the return values cleaning process to simulate the web service server.
3282         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_messages_returns(),
3283             $result);
3285         // Confirm the message data is correct. We shouldn't get 'Message 1' back.
3286         $messages = $result['messages'];
3287         $this->assertCount(3, $messages);
3289         $message1 = $messages[0];
3290         $message2 = $messages[1];
3291         $message3 = $messages[2];
3293         $this->assertContains('Message 2', $message1['text']);
3294         $this->assertContains('Message 3', $message2['text']);
3295         $this->assertContains('Message 4', $message3['text']);
3296     }
3298     /**
3299      * Tests retrieving messages as another user.
3300      */
3301     public function test_messagearea_messages_as_other_user() {
3302         $this->resetAfterTest(true);
3304         // Set as admin.
3305         $this->setAdminUser();
3307         // Create some users.
3308         $user1 = self::getDataGenerator()->create_user();
3309         $user2 = self::getDataGenerator()->create_user();
3311         // Send some messages back and forth.
3312         $time = time();
3313         $this->send_message($user1, $user2, 'Yo!', 0, $time);
3314         $this->send_message($user2, $user1, 'Sup mang?', 0, $time + 1);
3315         $this->send_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 2);
3316         $this->send_message($user2, $user1, 'Word.', 0, $time + 3);
3318         // Retrieve the messages.
3319         $result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id);
3321         // We need to execute the return values cleaning process to simulate the web service server.
3322         $result = external_api::clean_returnvalue(core_message_external::data_for_messagearea_messages_returns(),
3323             $result);
3325         // Check the results are correct.
3326         $this->assertFalse($result['iscurrentuser']);
3327         $this->assertEquals($user1->id, $result['currentuserid']);
3328         $this->assertEquals($user2->id, $result['otheruserid']);
3329         $this->assertEquals(fullname($user2), $result['otheruserfullname']);
3330         $this->assertFalse($result['isonline']);
3332         // Confirm the message data is correct.
3333         $messages = $result['messages'];
3334         $this->assertCount(4, $messages);
3336         $message1 = $messages[0];
3337         $message2 = $messages[1];
3338         $message3 = $messages[2];
3339         $message4 = $messages[3];
3341         $this->assertEquals($user1->id, $message1['useridfrom']);
3342         $this->assertEquals($user2->id, $message1['useridto']);
3343         $this->assertTrue($message1['displayblocktime']);
3344         $this->assertContains('Yo!', $message1['text']);
3346         $this->assertEquals($user2->id, $message2['useridfrom']);
3347         $this->assertEquals($user1->id, $message2['useridto']);
3348         $this->assertFalse($message2['displayblocktime']);
3349         $this->assertContains('Sup mang?', $message2['text']);
3351         $this->assertEquals($user1->id, $message3['useridfrom']);
3352         $this->assertEquals($user2->id, $message3['useridto']);
3353         $this->assertFalse($message3['displayblocktime']);
3354         $this->assertContains('Writing PHPUnit tests!', $message3['text']);
3356         $this->assertEquals($user2->id, $message4['useridfrom']);
3357         $this->assertEquals($user1->id, $message4['useridto']);
3358         $this->assertFalse($message4['displayblocktime']);
3359         $this->assertContains('Word.', $message4['text']);
3360     }
3362     /**
3363      * Tests retrieving messages as another user without the proper capabilities.
3364      */
3365     public function test_messagearea_messages_as_other_user_without_cap() {
3366         $this->resetAfterTest(true);
3368         // Create some users.
3369         $user1 = self::getDataGenerator()->create_user();
3370         $user2 = self::getDataGenerator()->create_user();
3371         $user3 = self::getDataGenerator()->create_user();
3373         // The person asking for the messages for another user.
3374         $this->setUser($user1);
3376         // Ensure an exception is thrown.
3377         $this->expectException('moodle_exception');
3378         core_message_external::data_for_messagearea_messages($user2->id, $user3->id);