90167d35c5fb10cf16ca2b06daee67dd32817b64
[moodle.git] / message / tests / api_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  * Test message API.
19  *
20  * @package core_message
21  * @category test
22  * @copyright 2016 Mark Nelson <markn@moodle.com>
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 . '/message/tests/messagelib_test.php');
32 use \core_message\tests\helper as testhelper;
34 /**
35  * Test message API.
36  *
37  * @package core_message
38  * @category test
39  * @copyright 2016 Mark Nelson <markn@moodle.com>
40  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  */
42 class core_message_api_testcase extends core_message_messagelib_testcase {
44     public function test_mark_all_read_for_user_touser() {
45         $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
46         $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
48         $this->send_fake_message($sender, $recipient, 'Notification', 1);
49         $this->send_fake_message($sender, $recipient, 'Notification', 1);
50         $this->send_fake_message($sender, $recipient, 'Notification', 1);
51         $this->send_fake_message($sender, $recipient);
52         $this->send_fake_message($sender, $recipient);
53         $this->send_fake_message($sender, $recipient);
55         \core_message\api::mark_all_read_for_user($recipient->id);
56         $this->assertDebuggingCalled();
57         $this->assertEquals(message_count_unread_messages($recipient), 0);
58     }
60     public function test_mark_all_read_for_user_touser_with_fromuser() {
61         $sender1 = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
62         $sender2 = $this->getDataGenerator()->create_user(array('firstname' => 'Test3', 'lastname' => 'User3'));
63         $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
65         $this->send_fake_message($sender1, $recipient, 'Notification', 1);
66         $this->send_fake_message($sender1, $recipient, 'Notification', 1);
67         $this->send_fake_message($sender1, $recipient, 'Notification', 1);
68         $this->send_fake_message($sender1, $recipient);
69         $this->send_fake_message($sender1, $recipient);
70         $this->send_fake_message($sender1, $recipient);
71         $this->send_fake_message($sender2, $recipient, 'Notification', 1);
72         $this->send_fake_message($sender2, $recipient, 'Notification', 1);
73         $this->send_fake_message($sender2, $recipient, 'Notification', 1);
74         $this->send_fake_message($sender2, $recipient);
75         $this->send_fake_message($sender2, $recipient);
76         $this->send_fake_message($sender2, $recipient);
78         \core_message\api::mark_all_read_for_user($recipient->id, $sender1->id);
79         $this->assertDebuggingCalled();
80         $this->assertEquals(message_count_unread_messages($recipient), 3);
81     }
83     public function test_mark_all_read_for_user_touser_with_type() {
84         $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
85         $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
87         $this->send_fake_message($sender, $recipient, 'Notification', 1);
88         $this->send_fake_message($sender, $recipient, 'Notification', 1);
89         $this->send_fake_message($sender, $recipient, 'Notification', 1);
90         $this->send_fake_message($sender, $recipient);
91         $this->send_fake_message($sender, $recipient);
92         $this->send_fake_message($sender, $recipient);
94         \core_message\api::mark_all_read_for_user($recipient->id, 0, MESSAGE_TYPE_NOTIFICATION);
95         $this->assertDebuggingCalled();
96         $this->assertEquals(message_count_unread_messages($recipient), 3);
98         \core_message\api::mark_all_read_for_user($recipient->id, 0, MESSAGE_TYPE_MESSAGE);
99         $this->assertDebuggingCalled();
100         $this->assertEquals(message_count_unread_messages($recipient), 0);
101     }
103     /**
104      * Test count_blocked_users.
105      */
106     public function test_count_blocked_users() {
107         global $USER;
109         // Set this user as the admin.
110         $this->setAdminUser();
112         // Create user to add to the admin's block list.
113         $user1 = $this->getDataGenerator()->create_user();
114         $user2 = $this->getDataGenerator()->create_user();
116         $this->assertEquals(0, \core_message\api::count_blocked_users());
118         // Add 1 blocked user to admin's blocked user list.
119         \core_message\api::block_user($USER->id, $user1->id);
121         $this->assertEquals(0, \core_message\api::count_blocked_users($user1));
122         $this->assertEquals(1, \core_message\api::count_blocked_users());
123     }
125     /**
126      * Tests searching users in a course.
127      */
128     public function test_search_users_in_course() {
129         // Create some users.
130         $user1 = new stdClass();
131         $user1->firstname = 'User';
132         $user1->lastname = 'One';
133         $user1 = self::getDataGenerator()->create_user($user1);
135         // The person doing the search.
136         $this->setUser($user1);
138         // Second user is going to have their last access set to now, so they are online.
139         $user2 = new stdClass();
140         $user2->firstname = 'User';
141         $user2->lastname = 'Two';
142         $user2->lastaccess = time();
143         $user2 = self::getDataGenerator()->create_user($user2);
145         // Block the second user.
146         \core_message\api::block_user($user1->id, $user2->id);
148         $user3 = new stdClass();
149         $user3->firstname = 'User';
150         $user3->lastname = 'Three';
151         $user3 = self::getDataGenerator()->create_user($user3);
153         // Create a course.
154         $course1 = new stdClass();
155         $course1->fullname = 'Course';
156         $course1->shortname = 'One';
157         $course1 = $this->getDataGenerator()->create_course($course1);
159         // Enrol the searcher and one user in the course.
160         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
161         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
163         // Perform a search.
164         $results = \core_message\api::search_users_in_course($user1->id, $course1->id, 'User');
166         $this->assertEquals(1, count($results));
168         $user = $results[0];
169         $this->assertEquals($user2->id, $user->userid);
170         $this->assertEquals(fullname($user2), $user->fullname);
171         $this->assertFalse($user->ismessaging);
172         $this->assertNull($user->lastmessage);
173         $this->assertNull($user->messageid);
174         $this->assertNull($user->isonline);
175         $this->assertFalse($user->isread);
176         $this->assertTrue($user->isblocked);
177         $this->assertNull($user->unreadcount);
178     }
180     /**
181      * Tests searching users.
182      */
183     public function test_search_users() {
184         global $DB;
186         // Create some users.
187         $user1 = new stdClass();
188         $user1->firstname = 'User';
189         $user1->lastname = 'One';
190         $user1 = self::getDataGenerator()->create_user($user1);
192         // Set as the user performing the search.
193         $this->setUser($user1);
195         $user2 = new stdClass();
196         $user2->firstname = 'User search';
197         $user2->lastname = 'Two';
198         $user2 = self::getDataGenerator()->create_user($user2);
200         $user3 = new stdClass();
201         $user3->firstname = 'User search';
202         $user3->lastname = 'Three';
203         $user3 = self::getDataGenerator()->create_user($user3);
205         $user4 = new stdClass();
206         $user4->firstname = 'User';
207         $user4->lastname = 'Four';
208         $user4 = self::getDataGenerator()->create_user($user4);
210         $user5 = new stdClass();
211         $user5->firstname = 'User search';
212         $user5->lastname = 'Five';
213         $user5 = self::getDataGenerator()->create_user($user5);
215         $user6 = new stdClass();
216         $user6->firstname = 'User';
217         $user6->lastname = 'Six';
218         $user6 = self::getDataGenerator()->create_user($user6);
220         // Create some courses.
221         $course1 = new stdClass();
222         $course1->fullname = 'Course search';
223         $course1->shortname = 'One';
224         $course1 = $this->getDataGenerator()->create_course($course1);
226         $course2 = new stdClass();
227         $course2->fullname = 'Course';
228         $course2->shortname = 'Two';
229         $course2 = $this->getDataGenerator()->create_course($course2);
231         $course3 = new stdClass();
232         $course3->fullname = 'Course';
233         $course3->shortname = 'Three search';
234         $course3 = $this->getDataGenerator()->create_course($course3);
236         $course4 = new stdClass();
237         $course4->fullname = 'Course Four';
238         $course4->shortname = 'CF100';
239         $course4 = $this->getDataGenerator()->create_course($course4);
241         $course5 = new stdClass();
242         $course5->fullname = 'Course';
243         $course5->shortname = 'Five search';
244         $course5 = $this->getDataGenerator()->create_course($course5);
246         $role = $DB->get_record('role', ['shortname' => 'student']);
247         $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $role->id);
248         $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $role->id);
249         $this->getDataGenerator()->enrol_user($user1->id, $course3->id, $role->id);
250         $this->getDataGenerator()->enrol_user($user1->id, $course5->id, $role->id);
252         // Add some users as contacts.
253         \core_message\api::add_contact($user1->id, $user2->id);
254         \core_message\api::add_contact($user1->id, $user3->id);
255         \core_message\api::add_contact($user1->id, $user4->id);
257         // Remove the viewparticipants capability from one of the courses.
258         $course5context = context_course::instance($course5->id);
259         assign_capability('moodle/course:viewparticipants', CAP_PROHIBIT, $role->id, $course5context->id);
261         // Perform a search $CFG->messagingallusers setting enabled.
262         set_config('messagingallusers', 1);
263         list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
265         // Check that we retrieved the correct contacts.
266         $this->assertEquals(2, count($contacts));
267         $this->assertEquals($user3->id, $contacts[0]->userid);
268         $this->assertEquals($user2->id, $contacts[1]->userid);
270         // Check that we retrieved the correct courses.
271         $this->assertEquals(2, count($courses));
272         $this->assertEquals($course3->id, $courses[0]->id);
273         $this->assertEquals($course1->id, $courses[1]->id);
275         // Check that we retrieved the correct non-contacts.
276         $this->assertEquals(1, count($noncontacts));
277         $this->assertEquals($user5->id, $noncontacts[0]->userid);
278     }
280     /**
281      * Tests searching users with empty result.
282      */
283     public function test_search_users_with_empty_result() {
285         // Create some users.
286         $user1 = new stdClass();
287         $user1->firstname = 'User';
288         $user1->lastname = 'One';
289         $user1 = self::getDataGenerator()->create_user($user1);
291         // Set as the user performing the search.
292         $this->setUser($user1);
294         $user2 = new stdClass();
295         $user2->firstname = 'User';
296         $user2->lastname = 'Two';
297         $user2 = self::getDataGenerator()->create_user($user2);
299         // Perform a search $CFG->messagingallusers setting enabled.
300         set_config('messagingallusers', 1);
301         list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
303         // Check results are empty.
304         $this->assertEquals(0, count($contacts));
305         $this->assertEquals(0, count($courses));
306         $this->assertEquals(0, count($noncontacts));
307     }
309     /**
310      * Tests searching for users when site-wide messaging is disabled.
311      *
312      * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
313      * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
314      * profile.
315      */
316     public function test_message_search_users_messagingallusers_disabled() {
317         $this->resetAfterTest();
319         // Create some users.
320         $users = [];
321         foreach (range(1, 7) as $i) {
322             $user = new stdClass();
323             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
324             $user->lastname = $i;
325             $user = $this->getDataGenerator()->create_user($user);
326             $users[$i] = $user;
327         }
329         // Enrol a few users in the same course, but leave them as non-contacts.
330         $course1 = $this->getDataGenerator()->create_course();
331         $this->setAdminUser();
332         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
333         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
334         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
336         // Add some other users as contacts.
337         \core_message\api::add_contact($users[1]->id, $users[2]->id);
338         \core_message\api::add_contact($users[3]->id, $users[1]->id);
339         \core_message\api::add_contact($users[1]->id, $users[4]->id);
341         // Create individual conversations between some users, one contact and one non-contact.
342         $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
343             [$users[1]->id, $users[2]->id]);
344         $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
345             [$users[6]->id, $users[1]->id]);
347         // Create a group conversation between 4 users, including a contact and a non-contact.
348         $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
349             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
351         // Set as the user performing the search.
352         $this->setUser($users[1]);
354         // Perform a search with $CFG->messagingallusers disabled.
355         set_config('messagingallusers', 0);
356         $result = \core_message\api::message_search_users($users[1]->id, 'search');
358         // Confirm that we returns contacts and non-contacts.
359         $this->assertArrayHasKey(0, $result);
360         $this->assertArrayHasKey(1, $result);
361         $contacts = $result[0];
362         $noncontacts = $result[1];
364         // Check that we retrieved the correct contacts.
365         $this->assertCount(2, $contacts);
366         $this->assertEquals($users[2]->id, $contacts[0]->id);
367         $this->assertEquals($users[3]->id, $contacts[1]->id);
369         // Verify the correct conversations were returned for the contacts.
370         $this->assertCount(2, $contacts[0]->conversations);
371         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
372         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
374         $this->assertCount(0, $contacts[1]->conversations);
376         // Check that we retrieved the correct non-contacts.
377         // When site wide messaging is disabled, we expect to see only those users whose profiles we can view.
378         $this->assertCount(2, $noncontacts);
379         $this->assertEquals($users[6]->id, $noncontacts[0]->id);
380         $this->assertEquals($users[7]->id, $noncontacts[1]->id);
382         // Verify the correct conversations were returned for the non-contacts.
383         $this->assertCount(1, $noncontacts[0]->conversations);
384         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
385             $noncontacts[0]->conversations[$ic2->id]->type);
387         $this->assertCount(1, $noncontacts[1]->conversations);
388         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[1]->conversations[$gc1->id]->type);
389     }
391     /**
392      * Tests searching for users when site-wide messaging is enabled.
393      *
394      * This test verifies that any contacts are returned, as well as any non-contacts, regardless of whether the searching user
395      * can view their respective profile.
396      */
397     public function test_message_search_users_messagingallusers_enabled() {
398         $this->resetAfterTest();
400         // Create some users.
401         $users = [];
402         foreach (range(1, 8) as $i) {
403             $user = new stdClass();
404             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
405             $user->lastname = $i;
406             $user = $this->getDataGenerator()->create_user($user);
407             $users[$i] = $user;
408         }
410         // Enrol a few users in the same course, but leave them as non-contacts.
411         $course1 = $this->getDataGenerator()->create_course();
412         $this->setAdminUser();
413         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
414         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
415         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
417         // Add some other users as contacts.
418         \core_message\api::add_contact($users[1]->id, $users[2]->id);
419         \core_message\api::add_contact($users[3]->id, $users[1]->id);
420         \core_message\api::add_contact($users[1]->id, $users[4]->id);
422         // Create individual conversations between some users, one contact and one non-contact.
423         $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
424             [$users[1]->id, $users[2]->id]);
425         $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
426             [$users[6]->id, $users[1]->id]);
428         // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
429         $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
430             [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
432         // Set as the user performing the search.
433         $this->setUser($users[1]);
435         // Perform a search with $CFG->messagingallusers enabled.
436         set_config('messagingallusers', 1);
437         $result = \core_message\api::message_search_users($users[1]->id, 'search');
439         // Confirm that we returns contacts and non-contacts.
440         $this->assertArrayHasKey(0, $result);
441         $this->assertArrayHasKey(1, $result);
442         $contacts = $result[0];
443         $noncontacts = $result[1];
445         // Check that we retrieved the correct contacts.
446         $this->assertCount(2, $contacts);
447         $this->assertEquals($users[2]->id, $contacts[0]->id);
448         $this->assertEquals($users[3]->id, $contacts[1]->id);
450         // Verify the correct conversations were returned for the contacts.
451         $this->assertCount(2, $contacts[0]->conversations);
452         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
453         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
455         $this->assertCount(0, $contacts[1]->conversations);
457         // Check that we retrieved the correct non-contacts.
458         // If site wide messaging is enabled, we expect to be able to search for any users.
459         $this->assertCount(4, $noncontacts);
460         $this->assertEquals($users[5]->id, $noncontacts[0]->id);
461         $this->assertEquals($users[6]->id, $noncontacts[1]->id);
462         $this->assertEquals($users[7]->id, $noncontacts[2]->id);
463         $this->assertEquals($users[8]->id, $noncontacts[3]->id);
465         // Verify the correct conversations were returned for the non-contacts.
466         $this->assertCount(0, $noncontacts[0]->conversations);
468         $this->assertCount(1, $noncontacts[1]->conversations);
469         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
470             $noncontacts[1]->conversations[$ic2->id]->type);
472         $this->assertCount(1, $noncontacts[2]->conversations);
473         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
475         $this->assertCount(1, $noncontacts[3]->conversations);
476         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[3]->conversations[$gc1->id]->type);
477     }
479     /**
480      * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
481      */
482     public function test_message_search_users_with_empty_result() {
483         $this->resetAfterTest();
485         // Create some users, but make sure neither will match the search term.
486         $user1 = new stdClass();
487         $user1->firstname = 'User';
488         $user1->lastname = 'One';
489         $user1 = $this->getDataGenerator()->create_user($user1);
490         $user2 = new stdClass();
491         $user2->firstname = 'User';
492         $user2->lastname = 'Two';
493         $user2 = $this->getDataGenerator()->create_user($user2);
495         // Perform a search as user1.
496         $this->setUser($user1);
497         $result = \core_message\api::message_search_users($user1->id, 'search');
499         // Check results are empty.
500         $this->assertCount(0, $result[0]);
501         $this->assertCount(0, $result[1]);
502     }
504     /**
505      * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
506      */
507     public function test_message_search_users_limit_offset() {
508         $this->resetAfterTest();
510         // Create 20 users.
511         $users = [];
512         foreach (range(1, 20) as $i) {
513             $user = new stdClass();
514             $user->firstname = "User search";
515             $user->lastname = $i;
516             $user = $this->getDataGenerator()->create_user($user);
517             $users[$i] = $user;
518         }
520         // Enrol the first 9 users in the same course, but leave them as non-contacts.
521         $this->setAdminUser();
522         $course1 = $this->getDataGenerator()->create_course();
523         foreach (range(1, 9) as $i) {
524             $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
525         }
527         // Add 5 users, starting at the 11th user, as contacts for user1.
528         foreach (range(11, 15) as $i) {
529             \core_message\api::add_contact($users[1]->id, $users[$i]->id);
530         }
532         // Set as the user performing the search.
533         $this->setUser($users[1]);
535         // Search using a limit of 3.
536         // This tests the case where we have more results than the limit for both contacts and non-contacts.
537         $result = \core_message\api::message_search_users($users[1]->id, 'search', 0, 3);
538         $contacts = $result[0];
539         $noncontacts = $result[1];
541         // Check that we retrieved the correct contacts.
542         $this->assertCount(3, $contacts);
543         $this->assertEquals($users[11]->id, $contacts[0]->id);
544         $this->assertEquals($users[12]->id, $contacts[1]->id);
545         $this->assertEquals($users[13]->id, $contacts[2]->id);
547         // Check that we retrieved the correct non-contacts.
548         $this->assertCount(3, $noncontacts);
549         $this->assertEquals($users[2]->id, $noncontacts[0]->id);
550         $this->assertEquals($users[3]->id, $noncontacts[1]->id);
551         $this->assertEquals($users[4]->id, $noncontacts[2]->id);
553         // Now, offset to get the next batch of results.
554         // We expect to see 2 contacts, and 3 non-contacts.
555         $result = \core_message\api::message_search_users($users[1]->id, 'search', 3, 3);
556         $contacts = $result[0];
557         $noncontacts = $result[1];
558         $this->assertCount(2, $contacts);
559         $this->assertEquals($users[14]->id, $contacts[0]->id);
560         $this->assertEquals($users[15]->id, $contacts[1]->id);
562         $this->assertCount(3, $noncontacts);
563         $this->assertEquals($users[5]->id, $noncontacts[0]->id);
564         $this->assertEquals($users[6]->id, $noncontacts[1]->id);
565         $this->assertEquals($users[7]->id, $noncontacts[2]->id);
567         // Now, offset to get the next batch of results.
568         // We expect to see 0 contacts, and 2 non-contacts.
569         $result = \core_message\api::message_search_users($users[1]->id, 'search', 6, 3);
570         $contacts = $result[0];
571         $noncontacts = $result[1];
572         $this->assertCount(0, $contacts);
574         $this->assertCount(2, $noncontacts);
575         $this->assertEquals($users[8]->id, $noncontacts[0]->id);
576         $this->assertEquals($users[9]->id, $noncontacts[1]->id);
577     }
579     /**
580      * Tests searching users as a user having the 'moodle/user:viewdetails' capability.
581      */
582     public function test_message_search_users_with_cap() {
583         $this->resetAfterTest();
584         global $DB;
586         // Create some users.
587         $users = [];
588         foreach (range(1, 8) as $i) {
589             $user = new stdClass();
590             $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
591             $user->lastname = $i;
592             $user = $this->getDataGenerator()->create_user($user);
593             $users[$i] = $user;
594         }
596         // Enrol a few users in the same course, but leave them as non-contacts.
597         $course1 = $this->getDataGenerator()->create_course();
598         $this->setAdminUser();
599         $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
600         $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
601         $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
603         // Add some other users as contacts.
604         \core_message\api::add_contact($users[1]->id, $users[2]->id);
605         \core_message\api::add_contact($users[3]->id, $users[1]->id);
606         \core_message\api::add_contact($users[1]->id, $users[4]->id);
608         // Set as the user performing the search.
609         $this->setUser($users[1]);
611         // Grant the authenticated user role the capability 'user:viewdetails' at site context.
612         $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
613         assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
615         // Perform a search with $CFG->messagingallusers disabled.
616         set_config('messagingallusers', 0);
617         $result = \core_message\api::message_search_users($users[1]->id, 'search');
618         $contacts = $result[0];
619         $noncontacts = $result[1];
621         // Check that we retrieved the correct contacts.
622         $this->assertCount(2, $contacts);
623         $this->assertEquals($users[2]->id, $contacts[0]->id);
624         $this->assertEquals($users[3]->id, $contacts[1]->id);
626         // Check that we retrieved the correct non-contacts.
627         // Site-wide messaging is disabled, but since we can see all users, we expect to be able to search for any users.
628         $this->assertCount(4, $noncontacts);
629         $this->assertEquals($users[5]->id, $noncontacts[0]->id);
630         $this->assertEquals($users[6]->id, $noncontacts[1]->id);
631         $this->assertEquals($users[7]->id, $noncontacts[2]->id);
632         $this->assertEquals($users[8]->id, $noncontacts[3]->id);
633     }
635     /**
636      * Tests searching users with messaging disabled.
637      */
638     public function test_message_search_users_messaging_disabled() {
639         $this->resetAfterTest();
641         // Create a user.
642         $user = $this->getDataGenerator()->create_user();
644         // Disable messaging.
645         set_config('messaging', 0);
647         // Ensure an exception is thrown.
648         $this->expectException('moodle_exception');
649         \core_message\api::message_search_users($user->id, 'User');
650     }
652     /**
653      * Tests getting conversations between 2 users.
654      */
655     public function test_get_conversations_between_users() {
656         // Create some users.
657         $user1 = new stdClass();
658         $user1->firstname = 'User';
659         $user1->lastname = 'One';
660         $user1 = self::getDataGenerator()->create_user($user1);
662         $user2 = new stdClass();
663         $user2->firstname = 'User';
664         $user2->lastname = 'Two';
665         $user2 = self::getDataGenerator()->create_user($user2);
667         $user3 = new stdClass();
668         $user3->firstname = 'User search';
669         $user3->lastname = 'Three';
670         $user3 = self::getDataGenerator()->create_user($user3);
672         $user4 = new stdClass();
673         $user4->firstname = 'User';
674         $user4->lastname = 'Four';
675         $user4 = self::getDataGenerator()->create_user($user4);
677         $user5 = new stdClass();
678         $user5->firstname = 'User';
679         $user5->lastname = 'Five';
680         $user5 = self::getDataGenerator()->create_user($user5);
682         $user6 = new stdClass();
683         $user6->firstname = 'User search';
684         $user6->lastname = 'Six';
685         $user6 = self::getDataGenerator()->create_user($user6);
687         // Add some users as contacts.
688         \core_message\api::add_contact($user1->id, $user2->id);
689         \core_message\api::add_contact($user6->id, $user1->id);
691         // Create private conversations with some users.
692         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
693             array($user1->id, $user2->id));
694         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
695             array($user3->id, $user1->id));
697         // Create a group conversation with users.
698         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
699             array($user1->id, $user2->id, $user3->id, $user4->id),
700             'Project chat');
702         // Check that we retrieved the correct conversations.
703         $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user2->id));
704         $this->assertCount(2, \core_message\api::get_conversations_between_users($user2->id, $user1->id));
705         $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user3->id));
706         $this->assertCount(2, \core_message\api::get_conversations_between_users($user3->id, $user1->id));
707         $this->assertCount(1, \core_message\api::get_conversations_between_users($user1->id, $user4->id));
708         $this->assertCount(1, \core_message\api::get_conversations_between_users($user4->id, $user1->id));
709         $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user5->id));
710         $this->assertCount(0, \core_message\api::get_conversations_between_users($user5->id, $user1->id));
711         $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user6->id));
712         $this->assertCount(0, \core_message\api::get_conversations_between_users($user6->id, $user1->id));
713     }
715     /**
716      * Tests searching messages.
717      */
718     public function test_search_messages() {
719         // Create some users.
720         $user1 = self::getDataGenerator()->create_user();
721         $user2 = self::getDataGenerator()->create_user();
722         $user3 = self::getDataGenerator()->create_user();
724         // The person doing the search.
725         $this->setUser($user1);
727         // Send some messages back and forth.
728         $time = 1;
729         $this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time);
730         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
731         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
732         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
733         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
735         $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
736         $conv2id = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
738         // Block user 3.
739         \core_message\api::block_user($user1->id, $user3->id);
741         // Perform a search.
742         $messages = \core_message\api::search_messages($user1->id, 'o');
744         // Confirm the data is correct.
745         $this->assertEquals(3, count($messages));
747         $message1 = $messages[0];
748         $message2 = $messages[1];
749         $message3 = $messages[2];
751         $this->assertEquals($user2->id, $message1->userid);
752         $this->assertEquals($user2->id, $message1->useridfrom);
753         $this->assertEquals(fullname($user2), $message1->fullname);
754         $this->assertTrue($message1->ismessaging);
755         $this->assertEquals('Word.', $message1->lastmessage);
756         $this->assertNotEmpty($message1->messageid);
757         $this->assertNull($message1->isonline);
758         $this->assertFalse($message1->isread);
759         $this->assertFalse($message1->isblocked);
760         $this->assertNull($message1->unreadcount);
761         $this->assertEquals($convid, $message1->conversationid);
763         $this->assertEquals($user2->id, $message2->userid);
764         $this->assertEquals($user1->id, $message2->useridfrom);
765         $this->assertEquals(fullname($user2), $message2->fullname);
766         $this->assertTrue($message2->ismessaging);
767         $this->assertEquals('Yo!', $message2->lastmessage);
768         $this->assertNotEmpty($message2->messageid);
769         $this->assertNull($message2->isonline);
770         $this->assertTrue($message2->isread);
771         $this->assertFalse($message2->isblocked);
772         $this->assertNull($message2->unreadcount);
773         $this->assertEquals($convid, $message2->conversationid);
775         $this->assertEquals($user3->id, $message3->userid);
776         $this->assertEquals($user3->id, $message3->useridfrom);
777         $this->assertEquals(fullname($user3), $message3->fullname);
778         $this->assertTrue($message3->ismessaging);
779         $this->assertEquals('Don\'t block me.', $message3->lastmessage);
780         $this->assertNotEmpty($message3->messageid);
781         $this->assertNull($message3->isonline);
782         $this->assertFalse($message3->isread);
783         $this->assertTrue($message3->isblocked);
784         $this->assertNull($message3->unreadcount);
785         $this->assertEquals($conv2id, $message3->conversationid);
786     }
788     /**
789      * Test verifying that favourited conversations can be retrieved.
790      */
791     public function test_get_favourite_conversations() {
792         // Create some users.
793         $user1 = self::getDataGenerator()->create_user();
794         $user2 = self::getDataGenerator()->create_user();
795         $user3 = self::getDataGenerator()->create_user();
796         $user4 = self::getDataGenerator()->create_user();
798         // The person doing the search.
799         $this->setUser($user1);
801         // No conversations yet.
802         $this->assertEquals([], \core_message\api::get_conversations($user1->id));
804         // Create some conversations for user1.
805         $time = 1;
806         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
807         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
808         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
809         $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
811         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
812         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
813         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
814         $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
816         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
817         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
818         $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
820         // Favourite the first 2 conversations for user1.
821         $convoids = [];
822         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
823         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
824         $user1context = context_user::instance($user1->id);
825         $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
826         foreach ($convoids as $convoid) {
827             $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
828         }
830         // We should have 3 conversations.
831         $this->assertCount(3, \core_message\api::get_conversations($user1->id));
833         // And 2 favourited conversations.
834         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
835         $this->assertCount(2, $conversations);
836     }
838     /**
839      * Tests retrieving favourite conversations with a limit and offset to ensure pagination works correctly.
840      */
841     public function test_get_favourite_conversations_limit_offset() {
842         // Create some users.
843         $user1 = self::getDataGenerator()->create_user();
844         $user2 = self::getDataGenerator()->create_user();
845         $user3 = self::getDataGenerator()->create_user();
846         $user4 = self::getDataGenerator()->create_user();
848         // The person doing the search.
849         $this->setUser($user1);
851         // No conversations yet.
852         $this->assertEquals([], \core_message\api::get_conversations($user1->id));
854         // Create some conversations for user1.
855         $time = 1;
856         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
857         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
858         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
859         $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
861         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
862         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
863         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
864         $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
866         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
867         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
868         $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
870         // Favourite the all conversations for user1.
871         $convoids = [];
872         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
873         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
874         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user4->id]);
875         $user1context = context_user::instance($user1->id);
876         $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
877         foreach ($convoids as $convoid) {
878             $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
879         }
881         // Get all records, using offset 0 and large limit.
882         $this->assertCount(2, \core_message\api::get_conversations($user1->id, 1, 10, null, true));
884         // Now, get 10 conversations starting at the second record. We should see 2 conversations.
885         $this->assertCount(2, \core_message\api::get_conversations($user1->id, 1, 10, null, true));
887         // Now, try to get favourited conversations using an invalid offset.
888         $this->assertCount(0, \core_message\api::get_conversations($user1->id, 4, 10, null, true));
889     }
891     /**
892      * Tests retrieving favourite conversations when a conversation contains a deleted user.
893      */
894     public function test_get_favourite_conversations_with_deleted_user() {
895         // Create some users.
896         $user1 = self::getDataGenerator()->create_user();
897         $user2 = self::getDataGenerator()->create_user();
898         $user3 = self::getDataGenerator()->create_user();
900         // Send some messages back and forth, have some different conversations with different users.
901         $time = 1;
902         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
903         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
904         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
905         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
907         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
908         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
909         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
910         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
912         // Favourite the all conversations for user1.
913         $convoids = [];
914         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
915         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
916         $user1context = context_user::instance($user1->id);
917         $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
918         foreach ($convoids as $convoid) {
919             $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
920         }
922         // Delete the second user.
923         delete_user($user2);
925         // Retrieve the conversations.
926         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
928         // We should only have one conversation because the other user was deleted.
929         $this->assertCount(1, $conversations);
931         // Confirm the conversation is from the non-deleted user.
932         $conversation = reset($conversations);
933         $this->assertEquals($convoids[1], $conversation->id);
934     }
936     /**
937      * Test confirming that conversations can be marked as favourites.
938      */
939     public function test_set_favourite_conversation() {
940         // Create some users.
941         $user1 = self::getDataGenerator()->create_user();
942         $user2 = self::getDataGenerator()->create_user();
943         $user3 = self::getDataGenerator()->create_user();
945         // Send some messages back and forth, have some different conversations with different users.
946         $time = 1;
947         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
948         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
949         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
950         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
952         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
953         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
954         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
955         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
957         // Favourite the first conversation as user 1.
958         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
959         $favourite = \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
961         // Verify we have a single favourite conversation a user 1.
962         $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
964         // Verify we have no favourites as user2, despite being a member in that conversation.
965         $this->assertCount(0, \core_message\api::get_conversations($user2->id, 0, 20, null, true));
967         // Try to favourite the same conversation again should just return the existing favourite.
968         $repeatresult = \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
969         $this->assertEquals($favourite->id, $repeatresult->id);
970     }
972     /**
973      * Test verifying that trying to mark a non-existent conversation as a favourite, results in an exception.
974      */
975     public function test_set_favourite_conversation_nonexistent_conversation() {
976         // Create some users.
977         $user1 = self::getDataGenerator()->create_user();
978         // Try to favourite a non-existent conversation.
979         $this->expectException(\moodle_exception::class);
980         \core_message\api::set_favourite_conversation(0, $user1->id);
981     }
983     /**
984      * Test verifying that a conversation cannot be marked as favourite unless the user is a member of that conversation.
985      */
986     public function test_set_favourite_conversation_non_member() {
987         // Create some users.
988         $user1 = self::getDataGenerator()->create_user();
989         $user2 = self::getDataGenerator()->create_user();
990         $user3 = self::getDataGenerator()->create_user();
992         // Send some messages back and forth, have some different conversations with different users.
993         $time = 1;
994         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
995         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
996         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
997         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
999         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1000         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1001         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1002         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1004         // Try to favourite the first conversation as user 3, who is not a member.
1005         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1006         $this->expectException(\moodle_exception::class);
1007         \core_message\api::set_favourite_conversation($conversationid1, $user3->id);
1008     }
1010     /**
1011      * Test confirming that those conversations marked as favourites can be unfavourited.
1012      */
1013     public function test_unset_favourite_conversation() {
1014         // Create some users.
1015         $user1 = self::getDataGenerator()->create_user();
1016         $user2 = self::getDataGenerator()->create_user();
1017         $user3 = self::getDataGenerator()->create_user();
1019         // Send some messages back and forth, have some different conversations with different users.
1020         $time = 1;
1021         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1022         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1023         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1024         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1026         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1027         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1028         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1029         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1031         // Favourite the first conversation as user 1 and the second as user 3.
1032         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1033         $conversationid2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1034         \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
1035         \core_message\api::set_favourite_conversation($conversationid2, $user3->id);
1037         // Verify we have a single favourite conversation for both user 1 and user 3.
1038         $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1039         $this->assertCount(1, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
1041         // Now unfavourite the conversation as user 1.
1042         \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1044         // Verify we have a single favourite conversation user 3 only, and none for user1.
1045         $this->assertCount(1, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
1046         $this->assertCount(0, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1048         // Try to favourite the same conversation again as user 1.
1049         $this->expectException(\moodle_exception::class);
1050         \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1051     }
1053     /**
1054      * Test verifying that a valid conversation cannot be unset as a favourite if it's not marked as a favourite.
1055      */
1056     public function test_unset_favourite_conversation_not_favourite() {
1057         // Create some users.
1058         $user1 = self::getDataGenerator()->create_user();
1059         $user2 = self::getDataGenerator()->create_user();
1061         // Send some messages back and forth, have some different conversations with different users.
1062         $time = 1;
1063         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1064         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1065         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1066         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1068         // Now try to unfavourite the conversation as user 1.
1069         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1070         $this->expectException(\moodle_exception::class);
1071         \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1072     }
1074     /**
1075      * Test verifying that a non-existent conversation cannot be unset as a favourite.
1076      */
1077     public function test_unset_favourite_conversation_non_existent_conversation() {
1078         // Create some users.
1079         $user1 = self::getDataGenerator()->create_user();
1081         // Now try to unfavourite the conversation as user 1.
1082         $this->expectException(\moodle_exception::class);
1083         \core_message\api::unset_favourite_conversation(0, $user1->id);
1084     }
1086     /**
1087      * Helper to seed the database with initial state.
1088      */
1089     protected function create_conversation_test_data() {
1090         // Create some users.
1091         $user1 = self::getDataGenerator()->create_user();
1092         $user2 = self::getDataGenerator()->create_user();
1093         $user3 = self::getDataGenerator()->create_user();
1094         $user4 = self::getDataGenerator()->create_user();
1096         $time = 1;
1098         // Create some conversations. We want:
1099         // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message.
1100         // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message.
1101         // 3) At least one of each type (group, individual) of which user1 IS NOT a member.
1102         // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering).
1103         // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member.
1105         // Individual conversation, user1 is a member, last message from other user.
1106         $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1107             [$user1->id, $user2->id]);
1108         testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time);
1109         testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1);
1111         // Individual conversation, user1 is a member, last message from user1.
1112         $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1113             [$user1->id, $user3->id]);
1114         testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2);
1115         testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3);
1117         // Individual conversation, user1 is not a member.
1118         $ic3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1119             [$user2->id, $user3->id]);
1120         testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4);
1121         testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5);
1123         // Group conversation, user1 is not a member.
1124         $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1125             [$user2->id, $user3->id, $user4->id], 'Project discussions');
1126         testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6);
1127         testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7);
1129         // Group conversation, user1 is a member, last message from another user.
1130         $gc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1131             [$user1->id, $user3->id, $user4->id], 'Group chat');
1132         testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8);
1133         testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9);
1134         testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10);
1136         // Group conversation, user1 is a member, last message from user1.
1137         $gc3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1138             [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!');
1139         testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11);
1140         testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12);
1141         testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13);
1143         // Empty group conversations (x2), user1 is a member.
1144         $gc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1145             [$user1->id, $user2->id, $user3->id], 'Empty group');
1146         $gc5 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1147             [$user1->id, $user2->id, $user4->id], 'Another empty group');
1149         // Empty group conversation, user1 is NOT a member.
1150         $gc6 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1151             [$user2->id, $user3->id, $user4->id], 'Empty group 3');
1153         return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6];
1154     }
1156     /**
1157      * Test verifying get_conversations when no limits, offsets, type filters or favourite restrictions are used.
1158      */
1159     public function test_get_conversations_no_restrictions() {
1160         global $DB;
1161         // No conversations should exist yet.
1162         $user1 = self::getDataGenerator()->create_user();
1163         $this->assertEquals([], \core_message\api::get_conversations($user1->id));
1165         // Get a bunch of conversations, some group, some individual and in different states.
1166         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1167             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1169         // Get all conversations for user1.
1170         $conversations = core_message\api::get_conversations($user1->id);
1172         // Verify there are 2 individual conversation, 2 group conversations, and 2 empty group conversations.
1173         // The conversations with the most recent messages should be listed first, followed by the empty
1174         // conversations, with the most recently created first.
1175         $this->assertCount(6, $conversations);
1176         $typecounts  = array_count_values(array_column($conversations, 'type'));
1177         $this->assertEquals(2, $typecounts[1]);
1178         $this->assertEquals(4, $typecounts[2]);
1180         // Those conversations having messages should be listed first, ordered by most recent message time.
1181         $this->assertEquals($gc3->id, $conversations[0]->id);
1182         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[0]->type);
1183         $this->assertFalse($conversations[0]->isfavourite);
1184         $this->assertCount(1, $conversations[0]->members);
1185         $this->assertEquals(4, $conversations[0]->membercount);
1186         $this->assertCount(1, $conversations[0]->messages);
1187         $message = $DB->get_record('messages', ['id' => $conversations[0]->messages[0]->id]);
1188         $expectedmessagetext = message_format_message_text($message);
1189         $this->assertEquals($expectedmessagetext, $conversations[0]->messages[0]->text);
1190         $this->assertEquals($user1->id, $conversations[0]->messages[0]->useridfrom);
1192         $this->assertEquals($gc2->id, $conversations[1]->id);
1193         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[1]->type);
1194         $this->assertFalse($conversations[1]->isfavourite);
1195         $this->assertCount(1, $conversations[1]->members);
1196         $this->assertEquals(3, $conversations[1]->membercount);
1197         $this->assertCount(1, $conversations[1]->messages);
1198         $message = $DB->get_record('messages', ['id' => $conversations[1]->messages[0]->id]);
1199         $expectedmessagetext = message_format_message_text($message);
1200         $this->assertEquals($expectedmessagetext, $conversations[1]->messages[0]->text);
1201         $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1203         $this->assertEquals($ic2->id, $conversations[2]->id);
1204         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[2]->type);
1205         $this->assertFalse($conversations[2]->isfavourite);
1206         $this->assertCount(1, $conversations[2]->members);
1207         $this->assertEquals($user3->id, $conversations[2]->members[$user3->id]->id);
1208         $this->assertEquals(2, $conversations[2]->membercount);
1209         $this->assertCount(1, $conversations[2]->messages);
1210         $message = $DB->get_record('messages', ['id' => $conversations[2]->messages[0]->id]);
1211         $expectedmessagetext = message_format_message_text($message);
1212         $this->assertEquals($expectedmessagetext, $conversations[2]->messages[0]->text);
1213         $this->assertEquals($user1->id, $conversations[2]->messages[0]->useridfrom);
1215         $this->assertEquals($ic1->id, $conversations[3]->id);
1216         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[3]->type);
1217         $this->assertFalse($conversations[3]->isfavourite);
1218         $this->assertCount(1, $conversations[3]->members);
1219         $this->assertEquals(2, $conversations[3]->membercount);
1220         $this->assertCount(1, $conversations[3]->messages);
1221         $message = $DB->get_record('messages', ['id' => $conversations[3]->messages[0]->id]);
1222         $expectedmessagetext = message_format_message_text($message);
1223         $this->assertEquals($expectedmessagetext, $conversations[3]->messages[0]->text);
1224         $this->assertEquals($user2->id, $conversations[3]->messages[0]->useridfrom);
1226         // Of the groups without messages, we expect to see the most recently created first.
1227         $this->assertEquals($gc5->id, $conversations[4]->id);
1228         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[4]->type);
1229         $this->assertFalse($conversations[4]->isfavourite);
1230         $this->assertCount(0, $conversations[4]->members); // No members returned, because no recent messages exist.
1231         $this->assertEquals(3, $conversations[4]->membercount);
1232         $this->assertEmpty($conversations[4]->messages);
1234         $this->assertEquals($gc4->id, $conversations[5]->id);
1235         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[5]->type);
1236         $this->assertFalse($conversations[5]->isfavourite);
1237         $this->assertCount(0, $conversations[5]->members);
1238         $this->assertEquals(3, $conversations[5]->membercount);
1239         $this->assertEmpty($conversations[5]->messages);
1241         // Verify format of the return structure.
1242         foreach ($conversations as $conv) {
1243             $this->assertObjectHasAttribute('id', $conv);
1244             $this->assertObjectHasAttribute('name', $conv);
1245             $this->assertObjectHasAttribute('subname', $conv);
1246             $this->assertObjectHasAttribute('imageurl', $conv);
1247             $this->assertObjectHasAttribute('type', $conv);
1248             $this->assertObjectHasAttribute('isfavourite', $conv);
1249             $this->assertObjectHasAttribute('membercount', $conv);
1250             $this->assertObjectHasAttribute('isread', $conv);
1251             $this->assertObjectHasAttribute('unreadcount', $conv);
1252             $this->assertObjectHasAttribute('members', $conv);
1253             foreach ($conv->members as $member) {
1254                 $this->assertObjectHasAttribute('id', $member);
1255                 $this->assertObjectHasAttribute('fullname', $member);
1256                 $this->assertObjectHasAttribute('profileimageurl', $member);
1257                 $this->assertObjectHasAttribute('profileimageurlsmall', $member);
1258                 $this->assertObjectHasAttribute('isonline', $member);
1259                 $this->assertObjectHasAttribute('showonlinestatus', $member);
1260                 $this->assertObjectHasAttribute('isblocked', $member);
1261                 $this->assertObjectHasAttribute('iscontact', $member);
1262                 $this->assertObjectHasAttribute('isdeleted', $member);
1263                 $this->assertObjectHasAttribute('canmessage', $member);
1264                 $this->assertObjectHasAttribute('requirescontact', $member);
1265                 $this->assertObjectHasAttribute('contactrequests', $member);
1266             }
1267             $this->assertObjectHasAttribute('messages', $conv);
1268             foreach ($conv->messages as $message) {
1269                 $this->assertObjectHasAttribute('id', $message);
1270                 $this->assertObjectHasAttribute('useridfrom', $message);
1271                 $this->assertObjectHasAttribute('text', $message);
1272                 $this->assertObjectHasAttribute('timecreated', $message);
1273             }
1274         }
1275     }
1277     /**
1278      * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately.
1279      */
1280     public function test_get_conversations_message_format() {
1281         global $DB;
1282         // Create some users.
1283         $user1 = self::getDataGenerator()->create_user();
1284         $user2 = self::getDataGenerator()->create_user();
1286         // Create conversation.
1287         $conversation = \core_message\api::create_conversation(
1288             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1289             [$user1->id, $user2->id]
1290         );
1292         // Send some messages back and forth.
1293         $time = 1;
1294         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1);
1295         $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2);
1297         // Verify the format of the html message.
1298         $message = $DB->get_record('messages', ['id' => $mid]);
1299         $expectedmessagetext = message_format_message_text($message);
1300         $conversations = \core_message\api::get_conversations($user1->id);
1301         $messages = $conversations[0]->messages;
1302         $this->assertEquals($expectedmessagetext, $messages[0]->text);
1303     }
1305     /**
1306      * Tests retrieving conversations with a limit and offset to ensure pagination works correctly.
1307      */
1308     public function test_get_conversations_limit_offset() {
1309         // Get a bunch of conversations, some group, some individual and in different states.
1310         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1311             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1313         // Get all conversations for user1, limited to 1 result.
1314         $conversations = core_message\api::get_conversations($user1->id, 0, 1);
1316         // Verify the first conversation.
1317         $this->assertCount(1, $conversations);
1318         $conversation = array_shift($conversations);
1319         $this->assertEquals($conversation->id, $gc3->id);
1321         // Verify the next conversation.
1322         $conversations = \core_message\api::get_conversations($user1->id, 1, 1);
1323         $this->assertCount(1, $conversations);
1324         $this->assertEquals($gc2->id, $conversations[0]->id);
1326         // Verify the next conversation.
1327         $conversations = \core_message\api::get_conversations($user1->id, 2, 1);
1328         $this->assertCount(1, $conversations);
1329         $this->assertEquals($ic2->id, $conversations[0]->id);
1331         // Skip one and get both empty conversations.
1332         $conversations = \core_message\api::get_conversations($user1->id, 4, 2);
1333         $this->assertCount(2, $conversations);
1334         $this->assertEquals($gc5->id, $conversations[0]->id);
1335         $this->assertEmpty($conversations[0]->messages);
1336         $this->assertEquals($gc4->id, $conversations[1]->id);
1337         $this->assertEmpty($conversations[1]->messages);
1339         // Ask for an offset that doesn't exist and verify no conversations are returned.
1340         $conversations = \core_message\api::get_conversations($user1->id, 10, 1);
1341         $this->assertCount(0, $conversations);
1342     }
1344     /**
1345      * Test verifying the type filtering behaviour of the
1346      */
1347     public function test_get_conversations_type_filter() {
1348         // Get a bunch of conversations, some group, some individual and in different states.
1349         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1350             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1352         // Verify we can ask for only individual conversations.
1353         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1354             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1355         $this->assertCount(2, $conversations);
1357         // Verify we can ask for only group conversations.
1358         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1359             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP);
1360         $this->assertCount(4, $conversations);
1362         // Verify an exception is thrown if an unrecognized type is specified.
1363         $this->expectException(\moodle_exception::class);
1364         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 0);
1365     }
1367     /**
1368      * Tests retrieving conversations when a conversation contains a deleted user.
1369      */
1370     public function test_get_conversations_with_deleted_user() {
1371         // Get a bunch of conversations, some group, some individual and in different states.
1372         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1373             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1375         // Delete the second user and retrieve the conversations.
1376         // We should have 5, as $ic1 drops off the list.
1377         // Group conversations remain albeit with less members.
1378         delete_user($user2);
1379         // This is to confirm an exception is not thrown when a user AND the user context is deleted.
1380         // We no longer delete the user context, but historically we did.
1381         context_helper::delete_instance(CONTEXT_USER, $user2->id);
1382         $conversations = \core_message\api::get_conversations($user1->id);
1383         $this->assertCount(5, $conversations);
1384         $this->assertEquals($gc3->id, $conversations[0]->id);
1385         $this->assertcount(1, $conversations[0]->members);
1386         $this->assertEquals($gc2->id, $conversations[1]->id);
1387         $this->assertcount(1, $conversations[1]->members);
1388         $this->assertEquals($ic2->id, $conversations[2]->id);
1389         $this->assertEquals($gc5->id, $conversations[3]->id);
1390         $this->assertEquals($gc4->id, $conversations[4]->id);
1392         // Delete a user from a group conversation where that user had sent the most recent message.
1393         // This user will still be present in the members array, as will the message in the messages array.
1394         delete_user($user4);
1395         $conversations = \core_message\api::get_conversations($user1->id);
1396         $this->assertCount(5, $conversations);
1397         $this->assertEquals($gc2->id, $conversations[1]->id);
1398         $this->assertcount(1, $conversations[1]->members);
1399         $this->assertEquals($user4->id, $conversations[1]->members[$user4->id]->id);
1400         $this->assertcount(1, $conversations[1]->messages);
1401         $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1403         // Delete the third user and retrieve the conversations.
1404         // We should have 4, as $ic1, $ic2 drop off the list.
1405         // Group conversations remain albeit with less members.
1406         delete_user($user3);
1407         $conversations = \core_message\api::get_conversations($user1->id);
1408         $this->assertCount(4, $conversations);
1409         $this->assertEquals($gc3->id, $conversations[0]->id);
1410         $this->assertcount(1, $conversations[0]->members);
1411         $this->assertEquals($gc2->id, $conversations[1]->id);
1412         $this->assertcount(1, $conversations[1]->members);
1413         $this->assertEquals($gc5->id, $conversations[2]->id);
1414         $this->assertEquals($gc4->id, $conversations[3]->id);
1415     }
1417     /**
1418      * Test confirming the behaviour of get_conversations() when users delete all messages.
1419      */
1420     public function test_get_conversations_deleted_messages() {
1421         // Get a bunch of conversations, some group, some individual and in different states.
1422         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1423             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1425         $conversations = \core_message\api::get_conversations($user1->id);
1426         $this->assertCount(6, $conversations);
1428         // Delete all messages from a group conversation the user is in - it should be returned.
1429         $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $gc2->id));
1430         $convmessages = \core_message\api::get_conversation_messages($user1->id, $gc2->id);
1431         $messages = $convmessages['messages'];
1432         foreach ($messages as $message) {
1433             \core_message\api::delete_message($user1->id, $message->id);
1434         }
1435         $conversations = \core_message\api::get_conversations($user1->id);
1436         $this->assertCount(6, $conversations);
1437         $this->assertContains($gc2->id, array_column($conversations, 'id'));
1439         // Delete all messages from an individual conversation the user is in - it should not be returned.
1440         $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $ic1->id));
1441         $convmessages = \core_message\api::get_conversation_messages($user1->id, $ic1->id);
1442         $messages = $convmessages['messages'];
1443         foreach ($messages as $message) {
1444             \core_message\api::delete_message($user1->id, $message->id);
1445         }
1446         $conversations = \core_message\api::get_conversations($user1->id);
1447         $this->assertCount(5, $conversations);
1448         $this->assertNotContains($ic1->id, array_column($conversations, 'id'));
1449     }
1451     /**
1452      * Test verifying the behaviour of get_conversations() when fetching favourite conversations with only a single
1453      * favourite.
1454      */
1455     public function test_get_conversations_favourite_conversations_single() {
1456         // Get a bunch of conversations, some group, some individual and in different states.
1457         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1458             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1460         // Mark a single conversation as favourites.
1461         \core_message\api::set_favourite_conversation($ic2->id, $user1->id);
1463         // Get the conversation, first with no restrictions, confirming the favourite status of the conversations.
1464         $conversations = \core_message\api::get_conversations($user1->id);
1465         $this->assertCount(6, $conversations);
1466         foreach ($conversations as $conv) {
1467             if (in_array($conv->id, [$ic2->id])) {
1468                 $this->assertTrue($conv->isfavourite);
1469             } else {
1470                 $this->assertFalse($conv->isfavourite);
1471             }
1472         }
1474         // Now, get ONLY favourite conversations.
1475         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1476         $this->assertCount(1, $conversations);
1477         foreach ($conversations as $conv) {
1478             $this->assertTrue($conv->isfavourite);
1479             $this->assertEquals($ic2->id, $conv->id);
1480         }
1482         // Now, try ONLY favourites of type 'group'.
1483         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1484             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1485         $this->assertEmpty($conversations);
1487         // And NO favourite conversations.
1488         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1489         $this->assertCount(5, $conversations);
1490         foreach ($conversations as $conv) {
1491             $this->assertFalse($conv->isfavourite);
1492             $this->assertNotEquals($ic2, $conv->id);
1493         }
1494     }
1496     /**
1497      * Test verifying the behaviour of get_conversations() when fetching favourite conversations.
1498      */
1499     public function test_get_conversations_favourite_conversations() {
1500         // Get a bunch of conversations, some group, some individual and in different states.
1501         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1502             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1504         // Try to get ONLY favourite conversations, when no favourites exist.
1505         $this->assertEquals([], \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1507         // Try to get NO favourite conversations, when no favourites exist.
1508         $this->assertCount(6, \core_message\api::get_conversations($user1->id, 0, 20, null, false));
1510         // Mark a few conversations as favourites.
1511         \core_message\api::set_favourite_conversation($ic1->id, $user1->id);
1512         \core_message\api::set_favourite_conversation($gc2->id, $user1->id);
1513         \core_message\api::set_favourite_conversation($gc5->id, $user1->id);
1514         $favouriteids = [$ic1->id, $gc2->id, $gc5->id];
1516         // Get the conversations, first with no restrictions, confirming the favourite status of the conversations.
1517         $conversations = \core_message\api::get_conversations($user1->id);
1518         $this->assertCount(6, $conversations);
1519         foreach ($conversations as $conv) {
1520             if (in_array($conv->id, $favouriteids)) {
1521                 $this->assertTrue($conv->isfavourite);
1522             } else {
1523                 $this->assertFalse($conv->isfavourite);
1524             }
1525         }
1527         // Now, get ONLY favourite conversations.
1528         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1529         $this->assertCount(3, $conversations);
1530         foreach ($conversations as $conv) {
1531             $this->assertTrue($conv->isfavourite);
1532             $this->assertNotFalse(array_search($conv->id, $favouriteids));
1533         }
1535         // Now, try ONLY favourites of type 'group'.
1536         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1537             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1538         $this->assertCount(2, $conversations);
1539         foreach ($conversations as $conv) {
1540             $this->assertTrue($conv->isfavourite);
1541             $this->assertNotFalse(array_search($conv->id, [$gc2->id, $gc5->id]));
1542         }
1544         // And NO favourite conversations.
1545         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1546         $this->assertCount(3, $conversations);
1547         foreach ($conversations as $conv) {
1548             $this->assertFalse($conv->isfavourite);
1549             $this->assertFalse(array_search($conv->id, $favouriteids));
1550         }
1551     }
1553     /**
1554      * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this
1555      * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want
1556      * to confirm this happens.
1557      */
1558     public function test_get_conversations_user_in_group_and_individual_chat() {
1559         $this->resetAfterTest();
1561         $user1 = self::getDataGenerator()->create_user();
1562         $user2 = self::getDataGenerator()->create_user();
1563         $user3 = self::getDataGenerator()->create_user();
1565         $conversation = \core_message\api::create_conversation(
1566             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1567             [
1568                 $user1->id,
1569                 $user2->id
1570             ],
1571             'Individual conversation'
1572         );
1574         testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1576         $conversation = \core_message\api::create_conversation(
1577             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1578             [
1579                 $user1->id,
1580                 $user2->id,
1581             ],
1582             'Group conversation'
1583         );
1585         testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1587         \core_message\api::create_contact_request($user1->id, $user2->id);
1588         \core_message\api::create_contact_request($user1->id, $user3->id);
1590         $conversations = \core_message\api::get_conversations($user2->id);
1592         $groupconversation = array_shift($conversations);
1593         $individualconversation = array_shift($conversations);
1595         $this->assertEquals('Group conversation', $groupconversation->name);
1596         $this->assertEquals('Individual conversation', $individualconversation->name);
1598         $this->assertCount(1, $groupconversation->members);
1599         $this->assertCount(1, $individualconversation->members);
1601         $groupmember = reset($groupconversation->members);
1602         $this->assertNull($groupmember->requirescontact);
1603         $this->assertNull($groupmember->canmessage);
1604         $this->assertEmpty($groupmember->contactrequests);
1606         $individualmember = reset($individualconversation->members);
1607         $this->assertNotNull($individualmember->requirescontact);
1608         $this->assertNotNull($individualmember->canmessage);
1609         $this->assertNotEmpty($individualmember->contactrequests);
1610     }
1612     /**
1613      * Test verifying that group linked conversations are returned and contain a subname matching the course name.
1614      */
1615     public function test_get_conversations_group_linked() {
1616         global $CFG, $DB;
1618         // Create some users.
1619         $user1 = self::getDataGenerator()->create_user();
1620         $user2 = self::getDataGenerator()->create_user();
1621         $user3 = self::getDataGenerator()->create_user();
1623         $course1 = $this->getDataGenerator()->create_course();
1625         // Create a group with a linked conversation and a valid image.
1626         $this->setAdminUser();
1627         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1628         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1629         $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
1630         $group1 = $this->getDataGenerator()->create_group([
1631             'courseid' => $course1->id,
1632             'enablemessaging' => 1,
1633             'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
1634         ]);
1636         // Add users to group1.
1637         $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1638         $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
1640         // Verify the group with the image works as expected.
1641         $conversations = \core_message\api::get_conversations($user1->id);
1642         $this->assertEquals(2, $conversations[0]->membercount);
1643         $this->assertEquals($course1->shortname, $conversations[0]->subname);
1644         $groupimageurl = get_group_picture_url($group1, $group1->courseid, true);
1645         $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1647         // Create a group with a linked conversation and without any image.
1648         $group2 = $this->getDataGenerator()->create_group([
1649             'courseid' => $course1->id,
1650             'enablemessaging' => 1,
1651         ]);
1653         // Add users to group2.
1654         $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1655         $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id));
1657         // Verify the group without any image works as expected too.
1658         $conversations = \core_message\api::get_conversations($user3->id);
1659         $this->assertEquals(2, $conversations[0]->membercount);
1660         $this->assertEquals($course1->shortname, $conversations[0]->subname);
1661         $groupimageurl = get_group_picture_url($group2, $group2->courseid, true);
1662         $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1664         // Now, disable the conversation linked to the group and verify it's no longer returned.
1665         $DB->set_field('message_conversations', 'enabled', 0, ['id' => $conversations[0]->id]);
1666         $conversations = \core_message\api::get_conversations($user3->id);
1667         $this->assertCount(0, $conversations);
1668     }
1670    /**
1671     * The data provider for get_conversations_mixed.
1672     *
1673     * This provides sets of data to for testing.
1674     * @return array
1675     */
1676    public function get_conversations_mixed_provider() {
1677        return array(
1678             'Test that conversations with messages contacts is correctly ordered.' => array(
1679                 'users' => array(
1680                     'user1',
1681                     'user2',
1682                     'user3',
1683                 ),
1684                 'contacts' => array(
1685                 ),
1686                 'messages' => array(
1687                     array(
1688                         'from'          => 'user1',
1689                         'to'            => 'user2',
1690                         'state'         => 'unread',
1691                         'subject'       => 'S1',
1692                     ),
1693                     array(
1694                         'from'          => 'user2',
1695                         'to'            => 'user1',
1696                         'state'         => 'unread',
1697                         'subject'       => 'S2',
1698                     ),
1699                     array(
1700                         'from'          => 'user1',
1701                         'to'            => 'user2',
1702                         'state'         => 'unread',
1703                         'timecreated'   => 0,
1704                         'subject'       => 'S3',
1705                     ),
1706                     array(
1707                         'from'          => 'user1',
1708                         'to'            => 'user3',
1709                         'state'         => 'read',
1710                         'timemodifier'  => 1,
1711                         'subject'       => 'S4',
1712                     ),
1713                     array(
1714                         'from'          => 'user3',
1715                         'to'            => 'user1',
1716                         'state'         => 'read',
1717                         'timemodifier'  => 1,
1718                         'subject'       => 'S5',
1719                     ),
1720                     array(
1721                         'from'          => 'user1',
1722                         'to'            => 'user3',
1723                         'state'         => 'read',
1724                         'timecreated'   => 0,
1725                         'subject'       => 'S6',
1726                     ),
1727                 ),
1728                 'expectations' => array(
1729                     'user1' => array(
1730                         // User1 has conversed most recently with user3. The most recent message is M5.
1731                         array(
1732                             'messageposition'   => 0,
1733                             'with'              => 'user3',
1734                             'subject'           => '<p>S5</p>',
1735                             'unreadcount'       => 0,
1736                         ),
1737                         // User1 has also conversed with user2. The most recent message is S2.
1738                         array(
1739                             'messageposition'   => 1,
1740                             'with'              => 'user2',
1741                             'subject'           => '<p>S2</p>',
1742                             'unreadcount'       => 1,
1743                         ),
1744                     ),
1745                     'user2' => array(
1746                         // User2 has only conversed with user1. Their most recent shared message was S2.
1747                         array(
1748                             'messageposition'   => 0,
1749                             'with'              => 'user1',
1750                             'subject'           => '<p>S2</p>',
1751                             'unreadcount'       => 2,
1752                         ),
1753                     ),
1754                     'user3' => array(
1755                         // User3 has only conversed with user1. Their most recent shared message was S5.
1756                         array(
1757                             'messageposition'   => 0,
1758                             'with'              => 'user1',
1759                             'subject'           => '<p>S5</p>',
1760                             'unreadcount'       => 0,
1761                         ),
1762                     ),
1763                 ),
1764             ),
1765             'Test conversations with a single user, where some messages are read and some are not.' => array(
1766                 'users' => array(
1767                     'user1',
1768                     'user2',
1769                 ),
1770                 'contacts' => array(
1771                 ),
1772                 'messages' => array(
1773                     array(
1774                         'from'          => 'user1',
1775                         'to'            => 'user2',
1776                         'state'         => 'read',
1777                         'subject'       => 'S1',
1778                     ),
1779                     array(
1780                         'from'          => 'user2',
1781                         'to'            => 'user1',
1782                         'state'         => 'read',
1783                         'subject'       => 'S2',
1784                     ),
1785                     array(
1786                         'from'          => 'user1',
1787                         'to'            => 'user2',
1788                         'state'         => 'unread',
1789                         'timemodifier'  => 1,
1790                         'subject'       => 'S3',
1791                     ),
1792                     array(
1793                         'from'          => 'user1',
1794                         'to'            => 'user2',
1795                         'state'         => 'unread',
1796                         'timemodifier'  => 1,
1797                         'subject'       => 'S4',
1798                     ),
1799                 ),
1800                 'expectations' => array(
1801                     // The most recent message between user1 and user2 was S4.
1802                     'user1' => array(
1803                         array(
1804                             'messageposition'   => 0,
1805                             'with'              => 'user2',
1806                             'subject'           => '<p>S4</p>',
1807                             'unreadcount'       => 0,
1808                         ),
1809                     ),
1810                     'user2' => array(
1811                         // The most recent message between user1 and user2 was S4.
1812                         array(
1813                             'messageposition'   => 0,
1814                             'with'              => 'user1',
1815                             'subject'           => '<p>S4</p>',
1816                             'unreadcount'       => 2,
1817                         ),
1818                     ),
1819                 ),
1820             ),
1821             'Test conversations with a single user, where some messages are read and some are not, and messages ' .
1822             'are out of order' => array(
1823             // This can happen through a combination of factors including multi-master DB replication with messages
1824             // read somehow (e.g. API).
1825                 'users' => array(
1826                     'user1',
1827                     'user2',
1828                 ),
1829                 'contacts' => array(
1830                 ),
1831                 'messages' => array(
1832                     array(
1833                         'from'          => 'user1',
1834                         'to'            => 'user2',
1835                         'state'         => 'read',
1836                         'subject'       => 'S1',
1837                         'timemodifier'  => 1,
1838                     ),
1839                     array(
1840                         'from'          => 'user2',
1841                         'to'            => 'user1',
1842                         'state'         => 'read',
1843                         'subject'       => 'S2',
1844                         'timemodifier'  => 2,
1845                     ),
1846                     array(
1847                         'from'          => 'user1',
1848                         'to'            => 'user2',
1849                         'state'         => 'unread',
1850                         'subject'       => 'S3',
1851                     ),
1852                     array(
1853                         'from'          => 'user1',
1854                         'to'            => 'user2',
1855                         'state'         => 'unread',
1856                         'subject'       => 'S4',
1857                     ),
1858                 ),
1859                 'expectations' => array(
1860                     // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1861                     'user1' => array(
1862                         array(
1863                             'messageposition'   => 0,
1864                             'with'              => 'user2',
1865                             'subject'           => '<p>S2</p>',
1866                             'unreadcount'       => 0,
1867                         ),
1868                     ),
1869                     'user2' => array(
1870                         array(
1871                             'messageposition'   => 0,
1872                             'with'              => 'user1',
1873                             'subject'           => '<p>S2</p>',
1874                             'unreadcount'       => 2
1875                         ),
1876                     ),
1877                 ),
1878             ),
1879             'Test unread message count is correct for both users' => array(
1880                 'users' => array(
1881                     'user1',
1882                     'user2',
1883                 ),
1884                 'contacts' => array(
1885                 ),
1886                 'messages' => array(
1887                     array(
1888                         'from'          => 'user1',
1889                         'to'            => 'user2',
1890                         'state'         => 'read',
1891                         'subject'       => 'S1',
1892                         'timemodifier'  => 1,
1893                     ),
1894                     array(
1895                         'from'          => 'user2',
1896                         'to'            => 'user1',
1897                         'state'         => 'read',
1898                         'subject'       => 'S2',
1899                         'timemodifier'  => 2,
1900                     ),
1901                     array(
1902                         'from'          => 'user1',
1903                         'to'            => 'user2',
1904                         'state'         => 'read',
1905                         'subject'       => 'S3',
1906                         'timemodifier'  => 3,
1907                     ),
1908                     array(
1909                         'from'          => 'user1',
1910                         'to'            => 'user2',
1911                         'state'         => 'read',
1912                         'subject'       => 'S4',
1913                         'timemodifier'  => 4,
1914                     ),
1915                     array(
1916                         'from'          => 'user1',
1917                         'to'            => 'user2',
1918                         'state'         => 'unread',
1919                         'subject'       => 'S5',
1920                         'timemodifier'  => 5,
1921                     ),
1922                     array(
1923                         'from'          => 'user2',
1924                         'to'            => 'user1',
1925                         'state'         => 'unread',
1926                         'subject'       => 'S6',
1927                         'timemodifier'  => 6,
1928                     ),
1929                     array(
1930                         'from'          => 'user1',
1931                         'to'            => 'user2',
1932                         'state'         => 'unread',
1933                         'subject'       => 'S7',
1934                         'timemodifier'  => 7,
1935                     ),
1936                     array(
1937                         'from'          => 'user1',
1938                         'to'            => 'user2',
1939                         'state'         => 'unread',
1940                         'subject'       => 'S8',
1941                         'timemodifier'  => 8,
1942                     ),
1943                 ),
1944                 'expectations' => array(
1945                     // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1946                     'user1' => array(
1947                         array(
1948                             'messageposition'   => 0,
1949                             'with'              => 'user2',
1950                             'subject'           => '<p>S8</p>',
1951                             'unreadcount'       => 1,
1952                         ),
1953                     ),
1954                     'user2' => array(
1955                         array(
1956                             'messageposition'   => 0,
1957                             'with'              => 'user1',
1958                             'subject'           => '<p>S8</p>',
1959                             'unreadcount'       => 3,
1960                         ),
1961                     ),
1962                 ),
1963             ),
1964         );
1965     }
1967     /**
1968      * Test get_conversations with a mixture of messages.
1969      *
1970      * @dataProvider get_conversations_mixed_provider
1971      * @param array $usersdata The list of users to create for this test.
1972      * @param array $messagesdata The list of messages to create.
1973      * @param array $expectations The list of expected outcomes.
1974      */
1975     public function test_get_conversations_mixed($usersdata, $contacts, $messagesdata, $expectations) {
1976         global $DB;
1978         // Create all of the users.
1979         $users = array();
1980         foreach ($usersdata as $username) {
1981             $users[$username] = $this->getDataGenerator()->create_user(array('username' => $username));
1982         }
1984         foreach ($contacts as $username => $contact) {
1985             foreach ($contact as $contactname => $blocked) {
1986                 $record = new stdClass();
1987                 $record->userid     = $users[$username]->id;
1988                 $record->contactid  = $users[$contactname]->id;
1989                 $record->blocked    = $blocked;
1990                 $record->id = $DB->insert_record('message_contacts', $record);
1991             }
1992         }
1994         $defaulttimecreated = time();
1995         foreach ($messagesdata as $messagedata) {
1996             $from       = $users[$messagedata['from']];
1997             $to         = $users[$messagedata['to']];
1998             $subject    = $messagedata['subject'];
2000             if (isset($messagedata['state']) && $messagedata['state'] == 'unread') {
2001                 $messageid = $this->send_fake_message($from, $to, $subject);
2002             } else {
2003                 // If there is no state, or the state is not 'unread', assume the message is read.
2004                 $messageid = message_post_message($from, $to, $subject, FORMAT_PLAIN);
2005             }
2007             $updatemessage = new stdClass();
2008             $updatemessage->id = $messageid;
2009             if (isset($messagedata['timecreated'])) {
2010                 $updatemessage->timecreated = $messagedata['timecreated'];
2011             } else if (isset($messagedata['timemodifier'])) {
2012                 $updatemessage->timecreated = $defaulttimecreated + $messagedata['timemodifier'];
2013             } else {
2014                 $updatemessage->timecreated = $defaulttimecreated;
2015             }
2017             $DB->update_record('messages', $updatemessage);
2018         }
2020         foreach ($expectations as $username => $data) {
2021             // Get the recent conversations for the specified user.
2022             $user = $users[$username];
2023             $conversations = array_values(\core_message\api::get_conversations($user->id));
2024             foreach ($data as $expectation) {
2025                 $otheruser = $users[$expectation['with']];
2026                 $conversation = $conversations[$expectation['messageposition']];
2027                 $this->assertEquals($otheruser->id, $conversation->members[$otheruser->id]->id);
2028                 $this->assertEquals($expectation['subject'], $conversation->messages[0]->text);
2029                 $this->assertEquals($expectation['unreadcount'], $conversation->unreadcount);
2030             }
2031         }
2032     }
2034     /**
2035      * Tests retrieving contacts.
2036      */
2037     public function test_get_contacts() {
2038         // Create some users.
2039         $user1 = self::getDataGenerator()->create_user();
2041         // Set as the user.
2042         $this->setUser($user1);
2044         $user2 = new stdClass();
2045         $user2->firstname = 'User';
2046         $user2->lastname = 'A';
2047         $user2 = self::getDataGenerator()->create_user($user2);
2049         $user3 = new stdClass();
2050         $user3->firstname = 'User';
2051         $user3->lastname = 'B';
2052         $user3 = self::getDataGenerator()->create_user($user3);
2054         $user4 = new stdClass();
2055         $user4->firstname = 'User';
2056         $user4->lastname = 'C';
2057         $user4 = self::getDataGenerator()->create_user($user4);
2059         $user5 = new stdClass();
2060         $user5->firstname = 'User';
2061         $user5->lastname = 'D';
2062         $user5 = self::getDataGenerator()->create_user($user5);
2064         // Add some users as contacts.
2065         \core_message\api::add_contact($user1->id, $user2->id);
2066         \core_message\api::add_contact($user1->id, $user3->id);
2067         \core_message\api::add_contact($user1->id, $user4->id);
2069         // Retrieve the contacts.
2070         $contacts = \core_message\api::get_contacts($user1->id);
2072         // Confirm the data is correct.
2073         $this->assertEquals(3, count($contacts));
2074         usort($contacts, ['static', 'sort_contacts']);
2076         $contact1 = $contacts[0];
2077         $contact2 = $contacts[1];
2078         $contact3 = $contacts[2];
2080         $this->assertEquals($user2->id, $contact1->userid);
2081         $this->assertEmpty($contact1->useridfrom);
2082         $this->assertFalse($contact1->ismessaging);
2083         $this->assertNull($contact1->lastmessage);
2084         $this->assertNull($contact1->messageid);
2085         $this->assertNull($contact1->isonline);
2086         $this->assertFalse($contact1->isread);
2087         $this->assertFalse($contact1->isblocked);
2088         $this->assertNull($contact1->unreadcount);
2090         $this->assertEquals($user3->id, $contact2->userid);
2091         $this->assertEmpty($contact2->useridfrom);
2092         $this->assertFalse($contact2->ismessaging);
2093         $this->assertNull($contact2->lastmessage);
2094         $this->assertNull($contact2->messageid);
2095         $this->assertNull($contact2->isonline);
2096         $this->assertFalse($contact2->isread);
2097         $this->assertFalse($contact2->isblocked);
2098         $this->assertNull($contact2->unreadcount);
2100         $this->assertEquals($user4->id, $contact3->userid);
2101         $this->assertEmpty($contact3->useridfrom);
2102         $this->assertFalse($contact3->ismessaging);
2103         $this->assertNull($contact3->lastmessage);
2104         $this->assertNull($contact3->messageid);
2105         $this->assertNull($contact3->isonline);
2106         $this->assertFalse($contact3->isread);
2107         $this->assertFalse($contact3->isblocked);
2108         $this->assertNull($contact3->unreadcount);
2109     }
2111     /**
2112      * Tests retrieving messages.
2113      */
2114     public function test_get_messages() {
2115         // Create some users.
2116         $user1 = self::getDataGenerator()->create_user();
2117         $user2 = self::getDataGenerator()->create_user();
2119         // The person doing the search.
2120         $this->setUser($user1);
2122         // Send some messages back and forth.
2123         $time = 1;
2124         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2125         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2126         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2127         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2129         // Retrieve the messages.
2130         $messages = \core_message\api::get_messages($user1->id, $user2->id);
2132         // Confirm the message data is correct.
2133         $this->assertEquals(4, count($messages));
2135         $message1 = $messages[0];
2136         $message2 = $messages[1];
2137         $message3 = $messages[2];
2138         $message4 = $messages[3];
2140         $this->assertEquals($user1->id, $message1->useridfrom);
2141         $this->assertEquals($user2->id, $message1->useridto);
2142         $this->assertTrue($message1->displayblocktime);
2143         $this->assertContains('Yo!', $message1->text);
2145         $this->assertEquals($user2->id, $message2->useridfrom);
2146         $this->assertEquals($user1->id, $message2->useridto);
2147         $this->assertFalse($message2->displayblocktime);
2148         $this->assertContains('Sup mang?', $message2->text);
2150         $this->assertEquals($user1->id, $message3->useridfrom);
2151         $this->assertEquals($user2->id, $message3->useridto);
2152         $this->assertFalse($message3->displayblocktime);
2153         $this->assertContains('Writing PHPUnit tests!', $message3->text);
2155         $this->assertEquals($user2->id, $message4->useridfrom);
2156         $this->assertEquals($user1->id, $message4->useridto);
2157         $this->assertFalse($message4->displayblocktime);
2158         $this->assertContains('Word.', $message4->text);
2159     }
2161     /**
2162      * Tests retrieving conversation messages.
2163      */
2164     public function test_get_conversation_messages() {
2165         // Create some users.
2166         $user1 = self::getDataGenerator()->create_user();
2167         $user2 = self::getDataGenerator()->create_user();
2169         // Create conversation.
2170         $conversation = \core_message\api::create_conversation(
2171             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2172             [$user1->id, $user2->id]
2173         );
2175         // The person doing the search.
2176         $this->setUser($user1);
2178         // Send some messages back and forth.
2179         $time = 1;
2180         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2181         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2182         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2183         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2185         // Retrieve the messages.
2186         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2188         // Confirm the conversation id is correct.
2189         $this->assertEquals($conversation->id, $convmessages['id']);
2191         // Confirm the message data is correct.
2192         $messages = $convmessages['messages'];
2193         $this->assertEquals(4, count($messages));
2194         $message1 = $messages[0];
2195         $message2 = $messages[1];
2196         $message3 = $messages[2];
2197         $message4 = $messages[3];
2199         $this->assertEquals($user1->id, $message1->useridfrom);
2200         $this->assertContains('Yo!', $message1->text);
2202         $this->assertEquals($user2->id, $message2->useridfrom);
2203         $this->assertContains('Sup mang?', $message2->text);
2205         $this->assertEquals($user1->id, $message3->useridfrom);
2206         $this->assertContains('Writing PHPUnit tests!', $message3->text);
2208         $this->assertEquals($user1->id, $message4->useridfrom);
2209         $this->assertContains('Word.', $message4->text);
2211         // Confirm the members data is correct.
2212         $members = $convmessages['members'];
2213         $this->assertEquals(2, count($members));
2214     }
2216     /**
2217      * Tests retrieving group conversation messages.
2218      */
2219     public function test_get_group_conversation_messages() {
2220         // Create some users.
2221         $user1 = self::getDataGenerator()->create_user();
2222         $user2 = self::getDataGenerator()->create_user();
2223         $user3 = self::getDataGenerator()->create_user();
2224         $user4 = self::getDataGenerator()->create_user();
2226         // Create group conversation.
2227         $conversation = \core_message\api::create_conversation(
2228             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2229             [$user1->id, $user2->id, $user3->id, $user4->id]
2230         );
2232         // The person doing the search.
2233         $this->setUser($user1);
2235         // Send some messages back and forth.
2236         $time = 1;
2237         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2238         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2239         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2240         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2241         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Yeah!', $time + 5);
2243         // Retrieve the messages.
2244         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2246         // Confirm the conversation id is correct.
2247         $this->assertEquals($conversation->id, $convmessages['id']);
2249         // Confirm the message data is correct.
2250         $messages = $convmessages['messages'];
2251         $this->assertEquals(5, count($messages));
2253         $message1 = $messages[0];
2254         $message2 = $messages[1];
2255         $message3 = $messages[2];
2256         $message4 = $messages[3];
2257         $message5 = $messages[4];
2259         $this->assertEquals($user1->id, $message1->useridfrom);
2260         $this->assertContains('Yo!', $message1->text);
2262         $this->assertEquals($user2->id, $message2->useridfrom);
2263         $this->assertContains('Sup mang?', $message2->text);
2265         $this->assertEquals($user3->id, $message3->useridfrom);
2266         $this->assertContains('Writing PHPUnit tests!', $message3->text);
2268         $this->assertEquals($user1->id, $message4->useridfrom);
2269         $this->assertContains('Word.', $message4->text);
2271         $this->assertEquals($user2->id, $message5->useridfrom);
2272         $this->assertContains('Yeah!', $message5->text);
2274         // Confirm the members data is correct.
2275         $members = $convmessages['members'];
2276         $this->assertEquals(3, count($members));
2277     }
2279     /**
2280      * Test verifying the sorting param for get_conversation_messages is respected().
2281      */
2282     public function test_get_conversation_messages_sorting() {
2283         // Create some users.
2284         $user1 = self::getDataGenerator()->create_user();
2285         $user2 = self::getDataGenerator()->create_user();
2286         $user3 = self::getDataGenerator()->create_user();
2288         // Create conversations - 1 group and 1 individual.
2289         $conversation = \core_message\api::create_conversation(
2290             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2291             [$user1->id, $user2->id]
2292         );
2293         $conversation2 = \core_message\api::create_conversation(
2294             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2295             [$user1->id, $user2->id, $user3->id]
2296         );
2298         // Send some messages back and forth.
2299         $time = 1;
2300         $m1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2301         $m2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2302         $m3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2303         $m4id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2305         $gm1id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Yo!', $time + 1);
2306         $gm2id = testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Sup mang?', $time + 2);
2307         $gm3id = testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'Writing PHPUnit tests!', $time + 3);
2308         $gm4id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Word.', $time + 4);
2310         // The person doing the search.
2311         $this->setUser($user1);
2313         // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2314         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2315         $messages = $convmessages['messages'];
2316         $this->assertEquals($m1id, $messages[0]->id);
2317         $this->assertEquals($m2id, $messages[1]->id);
2318         $this->assertEquals($m3id, $messages[2]->id);
2319         $this->assertEquals($m4id, $messages[3]->id);
2321         // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2322         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated DESC');
2323         $messages = $convmessages['messages'];
2324         $this->assertEquals($m1id, $messages[3]->id);
2325         $this->assertEquals($m2id, $messages[2]->id);
2326         $this->assertEquals($m3id, $messages[1]->id);
2327         $this->assertEquals($m4id, $messages[0]->id);
2329         // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2330         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id);
2331         $messages = $convmessages['messages'];
2332         $this->assertEquals($gm1id, $messages[0]->id);
2333         $this->assertEquals($gm2id, $messages[1]->id);
2334         $this->assertEquals($gm3id, $messages[2]->id);
2335         $this->assertEquals($gm4id, $messages[3]->id);
2337         // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2338         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id, 0, 0, 'timecreated DESC');
2339         $messages = $convmessages['messages'];
2340         $this->assertEquals($gm1id, $messages[3]->id);
2341         $this->assertEquals($gm2id, $messages[2]->id);
2342         $this->assertEquals($gm3id, $messages[1]->id);
2343         $this->assertEquals($gm4id, $messages[0]->id);
2344     }
2346     /**
2347      * Test retrieving conversation messages by providing a minimum timecreated value.
2348      */
2349     public function test_get_conversation_messages_time_from_only() {
2350         // Create some users.
2351         $user1 = self::getDataGenerator()->create_user();
2352         $user2 = self::getDataGenerator()->create_user();
2353         $user3 = self::getDataGenerator()->create_user();
2354         $user4 = self::getDataGenerator()->create_user();
2356         // Create group conversation.
2357         $conversation = \core_message\api::create_conversation(
2358             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2359             [$user1->id, $user2->id, $user3->id, $user4->id]
2360         );
2362         // The person doing the search.
2363         $this->setUser($user1);
2365         // Send some messages back and forth.
2366         $time = 1;
2367         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2368         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2369         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2370         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2372         // Retrieve the messages from $time, which should be all of them.
2373         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC', $time);
2375         // Confirm the conversation id is correct.
2376         $this->assertEquals($conversation->id, $convmessages['id']);
2378         // Confirm the message data is correct.
2379         $messages = $convmessages['messages'];
2380         $this->assertEquals(4, count($messages));
2382         $message1 = $messages[0];
2383         $message2 = $messages[1];
2384         $message3 = $messages[2];
2385         $message4 = $messages[3];
2387         $this->assertContains('Message 1', $message1->text);
2388         $this->assertContains('Message 2', $message2->text);
2389         $this->assertContains('Message 3', $message3->text);
2390         $this->assertContains('Message 4', $message4->text);
2392         // Confirm the members data is correct.
2393         $members = $convmessages['members'];
2394         $this->assertEquals(3, count($members));
2396         // Retrieve the messages from $time + 3, which should only be the 2 last messages.
2397         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2398             'timecreated ASC', $time + 3);
2400         // Confirm the conversation id is correct.
2401         $this->assertEquals($conversation->id, $convmessages['id']);
2403         // Confirm the message data is correct.
2404         $messages = $convmessages['messages'];
2405         $this->assertEquals(2, count($messages));
2407         $message1 = $messages[0];
2408         $message2 = $messages[1];
2410         $this->assertContains('Message 3', $message1->text);
2411         $this->assertContains('Message 4', $message2->text);
2413         // Confirm the members data is correct.
2414         $members = $convmessages['members'];
2415         $this->assertEquals(2, count($members));
2416     }
2418     /**
2419      * Test retrieving conversation messages by providing a maximum timecreated value.
2420      */
2421     public function test_get_conversation_messages_time_to_only() {
2422         // Create some users.
2423         $user1 = self::getDataGenerator()->create_user();
2424         $user2 = self::getDataGenerator()->create_user();
2425         $user3 = self::getDataGenerator()->create_user();
2426         $user4 = self::getDataGenerator()->create_user();
2428         // Create group conversation.
2429         $conversation = \core_message\api::create_conversation(
2430             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2431             [$user1->id, $user2->id, $user3->id, $user4->id]
2432         );
2434         // The person doing the search.
2435         $this->setUser($user1);
2437         // Send some messages back and forth.
2438         $time = 1;
2439         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2440         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2441         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2442         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2444         // Retrieve the messages up until $time + 4, which should be all of them.
2445         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2446             0, $time + 4);
2448         // Confirm the conversation id is correct.
2449         $this->assertEquals($conversation->id, $convmessages['id']);
2451         // Confirm the message data is correct.
2452         $messages = $convmessages['messages'];
2453         $this->assertEquals(4, count($messages));
2455         $message1 = $messages[0];
2456         $message2 = $messages[1];
2457         $message3 = $messages[2];
2458         $message4 = $messages[3];
2460         $this->assertContains('Message 1', $message1->text);
2461         $this->assertContains('Message 2', $message2->text);
2462         $this->assertContains('Message 3', $message3->text);
2463         $this->assertContains('Message 4', $message4->text);
2465         // Confirm the members data is correct.
2466         $members = $convmessages['members'];
2467         $this->assertEquals(3, count($members));
2469         // Retrieve the messages up until $time + 2, which should be the first two.
2470         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2471             0, $time + 2);
2473         // Confirm the conversation id is correct.
2474         $this->assertEquals($conversation->id, $convmessages['id']);
2476         // Confirm the message data is correct.
2477         $messages = $convmessages['messages'];
2478         $this->assertEquals(2, count($messages));
2480         $message1 = $messages[0];
2481         $message2 = $messages[1];
2483         $this->assertContains('Message 1', $message1->text);
2484         $this->assertContains('Message 2', $message2->text);
2486         // Confirm the members data is correct.
2487         $members = $convmessages['members'];
2488         $this->assertEquals(2, count($members));
2489     }
2491     /**
2492      * Test retrieving conversation messages by providing a minimum and maximum timecreated value.
2493      */
2494     public function test_get_conversation_messages_time_from_and_to() {
2495         // Create some users.
2496         $user1 = self::getDataGenerator()->create_user();
2497         $user2 = self::getDataGenerator()->create_user();
2498         $user3 = self::getDataGenerator()->create_user();
2499         $user4 = self::getDataGenerator()->create_user();
2501         // Create group conversation.
2502         $conversation = \core_message\api::create_conversation(
2503             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2504             [$user1->id, $user2->id, $user3->id, $user4->id]
2505         );
2507         // The person doing the search.
2508         $this->setUser($user1);
2510         // Send some messages back and forth.
2511         $time = 1;
2512         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2513         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2514         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2515         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2517         // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
2518         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2519             'timecreated ASC', $time + 2, $time + 3);
2521         // Confirm the conversation id is correct.
2522         $this->assertEquals($conversation->id, $convmessages['id']);
2524         // Confirm the message data is correct.
2525         $messages = $convmessages['messages'];
2526         $this->assertEquals(2, count($messages));
2528         $message1 = $messages[0];
2529         $message2 = $messages[1];
2531         $this->assertContains('Message 2', $message1->text);
2532         $this->assertContains('Message 3', $message2->text);
2534         // Confirm the members data is correct.
2535         $members = $convmessages['members'];
2536         $this->assertEquals(2, count($members));
2537     }
2540     /**
2541      * Test retrieving conversation messages by providing a limitfrom value.
2542      */
2543     public function test_get_conversation_messages_limitfrom_only() {
2544         // Create some users.
2545         $user1 = self::getDataGenerator()->create_user();
2546         $user2 = self::getDataGenerator()->create_user();
2547         $user3 = self::getDataGenerator()->create_user();
2548         $user4 = self::getDataGenerator()->create_user();
2550         // Create group conversation.
2551         $conversation = \core_message\api::create_conversation(
2552             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2553             [$user1->id, $user2->id, $user3->id, $user4->id]
2554         );
2556         // The person doing the search.
2557         $this->setUser($user1);
2559         // Send some messages back and forth.
2560         $time = 1;
2561         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2562         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2563         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2564         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2566         // Retrieve the messages from $time, which should be all of them.
2567         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2);
2569         // Confirm the conversation id is correct.
2570         $messages = $convmessages['messages'];
2571         $this->assertEquals($conversation->id, $convmessages['id']);
2573         // Confirm the message data is correct.
2574         $this->assertEquals(2, count($messages));
2576         $message1 = $messages[0];
2577         $message2 = $messages[1];
2579         $this->assertContains('Message 3', $message1->text);
2580         $this->assertContains('Message 4', $message2->text);
2582         // Confirm the members data is correct.
2583         $members = $convmessages['members'];
2584         $this->assertEquals(2, count($members));
2585     }
2587     /**
2588      * Test retrieving conversation messages by providing a limitnum value.
2589      */
2590     public function test_get_conversation_messages_limitnum() {
2591         // Create some users.
2592         $user1 = self::getDataGenerator()->create_user();
2593         $user2 = self::getDataGenerator()->create_user();
2594         $user3 = self::getDataGenerator()->create_user();
2595         $user4 = self::getDataGenerator()->create_user();
2597         // Create group conversation.
2598         $conversation = \core_message\api::create_conversation(
2599             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2600             [$user1->id, $user2->id, $user3->id, $user4->id]
2601         );
2603         // The person doing the search.
2604         $this->setUser($user1);
2606         // Send some messages back and forth.
2607         $time = 1;
2608         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2609         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2610         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2611         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2613         // Retrieve the messages from $time, which should be all of them.
2614         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2, 1);
2616         // Confirm the conversation id is correct.
2617         $messages = $convmessages['messages'];
2618         $this->assertEquals($conversation->id, $convmessages['id']);
2620         // Confirm the message data is correct.
2621         $messages = $convmessages['messages'];
2622         $this->assertEquals(1, count($messages));
2624         $message1 = $messages[0];
2626         $this->assertContains('Message 3', $message1->text);
2628         // Confirm the members data is correct.
2629         $members = $convmessages['members'];
2630         $this->assertEquals(1, count($members));
2631     }
2633     /**
2634      * Tests retrieving most recent message.
2635      */
2636     public function test_get_most_recent_message() {
2637         // Create some users.
2638         $user1 = self::getDataGenerator()->create_user();
2639         $user2 = self::getDataGenerator()->create_user();
2641         // The person doing the search.
2642         $this->setUser($user1);
2644         // Send some messages back and forth.
2645         $time = 1;
2646         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2647         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2648         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2649         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2651         // Retrieve the most recent messages.
2652         $message = \core_message\api::get_most_recent_message($user1->id, $user2->id);
2654         // Check the results are correct.
2655         $this->assertEquals($user2->id, $message->useridfrom);
2656         $this->assertEquals($user1->id, $message->useridto);
2657         $this->assertContains('Word.', $message->text);
2658     }
2660     /**
2661      * Tests retrieving most recent conversation message.
2662      */
2663     public function test_get_most_recent_conversation_message() {
2664         // Create some users.
2665         $user1 = self::getDataGenerator()->create_user();
2666         $user2 = self::getDataGenerator()->create_user();
2667         $user3 = self::getDataGenerator()->create_user();
2669         // Create group conversation.
2670         $conversation = \core_message\api::create_conversation(
2671             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2672             [$user1->id, $user2->id, $user3->id]
2673         );
2675         // The person getting the most recent conversation message.
2676         $this->setUser($user1);
2678         // Send some messages back and forth.
2679         $time = 1;
2680         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2681         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2682         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2683         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Word.', $time + 4);
2685         // Retrieve the most recent messages.
2686         $message = \core_message\api::get_most_recent_conversation_message($conversation->id, $user1->id);
2688         // Check the results are correct.
2689         $this->assertEquals($user2->id, $message->useridfrom);
2690         $this->assertContains('Word.', $message->text);
2691     }
2693     /**
2694      * Tests retrieving a user's profile.
2695      */
2696     public function test_get_profile() {
2697         // Create some users.
2698         $user1 = self::getDataGenerator()->create_user();
2700         $user2 = new stdClass();
2701         $user2->country = 'AU';
2702         $user2->city = 'Perth';
2703         $user2 = self::getDataGenerator()->create_user($user2);
2705         // The person doing the search.
2706         $this->setUser($user1);
2708         // Get the profile.
2709         $profile = \core_message\api::get_profile($user1->id, $user2->id);
2711         $this->assertEquals($user2->id, $profile->userid);
2712         $this->assertEmpty($profile->email);
2713         $this->assertEmpty($profile->country);
2714         $this->assertEmpty($profile->city);
2715         $this->assertEquals(fullname($user2), $profile->fullname);
2716         $this->assertNull($profile->isonline);
2717         $this->assertFalse($profile->isblocked);
2718         $this->assertFalse($profile->iscontact);
2719     }
2721     /**
2722      * Tests retrieving a user's profile.
2723      */
2724     public function test_get_profile_as_admin() {
2725         // The person doing the search.
2726         $this->setAdminUser();
2728         // Create some users.
2729         $user1 = self::getDataGenerator()->create_user();
2731         $user2 = new stdClass();
2732         $user2->country = 'AU';
2733         $user2->city = 'Perth';
2734         $user2 = self::getDataGenerator()->create_user($user2);
2736         // Get the profile.
2737         $profile = \core_message\api::get_profile($user1->id, $user2->id);
2739         $this->assertEquals($user2->id, $profile->userid);
2740         $this->assertEquals($user2->email, $profile->email);
2741         $this->assertEquals($user2->country, $profile->country);
2742         $this->assertEquals($user2->city, $profile->city);
2743         $this->assertEquals(fullname($user2), $profile->fullname);
2744         $this->assertFalse($profile->isonline);
2745         $this->assertFalse($profile->isblocked);
2746         $this->assertFalse($profile->iscontact);
2747     }
2749     /**
2750      * Tests checking if a user can mark all messages as read.
2751      */
2752     public function test_can_mark_all_messages_as_read() {
2753         // Set as the admin.
2754         $this->setAdminUser();
2756         // Create some users.
2757         $user1 = self::getDataGenerator()->create_user();
2758         $user2 = self::getDataGenerator()->create_user();
2759         $user3 = self::getDataGenerator()->create_user();
2761         // Send some messages back and forth.
2762         $time = 1;
2763         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2764         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2765         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2766         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2768         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2770         // The admin can do anything.
2771         $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
2773         // Set as the user 1.
2774         $this->setUser($user1);
2776         // The user can mark the messages as he is in the conversation.
2777         $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
2779         // User 1 can not mark the messages read for user 2.
2780         $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user2->id, $conversationid));
2782         // This user is not a part of the conversation.
2783         $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user3->id, $conversationid));
2784     }
2786     /**
2787      * Tests checking if a user can delete a conversation.
2788      */
2789     public function test_can_delete_conversation() {
2790         // Set as the admin.
2791         $this->setAdminUser();
2793         // Create some users.
2794         $user1 = self::getDataGenerator()->create_user();
2795         $user2 = self::getDataGenerator()->create_user();
2797         // Send some messages back and forth.
2798         $time = 1;
2799         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2800         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2801         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2802         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2804         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2806         // The admin can do anything.
2807         $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
2809         // Set as the user 1.
2810         $this->setUser($user1);
2812         // They can delete their own messages.
2813         $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
2815         // They can't delete someone elses.
2816         $this->assertFalse(\core_message\api::can_delete_conversation($user2->id, $conversationid));
2817     }
2819     /**
2820      * Tests deleting a conversation.
2821      */
2822     public function test_delete_conversation() {
2823         global $DB;
2825         // Create some users.
2826         $user1 = self::getDataGenerator()->create_user();
2827         $user2 = self::getDataGenerator()->create_user();
2829         // The person doing the search.
2830         $this->setUser($user1);
2832         // Send some messages back and forth.
2833         $time = 1;
2834         $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2835         $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2836         $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2837         $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2839         // Delete the conversation as user 1.
2840         \core_message\api::delete_conversation($user1->id, $user2->id);
2841         $this->assertDebuggingCalled();
2843         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2844         $this->assertCount(4, $muas);
2845         // Sort by id.
2846         ksort($muas);
2848         $mua1 = array_shift($muas);
2849         $mua2 = array_shift($muas);
2850         $mua3 = array_shift($muas);
2851         $mua4 = array_shift($muas);
2853         $this->assertEquals($user1->id, $mua1->userid);
2854         $this->assertEquals($m1id, $mua1->messageid);
2855         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
2857         $this->assertEquals($user1->id, $mua2->userid);
2858         $this->assertEquals($m2id, $mua2->messageid);
2859         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
2861         $this->assertEquals($user1->id, $mua3->userid);
2862         $this->assertEquals($m3id, $mua3->messageid);
2863         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
2865         $this->assertEquals($user1->id, $mua4->userid);
2866         $this->assertEquals($m4id, $mua4->messageid);
2867         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
2868     }
2870     /**
2871      * Tests deleting a conversation by conversation id.
2872      */
2873     public function test_delete_conversation_by_id() {
2874         global $DB;
2876         // Create some users.
2877         $user1 = self::getDataGenerator()->create_user();
2878         $user2 = self::getDataGenerator()->create_user();
2880         // The person doing the search.
2881         $this->setUser($user1);
2883         // Send some messages back and forth.
2884         $time = 1;
2885         $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2886         $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2887         $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2888         $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2890         // Delete the conversation as user 1.
2891         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2892         \core_message\api::delete_conversation_by_id($user1->id, $conversationid);
2894         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2895         $this->assertCount(4, $muas);
2896         // Sort by id.
2897         ksort($muas);
2899         $mua1 = array_shift($muas);
2900         $mua2 = array_shift($muas);
2901         $mua3 = array_shift($muas);
2902         $mua4 = array_shift($muas);
2904         $this->assertEquals($user1->id, $mua1->userid);
2905         $this->assertEquals($m1id, $mua1->messageid);
2906         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
2908         $this->assertEquals($user1->id, $mua2->userid);
2909         $this->assertEquals($m2id, $mua2->messageid);
2910         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
2912         $this->assertEquals($user1->id, $mua3->userid);
2913         $this->assertEquals($m3id, $mua3->messageid);
2914         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
2916         $this->assertEquals($user1->id, $mua4->userid);
2917         $this->assertEquals($m4id, $mua4->messageid);
2918         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
2919     }
2921     /**
2922      * Tests counting unread conversations.
2923      */
2924     public function test_count_unread_conversations() {
2925         $this->resetAfterTest(true);
2927         // Create some users.
2928         $user1 = self::getDataGenerator()->create_user();
2929         $user2 = self::getDataGenerator()->create_user();
2930         $user3 = self::getDataGenerator()->create_user();
2931         $user4 = self::getDataGenerator()->create_user();
2933         // The person wanting the conversation count.
2934         $this->setUser($user1);
2936         // Send some messages back and forth, have some different conversations with different users.
2937         $this->send_fake_message($user1, $user2, 'Yo!');
2938         $this->send_fake_message($user2, $user1, 'Sup mang?');
2939         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
2940         $this->send_fake_message($user2, $user1, 'Word.');
2942         $this->send_fake_message($user1, $user3, 'Booyah');
2943         $this->send_fake_message($user3, $user1, 'Whaaat?');
2944         $this->send_fake_message($user1, $user3, 'Nothing.');
2945         $this->send_fake_message($user3, $user1, 'Cool.');
2947         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
2948         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
2949         $this->send_fake_message($user1, $user4, 'Dope.');
2951         // Check the amount for the current user.
2952         $this->assertEquals(3, core_message\api::count_unread_conversations());
2954         // Check the amount for the second user.
2955         $this->assertEquals(1, core_message\api::count_unread_conversations($user2));
2956     }
2958     /**
2959      * Tests deleting a conversation.
2960      */
2961     public function test_get_all_message_preferences() {
2962         $user = self::getDataGenerator()->create_user();
2963         $this->setUser($user);
2965         // Set a couple of preferences to test.
2966         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
2967         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
2969         $processors = get_message_processors();
2970         $providers = message_get_providers_for_user($user->id);
2971         $prefs = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2973         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedin['popup']);
2974         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedoff['email']);
2975     }
2977     /**
2978      * Tests the user can post a message.
2979      */
2980     public function test_can_post_message() {
2981         // Create some users.
2982         $user1 = self::getDataGenerator()->create_user();
2983         $user2 = self::getDataGenerator()->create_user();
2985         // Set as the first user.
2986         $this->setUser($user1);
2988         // With the default privacy setting, users can't message them.
2989         $this->assertFalse(\core_message\api::can_post_message($user2));
2991         // Enrol users to the same course.
2992         $course = $this->getDataGenerator()->create_course();
2993         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
2994         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
2995         // After enrolling users to the course, they should be able to message them with the default privacy setting.
2996         $this->assertTrue(\core_message\api::can_post_message($user2));
2997     }
2999     /**
3000      * Tests the user can't post a message without proper capability.
3001      */
3002     public function test_can_post_message_without_sendmessage_cap() {
3003         global $DB;
3005         // Create some users.
3006         $user1 = self::getDataGenerator()->create_user();
3007         $user2 = self::getDataGenerator()->create_user();
3009         // Set as the user 1.
3010         $this->setUser($user1);
3012         // Remove the capability to send a message.
3013         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3014         unassign_capability('moodle/site:sendmessage', $roleids['user'],
3015             context_system::instance());
3017         // Check that we can not post a message without the capability.
3018         $this->assertFalse(\core_message\api::can_post_message($user2));
3019     }
3021     /**
3022      * Tests the user can post a message when they are contact.
3023      */
3024     public function test_can_post_message_when_contact() {
3025         // Create some users.
3026         $user1 = self::getDataGenerator()->create_user();
3027         $user2 = self::getDataGenerator()->create_user();
3029         // Set as the first user.
3030         $this->setUser($user1);
3032         // Check that we can not send user2 a message.
3033         $this->assertFalse(\core_message\api::can_post_message($user2));
3035         // Add users as contacts.
3036         \core_message\api::add_contact($user1->id, $user2->id);
3038         // Check that the return result is now true.
3039         $this->assertTrue(\core_message\api::can_post_message($user2));
3040     }
3042     /**
3043      * Tests the user can't post a message if they are not a contact and the user
3044      * has requested messages only from contacts.
3045      */
3046     public function test_can_post_message_when_not_contact() {
3047         // Create some users.
3048         $user1 = self::getDataGenerator()->create_user();
3049         $user2 = self::getDataGenerator()->create_user();
3051         // Set as the first user.
3052         $this->setUser($user1);
3054         // Set the second user's preference to not receive messages from non-contacts.
3055         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3057         // Check that we can not send user 2 a message.
3058         $this->assertFalse(\core_message\api::can_post_message($user2));
3059     }
3061     /**
3062      * Tests the user can't post a message if they are blocked.
3063      */
3064     public function test_can_post_message_when_blocked() {
3065         // Create some users.
3066         $user1 = self::getDataGenerator()->create_user();
3067         $user2 = self::getDataGenerator()->create_user();
3069         // Set the user.
3070         $this->setUser($user1);
3072         // Block the second user.
3073         \core_message\api::block_user($user1->id, $user2->id);
3075         // Check that the second user can no longer send the first user a message.
3076         $this->assertFalse(\core_message\api::can_post_message($user1, $user2));
3077     }
3079     /**
3080      * Tests the user can post a message when site-wide messaging setting is enabled,
3081      * even if they are not a contact and are not members of the same course.
3082      */
3083     public function test_can_post_message_site_messaging_setting() {
3084         // Create some users.
3085         $user1 = self::getDataGenerator()->create_user();
3086         $user2 = self::getDataGenerator()->create_user();
3088         // Set as the first user.
3089         $this->setUser($user1);
3091         // By default, user only can be messaged by contacts and members of any of his/her courses.
3092         $this->assertFalse(\core_message\api::can_post_message($user2));
3094         // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
3095         set_config('messagingallusers', true);
3097         // Set the second user's preference to receive messages from everybody.
3098         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
3100         // Check that we can send user2 a message.
3101         $this->assertTrue(\core_message\api::can_post_message($user2));
3103         // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
3104         // and members sharing a course with her.
3105         set_config('messagingallusers', false);
3107         // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
3108         $this->assertFalse(\core_message\api::can_post_message($user2));
3110         // Enrol users to the same course.
3111         $course = $this->getDataGenerator()->create_course();
3112         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3113         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3114         // Check that we can send user2 a message because they are sharing a course.
3115         $this->assertTrue(\core_message\api::can_post_message($user2));
3117         // Set the second user's preference to receive messages only from contacts.
3118         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3119         // Check that now the user2 can't be contacted because user1 is not their contact.
3120         $this->assertFalse(\core_message\api::can_post_message($user2));
3122         // Make contacts user1 and user2.
3123         \core_message\api::add_contact($user2->id, $user1->id);
3124         // Check that we can send user2 a message because they are contacts.
3125         $this->assertTrue(\core_message\api::can_post_message($user2));
3126     }
3128     /**
3129      * Tests the user with the messageanyuser capability can post a message.
3130      */
3131     public function test_can_post_message_with_messageanyuser_cap() {
3132         global $DB;
3134         // Create some users.
3135         $teacher1 = self::getDataGenerator()->create_user();
3136         $student1 = self::getDataGenerator()->create_user();
3137         $student2 = self::getDataGenerator()->create_user();
3139         // Create users not enrolled in any course.
3140         $user1 = self::getDataGenerator()->create_user();
3142         // Create a course.
3143         $course1 = $this->getDataGenerator()->create_course();
3145         // Enrol the users in the course.
3146         $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher');
3147         $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student');
3148         $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student');
3150         // Set some student preferences to not receive messages from non-contacts.
3151         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $student1->id);
3153         // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
3154         $this->assertTrue(\core_message\api::can_post_message($student1, $teacher1));
3155         // Check that the teacher can't contact user1 because it's not his teacher.
3156         $this->assertFalse(\core_message\api::can_post_message($user1, $teacher1));
3158         // Remove the messageanyuser capability from the course1 for teachers.
3159         $coursecontext = context_course::instance($course1->id);
3160         $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
3161         assign_capability('moodle/site:messageanyuser', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
3162         $coursecontext->mark_dirty();
3164         // Check that we can't send user1 a message because they are not contacts.
3165         $this->assertFalse(\core_message\api::can_post_message($student1, $teacher1));
3166         // However, teacher can message student2 because they are sharing a course.
3167         $this->assertTrue(\core_message\api::can_post_message($student2, $teacher1));
3168     }
3170     /**
3171      * Verify the expected behaviour of the can_send_message_to_conversation() method for authenticated users with default settings.
3172      */
3173     public function test_can_send_message_to_conversation_basic() {
3174         // Create some users.
3175         $user1 = self::getDataGenerator()->create_user();
3176         $user2 = self::getDataGenerator()->create_user();
3177         $user3 = self::getDataGenerator()->create_user();
3179         // Create an individual conversation between user1 and user2.
3180         $ic1 = \core_message\api::create_conversation(
3181             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3182             [
3183                 $user1->id,
3184                 $user2->id
3185             ]
3186         );
3188         // Create a group conversation between and users 1, 2 and 3.
3189         $gc1 = \core_message\api::create_conversation(
3190             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3191             [
3192                 $user1->id,
3193                 $user2->id,
3194                 $user3->id
3195             ]
3196         );
3198         // For group conversations, there are no user privacy checks, so only membership in the conversation is needed.
3199         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3201         // For individual conversations, the default privacy setting of 'only contacts and course members' applies.
3202         // Users are not in the same course, nor are they contacts, so messages cannot be sent.
3203         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3205         // Enrol the users into the same course.
3206         $course = $this->getDataGenerator()->create_course();
3207         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3208         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3210         // After enrolling users to the course, they should be able to message them with the default privacy setting.
3211         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3212     }
3214     /**
3215      * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the sendmessage capability.
3216      */
3217     public function test_can_send_message_to_conversation_sendmessage_cap() {
3218         global $DB;
3220         $user1 = self::getDataGenerator()->create_user();
3221         $user2 = self::getDataGenerator()->create_user();
3222         $user3 = self::getDataGenerator()->create_user();
3224         // Enrol the users into the same course.
3225         $course = $this->getDataGenerator()->create_course();
3226         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3227         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3228         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3230         // Create an individual conversation between user1 and user2.
3231         $ic1 = \core_message\api::create_conversation(
3232             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3233             [
3234                 $user1->id,
3235                 $user2->id
3236             ]
3237         );
3239         // Group conversation between and users 1, 2 and 3.
3240         $gc1 = \core_message\api::create_conversation(
3241             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3242             [
3243                 $user1->id,
3244                 $user2->id,
3245                 $user3->id
3246             ]
3247         );
3249         // Default settings - user1 can send a message to both conversations.
3250         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3251         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3253         // Remove the capability to send a message.
3254         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3255         unassign_capability('moodle/site:sendmessage', $roleids['user'], context_system::instance());
3257         // Verify that a user cannot send a message to either an individual or a group conversation.
3258         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3259         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3260     }
3262     /**
3263      * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the messageanyuser capability.
3264      */
3265     public function test_can_send_message_to_conversation_messageanyuser_cap() {
3266         global $DB;
3268         $user1 = self::getDataGenerator()->create_user();
3269         $user2 = self::getDataGenerator()->create_user();
3270         $user3 = self::getDataGenerator()->create_user();
3272         // Enrol the users into the same course.
3273         $course = $this->getDataGenerator()->create_course();
3274         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3275         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3276         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3278         // Create an individual conversation between user1 and user2.
3279         $ic1 = \core_message\api::create_conversation(
3280             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3281             [
3282                 $user1->id,
3283                 $user2->id
3284             ]
3285         );
3287         // Group conversation between and users 1, 2 and 3.
3288         $gc1 = \core_message\api::create_conversation(
3289             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3290             [
3291                 $user1->id,
3292                 $user2->id,
3293                 $user3->id
3294             ]
3295         );
3297         // Update the message preference for user2, so they can only be messaged by contacts.
3298         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3300         // Verify that the user cannot be contacted in the individual conversation and that groups are unaffected.
3301         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3302         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3304         // Assign the 'messageanyuser' capability to user1 at system context.
3305         $systemcontext = context_system::instance();
3306         $authenticateduser = $DB->get_record('role', ['shortname' => 'user']);
3307         assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, $systemcontext->id);
3309         // Check that user1 can now message user2 due to the capability, and that group conversations is again unaffected.
3310         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3311         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3312     }
3314     /**
3315      * Test verifying that users cannot send messages to conversations they are not a part of.
3316      */
3317     public function test_can_post_message_to_conversation_non_member() {
3318         // Create some users.
3319         $user1 = self::getDataGenerator()->create_user();
3320         $user2 = self::getDataGenerator()->create_user();
3321         $user3 = self::getDataGenerator()->create_user();
3322         $user4 = self::getDataGenerator()->create_user();
3324         // Enrol the users into the same course.
3325         $course = $this->getDataGenerator()->create_course();
3326         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3327         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3328         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3329         $this->getDataGenerator()->enrol_user($user4->id, $course->id);
3331         // Create an individual conversation between user1 and user2.
3332         $ic1 = \core_message\api::create_conversation(
3333             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3334             [
3335                 $user1->id,
3336                 $user2->id
3337             ]
3338         );
3340         // Create a group conversation between and users 1, 2 and 3.
3341         $gc1 = \core_message\api::create_conversation(
3342             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3343             [
3344                 $user1->id,
3345                 $user2->id,
3346                 $user3->id
3347             ]
3348         );
3350         // Verify, non members cannot send a message.
3351         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $gc1->id));
3352         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $ic1->id));
3353     }
3355     /**
3356      * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts only.
3357      */
3358     public function test_can_send_message_to_conversation_privacy_contacts_only() {
3359         // Create some users.
3360         $user1 = self::getDataGenerator()->create_user();
3361         $user2 = self::getDataGenerator()->create_user();
3362         $user3 = self::getDataGenerator()->create_user();
3364         // Create an individual conversation between user1 and user2.
3365         $ic1 = \core_message\api::create_conversation(
3366             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3367             [
3368                 $user1->id,
3369                 $user2->id
3370             ]
3371         );
3373         // Create a group conversation between and users 1, 2 and 3.
3374         $gc1 = \core_message\api::create_conversation(
3375             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3376             [
3377                 $user1->id,
3378                 $user2->id,
3379                 $user3->id
3380             ]
3381         );
3383         // Set the message privacy preference to 'contacts only' for user 2.
3384         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3386         // Verify that user1 cannot send a message to the individual conversation, but that the group conversation is unaffected.
3387         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3388         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3390         // Now, simulate a contact request (and approval) between user1 and user2.
3391         \core_message\api::create_contact_request($user1->id, $user2->id);
3392         \core_message\api::confirm_contact_request($user1->id, $user2->id);
3394         // Verify user1 can now message user2 again via their individual conversation.
3395         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3396     }
3398     /**
3399      * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts / course members.
3400      */
3401     public function test_can_send_message_to_conversation_privacy_contacts_course() {
3402         // Create some users.
3403         $user1 = self::getDataGenerator()->create_user();
3404         $user2 = self::getDataGenerator()->create_user();
3405         $user3 = self::getDataGenerator()->create_user();
3407         // Set the message privacy preference to 'contacts + course members' for user 2.
3408         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
3410         // Create an individual conversation between user1 and user2.
3411         $ic1 = \core_message\api::create_conversation(
3412             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3413             [
3414                 $user1->id,
3415                 $user2->id
3416             ]
3417         );
3419         // Create a group conversation between and users 1, 2 and 3.
3420         $gc1 = \core_message\api::create_conversation(
3421             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3422             [
3423                 $user1->id,
3424                 $user2->id,
3425                 $user3->id
3426             ]
3427         );
3429         // Verify that users in a group conversation can message one another (i.e. privacy controls ignored).
3430         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3432         // Verify that user1 can not message user2 unless they are either contacts, or share a course.
3433         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3435         // Enrol the users into the same course.
3436         $course = $this->getDataGenerator()->create_course();
3437         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3438         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3439         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3441         // Verify that user1 can send a message to user2, based on the shared course, without being a contact.
3442         $this->assertFalse(\core_message\api::is_contact($user1->id, $user2->id));
3443         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3444     }
3446     /**
3447      * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to any user.
3448      */
3449     public function test_can_send_message_to_conversation_privacy_sitewide() {
3450         // Create some users.
3451         $user1 = self::getDataGenerator()->create_user();
3452         $user2 = self::getDataGenerator()->create_user();
3453         $user3 = self::getDataGenerator()->create_user();
3455         // Create an individual conversation between user1 and user2.
3456         $ic1 = \core_message\api::create_conversation(
3457             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3458             [
3459                 $user1->id,
3460                 $user2->id
3461             ]
3462         );
3464         // Create a group conversation between and users 1, 2 and 3.
3465         $gc1 = \core_message\api::create_conversation(
3466             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3467             [
3468                 $user1->id,
3469                 $user2->id,
3470                 $user3->id
3471             ]
3472         );
3474         // By default, the messaging privacy dictates that users can only be contacted by contacts, and members of their courses.
3475         // Verify also, that groups are not restricted in this way.
3476         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3477         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3479         // Enable site-wide messagging privacy setting.
3480         // This enables a privacy option for users, allowing them to choose to be contactable by anybody on the site.
3481         set_config('messagingallusers', true);
3483         // Set the second user's preference to receive messages from everybody.
3484         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
3486         // Check that user1 can send user2 a message, and that the group conversation is unaffected.
3487         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3488         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3490         // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
3491         // and members sharing a course with her.
3492         set_config('messagingallusers', false);
3494         // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
3495         // Verify also that the group conversation is unaffected.
3496         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3497         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3498     }
3500     /**
3501      * Test verifying the behaviour of the can_send_message_to_conversation method when a user is blocked.
3502      */
3503     public function test_can_send_message_to_conversation_when_blocked() {
3504         $user1 = self::getDataGenerator()->create_user();
3505         $user2 = self::getDataGenerator()->create_user();
3506         $user3 = self::getDataGenerator()->create_user();
3508         // Create an individual conversation between user1 and user2.
3509         $ic1 = \core_message\api::create_conversation(
3510             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3511             [
3512                 $user1->id,
3513                 $user2->id
3514             ]
3515         );
3517         // Create a group conversation between and users 1, 2 and 3.
3518         $gc1 = \core_message\api::create_conversation(
3519             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3520             [
3521                 $user1->id,
3522                 $user2->id,
3523                 $user3->id
3524             ]
3525         );
3527         // Enrol the users into the same course.
3528         $course = $this->getDataGenerator()->create_course();
3529         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3530         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3531         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3533         // Block the second user.
3534         \core_message\api::block_user($user1->id, $user2->id);
3536         // Check that user2 can not send user1 a message in their individual conversation.
3537         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user2->id, $ic1->id));
3539         // Verify that group conversations are unaffected.
3540         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3541         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user2->id, $gc1->id));
3542     }
3544     /**
3545      * Tests get_user_privacy_messaging_preference method.
3546      */
3547     public function test_get_user_privacy_messaging_preference() {
3548         // Create some users.
3549         $user1 = self::getDataGenerator()->create_user();
3550         $user2 = self::getDataGenerator()->create_user();
3551         $user3 = self::getDataGenerator()->create_user();
3553         // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
3554         set_config('messagingallusers', true);
3556         // Set some user preferences.
3557         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user1->id);
3558         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3560         // Check the returned value for each user.
3561         $this->assertEquals(
3562             \core_message\api::MESSAGE_PRIVACY_SITE,
3563             \core_message\api::get_user_privacy_messaging_preference($user1->id)
3564         );
3565         $this->assertEquals(
3566             \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS,
3567             \core_message\api::get_user_privacy_messaging_preference($user2->id)
3568         );
3569         $this->assertEquals(
3570             \core_message\api::MESSAGE_PRIVACY_SITE,
3571             \core_message\api::get_user_privacy_messaging_preference($user3->id)
3572         );
3574         // Disable site-wide messagging privacy setting. The user will be able to receive messages from members of their course.
3575         set_config('messagingallusers', false);
3577         // Check the returned value for each user.
3578         $this->assertEquals(
3579             \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER,
3580             \core_message\api::get_user_privacy_messaging_preference($user1->id)
3581         );
3582         $this->assertEquals(
3583             \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS,
3584             \core_message\api::get_user_privacy_messaging_preference($user2->id)
3585         );
3586         $this->assertEquals(
3587             \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER,
3588             \core_message\api::get_user_privacy_messaging_preference($user3->id)
3589         );
3590     }
3592     /**
3593      * Tests that when blocking messages from non-contacts is enabled that
3594      * non-contacts trying to send a message return false.
3595      */
3596     public function test_is_user_non_contact_blocked() {
3597         // Create some users.
3598         $user1 = self::getDataGenerator()->create_user();
3599         $user2 = self::getDataGenerator()->create_user();
3601         // Set as the first user.
3602         $this->setUser($user1);
3604         // By default, user only can be messaged by contacts and members of any of his/her courses.
3605         $this->assertTrue(\core_message\api::is_user_non_contact_blocked($user2));
3606         $this->assertDebuggingCalled();
3608         // Enable all users privacy messaging and check now the default user's preference has been set to allow receiving
3609         // messages from everybody.
3610         set_config('messagingallusers', true);
3611         // Check that the return result is now false because any site user can contact him/her.
3612         $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
3613         $this->assertDebuggingCalled();
3615         // Set the second user's preference to not receive messages from non-contacts.
3616         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3617         // Check that the return result is still true (because is even more restricted).
3618         $this->assertTrue(\core_message\api::is_user_non_contact_blocked($user2));
3619         $this->assertDebuggingCalled();
3621         // Add the first user as a contact for the second user.
3622         \core_message\api::add_contact($user2->id, $user1->id);
3624         // Check that the return result is now false.
3625         $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
3626         $this->assertDebuggingCalled();
3628         // Set the second user's preference to receive messages from course members.
3629         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
3630         // Check that the return result is still false (because $user1 is still his/her contact).
3631         $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
3632         $this->assertDebuggingCalled();
3633     }
3635     /**
3636      * Tests that we return true when a user is blocked, or false
3637      * if they are not blocked.
3638      */
3639     public function test_is_user_blocked() {
3640         // Create some users.
3641         $user1 = self::getDataGenerator()->create_user();
3642         $user2 = self::getDataGenerator()->create_user();
3644         // Set the user.
3645         $this->setUser($user1);
3647         // User shouldn't be blocked.
3648         $this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
3649         $this->assertDebuggingCalled();
3651         // Block the user.
3652         \core_message\api::block_user($user1->id, $user2->id);
3654         // User should be blocked.
3655         $this->assertTrue(\core_message\api::is_user_blocked($user1->id, $user2->id));
3656         $this->assertDebuggingCalled();
3658         // Unblock the user.
3659         \core_message\api::unblock_user($user1->id, $user2->id);
3660         $this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
3661         $this->assertDebuggingCalled();
3662     }
3664     /**
3665      * Tests that the admin is not blocked even if someone has chosen to block them.
3666      */
3667     public function test_is_user_blocked_as_admin() {
3668         // Create a user.
3669         $user1 = self::getDataGenerator()->create_user();
3671         // Set the user.
3672         $this->setUser($user1);
3674         // Block the admin user.
3675         \core_message\api::block_user($user1->id, 2);
3677         // Now change to the admin user.
3678         $this->setAdminUser();
3680         // As the admin you should still be able to send messages to the user.
3681         $this->assertFalse(\core_message\api::is_user_blocked($user1->id));
3682         $this->assertDebuggingCalled();
3683     }
3685     /*
3686      * Tes get_message_processor api.
3687      */
3688     public function test_get_message_processor() {
3689         $processors = get_message_processors(true);
3690         if (empty($processors)) {
3691             $this->markTestSkipped("No message processors found");
3692         }
3694         $name = key($processors);
3695         $processor = current($processors);
3696         $testprocessor = \core_message\api::get_message_processor($name);
3697         $this->assertEquals($processor->name, $testprocessor->name);
3698         $this->assertEquals($processor->enabled, $testprocessor->enabled);
3699         $this->assertEquals($processor->available, $testprocessor->available);
3700         $this->assertEquals($processor->configured, $testprocessor->configured);
3702         // Disable processor and test.
3703         \core_message\api::update_processor_status($testprocessor, 0);
3704         $testprocessor = \core_message\api::get_message_processor($name, true);
3705         $this->assertEmpty($testprocessor);
3706         $testprocessor = \core_message\api::get_message_processor($name);
3707         $this->assertEquals($processor->name, $testprocessor->name);
3708         $this->assertEquals(0, $testprocessor->enabled);
3710         // Enable again and test.
3711         \core_message\api::update_processor_status($testprocessor, 1);
3712         $testprocessor = \core_message\api::get_message_processor($name, true);
3713         $this->assertEquals($processor->name, $testprocessor->name);
3714         $this->assertEquals(1, $testprocessor->enabled);
3715         $testprocessor = \core_message\api::get_message_processor($name);
3716         $this->assertEquals($processor->name, $testprocessor->name);
3717         $this->assertEquals(1, $testprocessor->enabled);
3718     }
3720     /**
3721      * Test method update_processor_status.
3722      */
3723     public function test_update_processor_status() {
3724         $processors = get_message_processors();
3725         if (empty($processors)) {
3726             $this->markTestSkipped("No message processors found");
3727         }
3728         $name = key($processors);
3729         $testprocessor = current($processors);
3731         // Enable.
3732         \core_message\api::update_processor_status($testprocessor, 1);
3733         $testprocessor = \core_message\api::get_message_processor($name);
3734         $this->assertEquals(1, $testprocessor->enabled);
3736         // Disable.
3737         \core_message\api::update_processor_status($testprocessor, 0);
3738         $testprocessor = \core_message\api::get_message_processor($name);
3739         $this->assertEquals(0, $testprocessor->enabled);
3741         // Enable again.
3742         \core_message\api::update_processor_status($testprocessor, 1);
3743         $testprocessor = \core_message\api::get_message_processor($name);
3744         $this->assertEquals(1, $testprocessor->enabled);
3745     }
3747     /**
3748      * Test method is_user_enabled.
3749      */
3750     public function is_user_enabled() {
3751         $processors = get_message_processors();
3752         if (empty($processors)) {
3753             $this->markTestSkipped("No message processors found");
3754         }
3755         $name = key($processors);
3756         $testprocessor = current($processors);
3758         // Enable.
3759         \core_message\api::update_processor_status($testprocessor, 1);
3760         $status = \core_message\api::is_processor_enabled($name);
3761         $this->assertEquals(1, $status);
3763         // Disable.
3764         \core_message\api::update_processor_status($testprocessor, 0);
3765         $status = \core_message\api::is_processor_enabled($name);
3766         $this->assertEquals(0, $status);
3768         // Enable again.
3769         \core_message\api::update_processor_status($testprocessor, 1);
3770         $status = \core_message\api::is_processor_enabled($name);
3771         $this->assertEquals(1, $status);
3772     }
3774     /**
3775      * Test retrieving messages by providing a minimum timecreated value.
3776      */
3777     public function test_get_messages_time_from_only() {
3778         // Create some users.
3779         $user1 = self::getDataGenerator()->create_user();
3780         $user2 = self::getDataGenerator()->create_user();
3782         // The person doing the search.
3783         $this->setUser($user1);
3785         // Send some messages back and forth.
3786         $time = 1;
3787         $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
3788         $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
3789         $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
3790         $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
3792         // Retrieve the messages from $time, which should be all of them.
3793         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time);
3795         // Confirm the message data is correct.
3796         $this->assertEquals(4, count($messages));
3798         $message1 = $messages[0];
3799         $message2 = $messages[1];
3800         $message3 = $messages[2];
3801         $message4 = $messages[3];
3803         $this->assertContains('Message 1', $message1->text);
3804         $this->assertContains('Message 2', $message2->text);
3805         $this->assertContains('Message 3', $message3->text);
3806         $this->assertContains('Message 4', $message4->text);
3808         // Retrieve the messages from $time + 3, which should only be the 2 last messages.
3809         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 3);
3811         // Confirm the message data is correct.
3812         $this->assertEquals(2, count($messages));
3814         $message1 = $messages[0];
3815         $message2 = $messages[1];
3817         $this->assertContains('Message 3', $message1->text);
3818         $this->assertContains('Message 4', $message2->text);
3819     }
3821     /**
3822      * Test retrieving messages by providing a maximum timecreated value.
3823      */
3824     public function test_get_messages_time_to_only() {
3825         // Create some users.
3826         $user1 = self::getDataGenerator()->create_user();
3827         $user2 = self::getDataGenerator()->create_user();
3829         // The person doing the search.
3830         $this->setUser($user1);
3832         // Send some messages back and forth.
3833         $time = 1;
3834         $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
3835         $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
3836         $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
3837         $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
3839         // Retrieve the messages up until $time + 4, which should be all of them.
3840         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 4);
3842         // Confirm the message data is correct.
3843         $this->assertEquals(4, count($messages));