Merge branch 'MDL-63716-master' of git://github.com/damyon/moodle
[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 users.
311      */
312     public function test_message_search_users() {
313         // Create some users.
314         $user1 = new stdClass();
315         $user1->firstname = 'User search';
316         $user1->lastname = 'One';
317         $user1 = self::getDataGenerator()->create_user($user1);
319         // Set as the user performing the search.
320         $this->setUser($user1);
322         $user2 = new stdClass();
323         $user2->firstname = 'User search';
324         $user2->lastname = 'Two';
325         $user2 = self::getDataGenerator()->create_user($user2);
327         $user3 = new stdClass();
328         $user3->firstname = 'User search';
329         $user3->lastname = 'Three';
330         $user3 = self::getDataGenerator()->create_user($user3);
332         $user4 = new stdClass();
333         $user4->firstname = 'User';
334         $user4->lastname = 'Four';
335         $user4 = self::getDataGenerator()->create_user($user4);
337         $user5 = new stdClass();
338         $user5->firstname = 'User search';
339         $user5->lastname = 'Five';
340         $user5 = self::getDataGenerator()->create_user($user5);
342         $user6 = new stdClass();
343         $user6->firstname = 'User search';
344         $user6->lastname = 'Six';
345         $user6 = self::getDataGenerator()->create_user($user6);
347         $user7 = new stdClass();
348         $user7->firstname = 'User search';
349         $user7->lastname = 'Seven';
350         $user7 = self::getDataGenerator()->create_user($user7);
352         // Add some users as contacts.
353         \core_message\api::add_contact($user1->id, $user2->id);
354         \core_message\api::add_contact($user3->id, $user1->id);
355         \core_message\api::add_contact($user1->id, $user4->id);
357         // Create private conversations with some users.
358         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
359             array($user1->id, $user6->id));
360         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
361             array($user7->id, $user1->id));
363         // Perform a search $CFG->messagingallusers setting enabled.
364         set_config('messagingallusers', 1);
365         list($contacts, $noncontacts) = \core_message\api::message_search_users($user1->id, 'search');
367         // Check that we retrieved the correct contacts.
368         $this->assertCount(2, $contacts);
369         $this->assertEquals($user3->id, $contacts[0]->id);
370         $this->assertEquals($user2->id, $contacts[1]->id);
372         // Check that we retrieved the correct non-contacts.
373         $this->assertCount(3, $noncontacts);
374         $this->assertEquals($user5->id, $noncontacts[0]->id);
375         $this->assertEquals($user7->id, $noncontacts[1]->id);
376         $this->assertEquals($user6->id, $noncontacts[2]->id);
378         // Perform a search $CFG->messagingallusers setting disabled.
379         set_config('messagingallusers', 0);
380         list($contacts, $noncontacts) = \core_message\api::message_search_users($user1->id, 'search');
382         // Check that we retrieved the correct contacts.
383         $this->assertCount(2, $contacts);
384         $this->assertEquals($user3->id, $contacts[0]->id);
385         $this->assertEquals($user2->id, $contacts[1]->id);
387         // Check that we retrieved the correct non-contacts.
388         $this->assertCount(2, $noncontacts);
389         $this->assertEquals($user7->id, $noncontacts[0]->id);
390         $this->assertEquals($user6->id, $noncontacts[1]->id);
391     }
393     /**
394      * Tests getting conversations between 2 users.
395      */
396     public function test_get_conversations_between_users() {
397         // Create some users.
398         $user1 = new stdClass();
399         $user1->firstname = 'User';
400         $user1->lastname = 'One';
401         $user1 = self::getDataGenerator()->create_user($user1);
403         $user2 = new stdClass();
404         $user2->firstname = 'User';
405         $user2->lastname = 'Two';
406         $user2 = self::getDataGenerator()->create_user($user2);
408         $user3 = new stdClass();
409         $user3->firstname = 'User search';
410         $user3->lastname = 'Three';
411         $user3 = self::getDataGenerator()->create_user($user3);
413         $user4 = new stdClass();
414         $user4->firstname = 'User';
415         $user4->lastname = 'Four';
416         $user4 = self::getDataGenerator()->create_user($user4);
418         $user5 = new stdClass();
419         $user5->firstname = 'User';
420         $user5->lastname = 'Five';
421         $user5 = self::getDataGenerator()->create_user($user5);
423         $user6 = new stdClass();
424         $user6->firstname = 'User search';
425         $user6->lastname = 'Six';
426         $user6 = self::getDataGenerator()->create_user($user6);
428         // Add some users as contacts.
429         \core_message\api::add_contact($user1->id, $user2->id);
430         \core_message\api::add_contact($user6->id, $user1->id);
432         // Create private conversations with some users.
433         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
434             array($user1->id, $user2->id));
435         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
436             array($user3->id, $user1->id));
438         // Create a group conversation with users.
439         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
440             array($user1->id, $user2->id, $user3->id, $user4->id),
441             'Project chat');
443         // Check that we retrieved the correct conversations.
444         $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user2->id));
445         $this->assertCount(2, \core_message\api::get_conversations_between_users($user2->id, $user1->id));
446         $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user3->id));
447         $this->assertCount(2, \core_message\api::get_conversations_between_users($user3->id, $user1->id));
448         $this->assertCount(1, \core_message\api::get_conversations_between_users($user1->id, $user4->id));
449         $this->assertCount(1, \core_message\api::get_conversations_between_users($user4->id, $user1->id));
450         $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user5->id));
451         $this->assertCount(0, \core_message\api::get_conversations_between_users($user5->id, $user1->id));
452         $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user6->id));
453         $this->assertCount(0, \core_message\api::get_conversations_between_users($user6->id, $user1->id));
454     }
456     /**
457      * Tests searching users with and without conversations.
458      */
459     public function test_message_search_users_with_and_without_conversations() {
460         // Create some users.
461         $user1 = new stdClass();
462         $user1->firstname = 'User search';
463         $user1->lastname = 'One';
464         $user1 = self::getDataGenerator()->create_user($user1);
466         // Set as the user performing the search.
467         $this->setUser($user1);
469         $user2 = new stdClass();
470         $user2->firstname = 'User search';
471         $user2->lastname = 'Two';
472         $user2 = self::getDataGenerator()->create_user($user2);
474         $user3 = new stdClass();
475         $user3->firstname = 'User search';
476         $user3->lastname = 'Three';
477         $user3 = self::getDataGenerator()->create_user($user3);
479         $user4 = new stdClass();
480         $user4->firstname = 'User';
481         $user4->lastname = 'Four';
482         $user4 = self::getDataGenerator()->create_user($user4);
484         $user5 = new stdClass();
485         $user5->firstname = 'User search';
486         $user5->lastname = 'Five';
487         $user5 = self::getDataGenerator()->create_user($user5);
489         // Add a user as contact.
490         \core_message\api::add_contact($user1->id, $user2->id);
492         // Create private conversations with some users.
493         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
494             array($user1->id, $user2->id));
495         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
496             array($user3->id, $user1->id));
498         // Create a group conversation with users.
499         \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
500             array($user1->id, $user2->id, $user4->id),
501             'Project chat');
503         // Perform a search $CFG->messagingallusers setting enabled.
504         set_config('messagingallusers', 1);
505         list($contacts, $noncontacts) = \core_message\api::message_search_users($user1->id, 'search');
507         // Check that we retrieved the correct contacts.
508         $this->assertCount(1, $contacts);
510         // Check that we retrieved the correct conversations for contacts.
511         $this->assertCount(2, $contacts[0]->conversations);
513         // Check that we retrieved the correct non-contacts.
514         $this->assertCount(2, $noncontacts);
515         $this->assertEquals($user5->id, $noncontacts[0]->id);
516         $this->assertEquals($user3->id, $noncontacts[1]->id);
518         // Check that we retrieved the correct conversations for non-contacts.
519         $this->assertCount(0, $noncontacts[0]->conversations);
520         $this->assertCount(1, $noncontacts[1]->conversations);
521     }
523     /**
524      * Tests searching users with empty result.
525      */
526     public function test_message_search_users_with_empty_result() {
528         // Create some users.
529         $user1 = new stdClass();
530         $user1->firstname = 'User';
531         $user1->lastname = 'One';
532         $user1 = self::getDataGenerator()->create_user($user1);
534         // Set as the user performing the search.
535         $this->setUser($user1);
537         $user2 = new stdClass();
538         $user2->firstname = 'User';
539         $user2->lastname = 'Two';
540         $user2 = self::getDataGenerator()->create_user($user2);
542         // Perform a search $CFG->messagingallusers setting enabled.
543         set_config('messagingallusers', 1);
544         list($contacts, $noncontacts) = \core_message\api::message_search_users($user1->id, 'search');
546         // Check results are empty.
547         $this->assertEquals(0, count($contacts));
548         $this->assertEquals(0, count($noncontacts));
549     }
551     /**
552      * Tests searching messages.
553      */
554     public function test_search_messages() {
555         // Create some users.
556         $user1 = self::getDataGenerator()->create_user();
557         $user2 = self::getDataGenerator()->create_user();
558         $user3 = self::getDataGenerator()->create_user();
560         // The person doing the search.
561         $this->setUser($user1);
563         // Send some messages back and forth.
564         $time = 1;
565         $this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time);
566         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
567         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
568         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
569         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
571         // Block user 3.
572         \core_message\api::block_user($user1->id, $user3->id);
574         // Perform a search.
575         $messages = \core_message\api::search_messages($user1->id, 'o');
577         // Confirm the data is correct.
578         $this->assertEquals(3, count($messages));
580         $message1 = $messages[0];
581         $message2 = $messages[1];
582         $message3 = $messages[2];
584         $this->assertEquals($user2->id, $message1->userid);
585         $this->assertEquals($user2->id, $message1->useridfrom);
586         $this->assertEquals(fullname($user2), $message1->fullname);
587         $this->assertTrue($message1->ismessaging);
588         $this->assertEquals('Word.', $message1->lastmessage);
589         $this->assertNotEmpty($message1->messageid);
590         $this->assertNull($message1->isonline);
591         $this->assertFalse($message1->isread);
592         $this->assertFalse($message1->isblocked);
593         $this->assertNull($message1->unreadcount);
595         $this->assertEquals($user2->id, $message2->userid);
596         $this->assertEquals($user1->id, $message2->useridfrom);
597         $this->assertEquals(fullname($user2), $message2->fullname);
598         $this->assertTrue($message2->ismessaging);
599         $this->assertEquals('Yo!', $message2->lastmessage);
600         $this->assertNotEmpty($message2->messageid);
601         $this->assertNull($message2->isonline);
602         $this->assertTrue($message2->isread);
603         $this->assertFalse($message2->isblocked);
604         $this->assertNull($message2->unreadcount);
606         $this->assertEquals($user3->id, $message3->userid);
607         $this->assertEquals($user3->id, $message3->useridfrom);
608         $this->assertEquals(fullname($user3), $message3->fullname);
609         $this->assertTrue($message3->ismessaging);
610         $this->assertEquals('Don\'t block me.', $message3->lastmessage);
611         $this->assertNotEmpty($message3->messageid);
612         $this->assertNull($message3->isonline);
613         $this->assertFalse($message3->isread);
614         $this->assertTrue($message3->isblocked);
615         $this->assertNull($message3->unreadcount);
616     }
618     /**
619      * Test verifying that favourited conversations can be retrieved.
620      */
621     public function test_get_favourite_conversations() {
622         // Create some users.
623         $user1 = self::getDataGenerator()->create_user();
624         $user2 = self::getDataGenerator()->create_user();
625         $user3 = self::getDataGenerator()->create_user();
626         $user4 = self::getDataGenerator()->create_user();
628         // The person doing the search.
629         $this->setUser($user1);
631         // No conversations yet.
632         $this->assertEquals([], \core_message\api::get_conversations($user1->id));
634         // Create some conversations for user1.
635         $time = 1;
636         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
637         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
638         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
639         $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
641         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
642         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
643         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
644         $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
646         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
647         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
648         $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
650         // Favourite the first 2 conversations for user1.
651         $convoids = [];
652         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
653         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
654         $user1context = context_user::instance($user1->id);
655         $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
656         foreach ($convoids as $convoid) {
657             $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
658         }
660         // We should have 3 conversations.
661         $this->assertCount(3, \core_message\api::get_conversations($user1->id));
663         // And 2 favourited conversations.
664         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
665         $this->assertCount(2, $conversations);
666     }
668     /**
669      * Tests retrieving favourite conversations with a limit and offset to ensure pagination works correctly.
670      */
671     public function test_get_favourite_conversations_limit_offset() {
672         // Create some users.
673         $user1 = self::getDataGenerator()->create_user();
674         $user2 = self::getDataGenerator()->create_user();
675         $user3 = self::getDataGenerator()->create_user();
676         $user4 = self::getDataGenerator()->create_user();
678         // The person doing the search.
679         $this->setUser($user1);
681         // No conversations yet.
682         $this->assertEquals([], \core_message\api::get_conversations($user1->id));
684         // Create some conversations for user1.
685         $time = 1;
686         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
687         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
688         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
689         $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
691         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
692         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
693         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
694         $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
696         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
697         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
698         $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
700         // Favourite the all conversations for user1.
701         $convoids = [];
702         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
703         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
704         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user4->id]);
705         $user1context = context_user::instance($user1->id);
706         $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
707         foreach ($convoids as $convoid) {
708             $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
709         }
711         // Get all records, using offset 0 and large limit.
712         $this->assertCount(2, \core_message\api::get_conversations($user1->id, 1, 10, null, true));
714         // Now, get 10 conversations starting at the second record. We should see 2 conversations.
715         $this->assertCount(2, \core_message\api::get_conversations($user1->id, 1, 10, null, true));
717         // Now, try to get favourited conversations using an invalid offset.
718         $this->assertCount(0, \core_message\api::get_conversations($user1->id, 4, 10, null, true));
719     }
721     /**
722      * Tests retrieving favourite conversations when a conversation contains a deleted user.
723      */
724     public function test_get_favourite_conversations_with_deleted_user() {
725         // Create some users.
726         $user1 = self::getDataGenerator()->create_user();
727         $user2 = self::getDataGenerator()->create_user();
728         $user3 = self::getDataGenerator()->create_user();
730         // Send some messages back and forth, have some different conversations with different users.
731         $time = 1;
732         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
733         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
734         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
735         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
737         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
738         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
739         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
740         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
742         // Favourite the all conversations for user1.
743         $convoids = [];
744         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
745         $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
746         $user1context = context_user::instance($user1->id);
747         $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
748         foreach ($convoids as $convoid) {
749             $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
750         }
752         // Delete the second user.
753         delete_user($user2);
755         // Retrieve the conversations.
756         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
758         // We should only have one conversation because the other user was deleted.
759         $this->assertCount(1, $conversations);
761         // Confirm the conversation is from the non-deleted user.
762         $conversation = reset($conversations);
763         $this->assertEquals($convoids[1], $conversation->id);
764     }
766     /**
767      * Test confirming that conversations can be marked as favourites.
768      */
769     public function test_set_favourite_conversation() {
770         // Create some users.
771         $user1 = self::getDataGenerator()->create_user();
772         $user2 = self::getDataGenerator()->create_user();
773         $user3 = self::getDataGenerator()->create_user();
775         // Send some messages back and forth, have some different conversations with different users.
776         $time = 1;
777         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
778         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
779         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
780         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
782         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
783         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
784         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
785         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
787         // Favourite the first conversation as user 1.
788         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
789         \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
791         // Verify we have a single favourite conversation a user 1.
792         $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
794         // Verify we have no favourites as user2, despite being a member in that conversation.
795         $this->assertCount(0, \core_message\api::get_conversations($user2->id, 0, 20, null, true));
797         // Try to favourite the same conversation again.
798         $this->expectException(\moodle_exception::class);
799         \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
800     }
802     /**
803      * Test verifying that trying to mark a non-existent conversation as a favourite, results in an exception.
804      */
805     public function test_set_favourite_conversation_nonexistent_conversation() {
806         // Create some users.
807         $user1 = self::getDataGenerator()->create_user();
808         // Try to favourite a non-existent conversation.
809         $this->expectException(\moodle_exception::class);
810         \core_message\api::set_favourite_conversation(0, $user1->id);
811     }
813     /**
814      * Test verifying that a conversation cannot be marked as favourite unless the user is a member of that conversation.
815      */
816     public function test_set_favourite_conversation_non_member() {
817         // Create some users.
818         $user1 = self::getDataGenerator()->create_user();
819         $user2 = self::getDataGenerator()->create_user();
820         $user3 = self::getDataGenerator()->create_user();
822         // Send some messages back and forth, have some different conversations with different users.
823         $time = 1;
824         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
825         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
826         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
827         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
829         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
830         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
831         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
832         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
834         // Try to favourite the first conversation as user 3, who is not a member.
835         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
836         $this->expectException(\moodle_exception::class);
837         \core_message\api::set_favourite_conversation($conversationid1, $user3->id);
838     }
840     /**
841      * Test confirming that those conversations marked as favourites can be unfavourited.
842      */
843     public function test_unset_favourite_conversation() {
844         // Create some users.
845         $user1 = self::getDataGenerator()->create_user();
846         $user2 = self::getDataGenerator()->create_user();
847         $user3 = self::getDataGenerator()->create_user();
849         // Send some messages back and forth, have some different conversations with different users.
850         $time = 1;
851         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
852         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
853         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
854         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
856         $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
857         $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
858         $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
859         $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
861         // Favourite the first conversation as user 1 and the second as user 3.
862         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
863         $conversationid2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
864         \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
865         \core_message\api::set_favourite_conversation($conversationid2, $user3->id);
867         // Verify we have a single favourite conversation for both user 1 and user 3.
868         $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
869         $this->assertCount(1, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
871         // Now unfavourite the conversation as user 1.
872         \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
874         // Verify we have a single favourite conversation user 3 only, and none for user1.
875         $this->assertCount(1, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
876         $this->assertCount(0, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
878         // Try to favourite the same conversation again as user 1.
879         $this->expectException(\moodle_exception::class);
880         \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
881     }
883     /**
884      * Test verifying that a valid conversation cannot be unset as a favourite if it's not marked as a favourite.
885      */
886     public function test_unset_favourite_conversation_not_favourite() {
887         // Create some users.
888         $user1 = self::getDataGenerator()->create_user();
889         $user2 = self::getDataGenerator()->create_user();
891         // Send some messages back and forth, have some different conversations with different users.
892         $time = 1;
893         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
894         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
895         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
896         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
898         // Now try to unfavourite the conversation as user 1.
899         $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
900         $this->expectException(\moodle_exception::class);
901         \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
902     }
904     /**
905      * Test verifying that a non-existent conversation cannot be unset as a favourite.
906      */
907     public function test_unset_favourite_conversation_non_existent_conversation() {
908         // Create some users.
909         $user1 = self::getDataGenerator()->create_user();
911         // Now try to unfavourite the conversation as user 1.
912         $this->expectException(\moodle_exception::class);
913         \core_message\api::unset_favourite_conversation(0, $user1->id);
914     }
916     /**
917      * Helper to seed the database with initial state.
918      */
919     protected function create_conversation_test_data() {
920         // Create some users.
921         $user1 = self::getDataGenerator()->create_user();
922         $user2 = self::getDataGenerator()->create_user();
923         $user3 = self::getDataGenerator()->create_user();
924         $user4 = self::getDataGenerator()->create_user();
926         $time = 1;
928         // Create some conversations. We want:
929         // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message.
930         // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message.
931         // 3) At least one of each type (group, individual) of which user1 IS NOT a member.
932         // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering).
933         // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member.
935         // Individual conversation, user1 is a member, last message from other user.
936         $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
937             [$user1->id, $user2->id]);
938         testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time);
939         testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1);
941         // Individual conversation, user1 is a member, last message from user1.
942         $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
943             [$user1->id, $user3->id]);
944         testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2);
945         testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3);
947         // Individual conversation, user1 is not a member.
948         $ic3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
949             [$user2->id, $user3->id]);
950         testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4);
951         testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5);
953         // Group conversation, user1 is not a member.
954         $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
955             [$user2->id, $user3->id, $user4->id], 'Project discussions');
956         testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6);
957         testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7);
959         // Group conversation, user1 is a member, last message from another user.
960         $gc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
961             [$user1->id, $user3->id, $user4->id], 'Group chat');
962         testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8);
963         testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9);
964         testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10);
966         // Group conversation, user1 is a member, last message from user1.
967         $gc3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
968             [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!');
969         testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11);
970         testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12);
971         testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13);
973         // Empty group conversations (x2), user1 is a member.
974         $gc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
975             [$user1->id, $user2->id, $user3->id], 'Empty group');
976         $gc5 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
977             [$user1->id, $user2->id, $user4->id], 'Another empty group');
979         // Empty group conversation, user1 is NOT a member.
980         $gc6 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
981             [$user2->id, $user3->id, $user4->id], 'Empty group 3');
983         return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6];
984     }
986     /**
987      * Test verifying get_conversations when no limits, offsets, type filters or favourite restrictions are used.
988      */
989     public function test_get_conversations_no_restrictions() {
990         global $DB;
991         // No conversations should exist yet.
992         $user1 = self::getDataGenerator()->create_user();
993         $this->assertEquals([], \core_message\api::get_conversations($user1->id));
995         // Get a bunch of conversations, some group, some individual and in different states.
996         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
997             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
999         // Get all conversations for user1.
1000         $conversations = core_message\api::get_conversations($user1->id);
1002         // Verify there are 2 individual conversation, 2 group conversations, and 2 empty group conversations.
1003         // The conversations with the most recent messages should be listed first, followed by the empty
1004         // conversations, with the most recently created first.
1005         $this->assertCount(6, $conversations);
1006         $typecounts  = array_count_values(array_column($conversations, 'type'));
1007         $this->assertEquals(2, $typecounts[1]);
1008         $this->assertEquals(4, $typecounts[2]);
1010         // Those conversations having messages should be listed first, ordered by most recent message time.
1011         $this->assertEquals($gc3->id, $conversations[0]->id);
1012         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[0]->type);
1013         $this->assertFalse($conversations[0]->isfavourite);
1014         $this->assertCount(1, $conversations[0]->members);
1015         $this->assertEquals(4, $conversations[0]->membercount);
1016         $this->assertCount(1, $conversations[0]->messages);
1017         $message = $DB->get_record('messages', ['id' => $conversations[0]->messages[0]->id]);
1018         $expectedmessagetext = message_format_message_text($message);
1019         $this->assertEquals($expectedmessagetext, $conversations[0]->messages[0]->text);
1020         $this->assertEquals($user1->id, $conversations[0]->messages[0]->useridfrom);
1022         $this->assertEquals($gc2->id, $conversations[1]->id);
1023         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[1]->type);
1024         $this->assertFalse($conversations[1]->isfavourite);
1025         $this->assertCount(1, $conversations[1]->members);
1026         $this->assertEquals(3, $conversations[1]->membercount);
1027         $this->assertCount(1, $conversations[1]->messages);
1028         $message = $DB->get_record('messages', ['id' => $conversations[1]->messages[0]->id]);
1029         $expectedmessagetext = message_format_message_text($message);
1030         $this->assertEquals($expectedmessagetext, $conversations[1]->messages[0]->text);
1031         $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1033         $this->assertEquals($ic2->id, $conversations[2]->id);
1034         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[2]->type);
1035         $this->assertFalse($conversations[2]->isfavourite);
1036         $this->assertCount(1, $conversations[2]->members);
1037         $this->assertEquals($user3->id, $conversations[2]->members[$user3->id]->id);
1038         $this->assertEquals(2, $conversations[2]->membercount);
1039         $this->assertCount(1, $conversations[2]->messages);
1040         $message = $DB->get_record('messages', ['id' => $conversations[2]->messages[0]->id]);
1041         $expectedmessagetext = message_format_message_text($message);
1042         $this->assertEquals($expectedmessagetext, $conversations[2]->messages[0]->text);
1043         $this->assertEquals($user1->id, $conversations[2]->messages[0]->useridfrom);
1045         $this->assertEquals($ic1->id, $conversations[3]->id);
1046         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[3]->type);
1047         $this->assertFalse($conversations[3]->isfavourite);
1048         $this->assertCount(1, $conversations[3]->members);
1049         $this->assertEquals(2, $conversations[3]->membercount);
1050         $this->assertCount(1, $conversations[3]->messages);
1051         $message = $DB->get_record('messages', ['id' => $conversations[3]->messages[0]->id]);
1052         $expectedmessagetext = message_format_message_text($message);
1053         $this->assertEquals($expectedmessagetext, $conversations[3]->messages[0]->text);
1054         $this->assertEquals($user2->id, $conversations[3]->messages[0]->useridfrom);
1056         // Of the groups without messages, we expect to see the most recently created first.
1057         $this->assertEquals($gc5->id, $conversations[4]->id);
1058         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[4]->type);
1059         $this->assertFalse($conversations[4]->isfavourite);
1060         $this->assertCount(0, $conversations[4]->members); // No members returned, because no recent messages exist.
1061         $this->assertEquals(3, $conversations[4]->membercount);
1062         $this->assertEmpty($conversations[4]->messages);
1064         $this->assertEquals($gc4->id, $conversations[5]->id);
1065         $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[5]->type);
1066         $this->assertFalse($conversations[5]->isfavourite);
1067         $this->assertCount(0, $conversations[5]->members);
1068         $this->assertEquals(3, $conversations[5]->membercount);
1069         $this->assertEmpty($conversations[5]->messages);
1071         // Verify format of the return structure.
1072         foreach ($conversations as $conv) {
1073             $this->assertObjectHasAttribute('id', $conv);
1074             $this->assertObjectHasAttribute('name', $conv);
1075             $this->assertObjectHasAttribute('subname', $conv);
1076             $this->assertObjectHasAttribute('imageurl', $conv);
1077             $this->assertObjectHasAttribute('type', $conv);
1078             $this->assertObjectHasAttribute('isfavourite', $conv);
1079             $this->assertObjectHasAttribute('membercount', $conv);
1080             $this->assertObjectHasAttribute('isread', $conv);
1081             $this->assertObjectHasAttribute('unreadcount', $conv);
1082             $this->assertObjectHasAttribute('members', $conv);
1083             foreach ($conv->members as $member) {
1084                 $this->assertObjectHasAttribute('id', $member);
1085                 $this->assertObjectHasAttribute('fullname', $member);
1086                 $this->assertObjectHasAttribute('profileimageurl', $member);
1087                 $this->assertObjectHasAttribute('profileimageurlsmall', $member);
1088                 $this->assertObjectHasAttribute('isonline', $member);
1089                 $this->assertObjectHasAttribute('showonlinestatus', $member);
1090                 $this->assertObjectHasAttribute('isblocked', $member);
1091                 $this->assertObjectHasAttribute('iscontact', $member);
1092                 $this->assertObjectHasAttribute('isdeleted', $member);
1093                 $this->assertObjectHasAttribute('canmessage', $member);
1094                 $this->assertObjectHasAttribute('requirescontact', $member);
1095                 $this->assertObjectHasAttribute('contactrequests', $member);
1096             }
1097             $this->assertObjectHasAttribute('messages', $conv);
1098             foreach ($conv->messages as $message) {
1099                 $this->assertObjectHasAttribute('id', $message);
1100                 $this->assertObjectHasAttribute('useridfrom', $message);
1101                 $this->assertObjectHasAttribute('text', $message);
1102                 $this->assertObjectHasAttribute('timecreated', $message);
1103             }
1104         }
1105     }
1107     /**
1108      * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately.
1109      */
1110     public function test_get_conversations_message_format() {
1111         global $DB;
1112         // Create some users.
1113         $user1 = self::getDataGenerator()->create_user();
1114         $user2 = self::getDataGenerator()->create_user();
1116         // Create conversation.
1117         $conversation = \core_message\api::create_conversation(
1118             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1119             [$user1->id, $user2->id]
1120         );
1122         // Send some messages back and forth.
1123         $time = 1;
1124         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1);
1125         $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2);
1127         // Verify the format of the html message.
1128         $message = $DB->get_record('messages', ['id' => $mid]);
1129         $expectedmessagetext = message_format_message_text($message);
1130         $conversations = \core_message\api::get_conversations($user1->id);
1131         $messages = $conversations[0]->messages;
1132         $this->assertEquals($expectedmessagetext, $messages[0]->text);
1133     }
1135     /**
1136      * Tests retrieving conversations with a limit and offset to ensure pagination works correctly.
1137      */
1138     public function test_get_conversations_limit_offset() {
1139         // Get a bunch of conversations, some group, some individual and in different states.
1140         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1141             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1143         // Get all conversations for user1, limited to 1 result.
1144         $conversations = core_message\api::get_conversations($user1->id, 0, 1);
1146         // Verify the first conversation.
1147         $this->assertCount(1, $conversations);
1148         $conversation = array_shift($conversations);
1149         $this->assertEquals($conversation->id, $gc3->id);
1151         // Verify the next conversation.
1152         $conversations = \core_message\api::get_conversations($user1->id, 1, 1);
1153         $this->assertCount(1, $conversations);
1154         $this->assertEquals($gc2->id, $conversations[0]->id);
1156         // Verify the next conversation.
1157         $conversations = \core_message\api::get_conversations($user1->id, 2, 1);
1158         $this->assertCount(1, $conversations);
1159         $this->assertEquals($ic2->id, $conversations[0]->id);
1161         // Skip one and get both empty conversations.
1162         $conversations = \core_message\api::get_conversations($user1->id, 4, 2);
1163         $this->assertCount(2, $conversations);
1164         $this->assertEquals($gc5->id, $conversations[0]->id);
1165         $this->assertEmpty($conversations[0]->messages);
1166         $this->assertEquals($gc4->id, $conversations[1]->id);
1167         $this->assertEmpty($conversations[1]->messages);
1169         // Ask for an offset that doesn't exist and verify no conversations are returned.
1170         $conversations = \core_message\api::get_conversations($user1->id, 10, 1);
1171         $this->assertCount(0, $conversations);
1172     }
1174     /**
1175      * Test verifying the type filtering behaviour of the
1176      */
1177     public function test_get_conversations_type_filter() {
1178         // Get a bunch of conversations, some group, some individual and in different states.
1179         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1180             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1182         // Verify we can ask for only individual conversations.
1183         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1184             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1185         $this->assertCount(2, $conversations);
1187         // Verify we can ask for only group conversations.
1188         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1189             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP);
1190         $this->assertCount(4, $conversations);
1192         // Verify an exception is thrown if an unrecognized type is specified.
1193         $this->expectException(\moodle_exception::class);
1194         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 0);
1195     }
1197     /**
1198      * Tests retrieving conversations when a conversation contains a deleted user.
1199      */
1200     public function test_get_conversations_with_deleted_user() {
1201         // Get a bunch of conversations, some group, some individual and in different states.
1202         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1203             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1205         // Delete the second user and retrieve the conversations.
1206         // We should have 5, as $ic1 drops off the list.
1207         // Group conversations remain albeit with less members.
1208         delete_user($user2);
1209         $conversations = \core_message\api::get_conversations($user1->id);
1210         $this->assertCount(5, $conversations);
1211         $this->assertEquals($gc3->id, $conversations[0]->id);
1212         $this->assertcount(1, $conversations[0]->members);
1213         $this->assertEquals($gc2->id, $conversations[1]->id);
1214         $this->assertcount(1, $conversations[1]->members);
1215         $this->assertEquals($ic2->id, $conversations[2]->id);
1216         $this->assertEquals($gc5->id, $conversations[3]->id);
1217         $this->assertEquals($gc4->id, $conversations[4]->id);
1219         // Delete a user from a group conversation where that user had sent the most recent message.
1220         // This user will still be present in the members array, as will the message in the messages array.
1221         delete_user($user4);
1222         $conversations = \core_message\api::get_conversations($user1->id);
1223         $this->assertCount(5, $conversations);
1224         $this->assertEquals($gc2->id, $conversations[1]->id);
1225         $this->assertcount(1, $conversations[1]->members);
1226         $this->assertEquals($user4->id, $conversations[1]->members[$user4->id]->id);
1227         $this->assertcount(1, $conversations[1]->messages);
1228         $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1230         // Delete the third user and retrieve the conversations.
1231         // We should have 4, as $ic1, $ic2 drop off the list.
1232         // Group conversations remain albeit with less members.
1233         delete_user($user3);
1234         $conversations = \core_message\api::get_conversations($user1->id);
1235         $this->assertCount(4, $conversations);
1236         $this->assertEquals($gc3->id, $conversations[0]->id);
1237         $this->assertcount(1, $conversations[0]->members);
1238         $this->assertEquals($gc2->id, $conversations[1]->id);
1239         $this->assertcount(1, $conversations[1]->members);
1240         $this->assertEquals($gc5->id, $conversations[2]->id);
1241         $this->assertEquals($gc4->id, $conversations[3]->id);
1242     }
1244     /**
1245      * Test confirming the behaviour of get_conversations() when users delete all messages.
1246      */
1247     public function test_get_conversations_deleted_messages() {
1248         // Get a bunch of conversations, some group, some individual and in different states.
1249         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1250             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1252         $conversations = \core_message\api::get_conversations($user1->id);
1253         $this->assertCount(6, $conversations);
1255         // Delete all messages from a group conversation the user is in - it should be returned.
1256         $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $gc2->id));
1257         $convmessages = \core_message\api::get_conversation_messages($user1->id, $gc2->id);
1258         $messages = $convmessages['messages'];
1259         foreach ($messages as $message) {
1260             \core_message\api::delete_message($user1->id, $message->id);
1261         }
1262         $conversations = \core_message\api::get_conversations($user1->id);
1263         $this->assertCount(6, $conversations);
1264         $this->assertContains($gc2->id, array_column($conversations, 'id'));
1266         // Delete all messages from an individual conversation the user is in - it should not be returned.
1267         $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $ic1->id));
1268         $convmessages = \core_message\api::get_conversation_messages($user1->id, $ic1->id);
1269         $messages = $convmessages['messages'];
1270         foreach ($messages as $message) {
1271             \core_message\api::delete_message($user1->id, $message->id);
1272         }
1273         $conversations = \core_message\api::get_conversations($user1->id);
1274         $this->assertCount(5, $conversations);
1275         $this->assertNotContains($ic1->id, array_column($conversations, 'id'));
1276     }
1278     /**
1279      * Test verifying the behaviour of get_conversations() when fetching favourite conversations with only a single
1280      * favourite.
1281      */
1282     public function test_get_conversations_favourite_conversations_single() {
1283         // Get a bunch of conversations, some group, some individual and in different states.
1284         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1285             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1287         // Mark a single conversation as favourites.
1288         \core_message\api::set_favourite_conversation($ic2->id, $user1->id);
1290         // Get the conversation, first with no restrictions, confirming the favourite status of the conversations.
1291         $conversations = \core_message\api::get_conversations($user1->id);
1292         $this->assertCount(6, $conversations);
1293         foreach ($conversations as $conv) {
1294             if (in_array($conv->id, [$ic2->id])) {
1295                 $this->assertTrue($conv->isfavourite);
1296             } else {
1297                 $this->assertFalse($conv->isfavourite);
1298             }
1299         }
1301         // Now, get ONLY favourite conversations.
1302         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1303         $this->assertCount(1, $conversations);
1304         foreach ($conversations as $conv) {
1305             $this->assertTrue($conv->isfavourite);
1306             $this->assertEquals($ic2->id, $conv->id);
1307         }
1309         // Now, try ONLY favourites of type 'group'.
1310         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1311             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1312         $this->assertEmpty($conversations);
1314         // And NO favourite conversations.
1315         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1316         $this->assertCount(5, $conversations);
1317         foreach ($conversations as $conv) {
1318             $this->assertFalse($conv->isfavourite);
1319             $this->assertNotEquals($ic2, $conv->id);
1320         }
1321     }
1323     /**
1324      * Test verifying the behaviour of get_conversations() when fetching favourite conversations.
1325      */
1326     public function test_get_conversations_favourite_conversations() {
1327         // Get a bunch of conversations, some group, some individual and in different states.
1328         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1329             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1331         // Try to get ONLY favourite conversations, when no favourites exist.
1332         $this->assertEquals([], \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1334         // Try to get NO favourite conversations, when no favourites exist.
1335         $this->assertCount(6, \core_message\api::get_conversations($user1->id, 0, 20, null, false));
1337         // Mark a few conversations as favourites.
1338         \core_message\api::set_favourite_conversation($ic1->id, $user1->id);
1339         \core_message\api::set_favourite_conversation($gc2->id, $user1->id);
1340         \core_message\api::set_favourite_conversation($gc5->id, $user1->id);
1341         $favouriteids = [$ic1->id, $gc2->id, $gc5->id];
1343         // Get the conversations, first with no restrictions, confirming the favourite status of the conversations.
1344         $conversations = \core_message\api::get_conversations($user1->id);
1345         $this->assertCount(6, $conversations);
1346         foreach ($conversations as $conv) {
1347             if (in_array($conv->id, $favouriteids)) {
1348                 $this->assertTrue($conv->isfavourite);
1349             } else {
1350                 $this->assertFalse($conv->isfavourite);
1351             }
1352         }
1354         // Now, get ONLY favourite conversations.
1355         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1356         $this->assertCount(3, $conversations);
1357         foreach ($conversations as $conv) {
1358             $this->assertTrue($conv->isfavourite);
1359             $this->assertNotFalse(array_search($conv->id, $favouriteids));
1360         }
1362         // Now, try ONLY favourites of type 'group'.
1363         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1364             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1365         $this->assertCount(2, $conversations);
1366         foreach ($conversations as $conv) {
1367             $this->assertTrue($conv->isfavourite);
1368             $this->assertNotFalse(array_search($conv->id, [$gc2->id, $gc5->id]));
1369         }
1371         // And NO favourite conversations.
1372         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1373         $this->assertCount(3, $conversations);
1374         foreach ($conversations as $conv) {
1375             $this->assertFalse($conv->isfavourite);
1376             $this->assertFalse(array_search($conv->id, $favouriteids));
1377         }
1378     }
1380     /**
1381      * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this
1382      * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want
1383      * to confirm this happens.
1384      */
1385     public function test_get_conversations_user_in_group_and_individual_chat() {
1386         $this->resetAfterTest();
1388         $user1 = self::getDataGenerator()->create_user();
1389         $user2 = self::getDataGenerator()->create_user();
1390         $user3 = self::getDataGenerator()->create_user();
1392         $conversation = \core_message\api::create_conversation(
1393             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1394             [
1395                 $user1->id,
1396                 $user2->id
1397             ],
1398             'Individual conversation'
1399         );
1401         testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1403         $conversation = \core_message\api::create_conversation(
1404             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1405             [
1406                 $user1->id,
1407                 $user2->id,
1408             ],
1409             'Group conversation'
1410         );
1412         testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1414         \core_message\api::create_contact_request($user1->id, $user2->id);
1415         \core_message\api::create_contact_request($user1->id, $user3->id);
1417         $conversations = \core_message\api::get_conversations($user2->id);
1419         $groupconversation = array_shift($conversations);
1420         $individualconversation = array_shift($conversations);
1422         $this->assertEquals('Group conversation', $groupconversation->name);
1423         $this->assertEquals('Individual conversation', $individualconversation->name);
1425         $this->assertCount(1, $groupconversation->members);
1426         $this->assertCount(1, $individualconversation->members);
1428         $groupmember = reset($groupconversation->members);
1429         $this->assertNull($groupmember->requirescontact);
1430         $this->assertNull($groupmember->canmessage);
1431         $this->assertEmpty($groupmember->contactrequests);
1433         $individualmember = reset($individualconversation->members);
1434         $this->assertNotNull($individualmember->requirescontact);
1435         $this->assertNotNull($individualmember->canmessage);
1436         $this->assertNotEmpty($individualmember->contactrequests);
1437     }
1439     /**
1440      * Test verifying that group linked conversations are returned and contain a subname matching the course name.
1441      */
1442     public function test_get_conversations_group_linked() {
1443         global $CFG;
1445         // Create some users.
1446         $user1 = self::getDataGenerator()->create_user();
1447         $user2 = self::getDataGenerator()->create_user();
1448         $user3 = self::getDataGenerator()->create_user();
1450         $course1 = $this->getDataGenerator()->create_course();
1452         // Create a group with a linked conversation and a valid image.
1453         $this->setAdminUser();
1454         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1455         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1456         $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
1457         $group1 = $this->getDataGenerator()->create_group([
1458             'courseid' => $course1->id,
1459             'enablemessaging' => 1,
1460             'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
1461         ]);
1463         // Add users to group1.
1464         $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1465         $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
1467         // Verify the group with the image works as expected.
1468         $conversations = \core_message\api::get_conversations($user1->id);
1469         $this->assertEquals(2, $conversations[0]->membercount);
1470         $this->assertEquals($course1->shortname, $conversations[0]->subname);
1471         $groupimageurl = get_group_picture_url($group1, $group1->courseid, true);
1472         $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1474         // Create a group with a linked conversation and without any image.
1475         $group2 = $this->getDataGenerator()->create_group([
1476             'courseid' => $course1->id,
1477             'enablemessaging' => 1,
1478         ]);
1480         // Add users to group2.
1481         $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1482         $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id));
1484         // Verify the group without any image works as expected too.
1485         $conversations = \core_message\api::get_conversations($user3->id);
1486         $this->assertEquals(2, $conversations[0]->membercount);
1487         $this->assertEquals($course1->shortname, $conversations[0]->subname);
1488         $groupimageurl = get_group_picture_url($group2, $group2->courseid, true);
1489         $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1490     }
1492    /**
1493     * The data provider for get_conversations_mixed.
1494     *
1495     * This provides sets of data to for testing.
1496     * @return array
1497     */
1498    public function get_conversations_mixed_provider() {
1499        return array(
1500             'Test that conversations with messages contacts is correctly ordered.' => array(
1501                 'users' => array(
1502                     'user1',
1503                     'user2',
1504                     'user3',
1505                 ),
1506                 'contacts' => array(
1507                 ),
1508                 'messages' => array(
1509                     array(
1510                         'from'          => 'user1',
1511                         'to'            => 'user2',
1512                         'state'         => 'unread',
1513                         'subject'       => 'S1',
1514                     ),
1515                     array(
1516                         'from'          => 'user2',
1517                         'to'            => 'user1',
1518                         'state'         => 'unread',
1519                         'subject'       => 'S2',
1520                     ),
1521                     array(
1522                         'from'          => 'user1',
1523                         'to'            => 'user2',
1524                         'state'         => 'unread',
1525                         'timecreated'   => 0,
1526                         'subject'       => 'S3',
1527                     ),
1528                     array(
1529                         'from'          => 'user1',
1530                         'to'            => 'user3',
1531                         'state'         => 'read',
1532                         'timemodifier'  => 1,
1533                         'subject'       => 'S4',
1534                     ),
1535                     array(
1536                         'from'          => 'user3',
1537                         'to'            => 'user1',
1538                         'state'         => 'read',
1539                         'timemodifier'  => 1,
1540                         'subject'       => 'S5',
1541                     ),
1542                     array(
1543                         'from'          => 'user1',
1544                         'to'            => 'user3',
1545                         'state'         => 'read',
1546                         'timecreated'   => 0,
1547                         'subject'       => 'S6',
1548                     ),
1549                 ),
1550                 'expectations' => array(
1551                     'user1' => array(
1552                         // User1 has conversed most recently with user3. The most recent message is M5.
1553                         array(
1554                             'messageposition'   => 0,
1555                             'with'              => 'user3',
1556                             'subject'           => '<p>S5</p>',
1557                             'unreadcount'       => 0,
1558                         ),
1559                         // User1 has also conversed with user2. The most recent message is S2.
1560                         array(
1561                             'messageposition'   => 1,
1562                             'with'              => 'user2',
1563                             'subject'           => '<p>S2</p>',
1564                             'unreadcount'       => 1,
1565                         ),
1566                     ),
1567                     'user2' => array(
1568                         // User2 has only conversed with user1. Their most recent shared message was S2.
1569                         array(
1570                             'messageposition'   => 0,
1571                             'with'              => 'user1',
1572                             'subject'           => '<p>S2</p>',
1573                             'unreadcount'       => 2,
1574                         ),
1575                     ),
1576                     'user3' => array(
1577                         // User3 has only conversed with user1. Their most recent shared message was S5.
1578                         array(
1579                             'messageposition'   => 0,
1580                             'with'              => 'user1',
1581                             'subject'           => '<p>S5</p>',
1582                             'unreadcount'       => 0,
1583                         ),
1584                     ),
1585                 ),
1586             ),
1587             'Test conversations with a single user, where some messages are read and some are not.' => array(
1588                 'users' => array(
1589                     'user1',
1590                     'user2',
1591                 ),
1592                 'contacts' => array(
1593                 ),
1594                 'messages' => array(
1595                     array(
1596                         'from'          => 'user1',
1597                         'to'            => 'user2',
1598                         'state'         => 'read',
1599                         'subject'       => 'S1',
1600                     ),
1601                     array(
1602                         'from'          => 'user2',
1603                         'to'            => 'user1',
1604                         'state'         => 'read',
1605                         'subject'       => 'S2',
1606                     ),
1607                     array(
1608                         'from'          => 'user1',
1609                         'to'            => 'user2',
1610                         'state'         => 'unread',
1611                         'timemodifier'  => 1,
1612                         'subject'       => 'S3',
1613                     ),
1614                     array(
1615                         'from'          => 'user1',
1616                         'to'            => 'user2',
1617                         'state'         => 'unread',
1618                         'timemodifier'  => 1,
1619                         'subject'       => 'S4',
1620                     ),
1621                 ),
1622                 'expectations' => array(
1623                     // The most recent message between user1 and user2 was S4.
1624                     'user1' => array(
1625                         array(
1626                             'messageposition'   => 0,
1627                             'with'              => 'user2',
1628                             'subject'           => '<p>S4</p>',
1629                             'unreadcount'       => 0,
1630                         ),
1631                     ),
1632                     'user2' => array(
1633                         // The most recent message between user1 and user2 was S4.
1634                         array(
1635                             'messageposition'   => 0,
1636                             'with'              => 'user1',
1637                             'subject'           => '<p>S4</p>',
1638                             'unreadcount'       => 2,
1639                         ),
1640                     ),
1641                 ),
1642             ),
1643             'Test conversations with a single user, where some messages are read and some are not, and messages ' .
1644             'are out of order' => array(
1645             // This can happen through a combination of factors including multi-master DB replication with messages
1646             // read somehow (e.g. API).
1647                 'users' => array(
1648                     'user1',
1649                     'user2',
1650                 ),
1651                 'contacts' => array(
1652                 ),
1653                 'messages' => array(
1654                     array(
1655                         'from'          => 'user1',
1656                         'to'            => 'user2',
1657                         'state'         => 'read',
1658                         'subject'       => 'S1',
1659                         'timemodifier'  => 1,
1660                     ),
1661                     array(
1662                         'from'          => 'user2',
1663                         'to'            => 'user1',
1664                         'state'         => 'read',
1665                         'subject'       => 'S2',
1666                         'timemodifier'  => 2,
1667                     ),
1668                     array(
1669                         'from'          => 'user1',
1670                         'to'            => 'user2',
1671                         'state'         => 'unread',
1672                         'subject'       => 'S3',
1673                     ),
1674                     array(
1675                         'from'          => 'user1',
1676                         'to'            => 'user2',
1677                         'state'         => 'unread',
1678                         'subject'       => 'S4',
1679                     ),
1680                 ),
1681                 'expectations' => array(
1682                     // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1683                     'user1' => array(
1684                         array(
1685                             'messageposition'   => 0,
1686                             'with'              => 'user2',
1687                             'subject'           => '<p>S2</p>',
1688                             'unreadcount'       => 0,
1689                         ),
1690                     ),
1691                     'user2' => array(
1692                         array(
1693                             'messageposition'   => 0,
1694                             'with'              => 'user1',
1695                             'subject'           => '<p>S2</p>',
1696                             'unreadcount'       => 2
1697                         ),
1698                     ),
1699                 ),
1700             ),
1701             'Test unread message count is correct for both users' => array(
1702                 'users' => array(
1703                     'user1',
1704                     'user2',
1705                 ),
1706                 'contacts' => array(
1707                 ),
1708                 'messages' => array(
1709                     array(
1710                         'from'          => 'user1',
1711                         'to'            => 'user2',
1712                         'state'         => 'read',
1713                         'subject'       => 'S1',
1714                         'timemodifier'  => 1,
1715                     ),
1716                     array(
1717                         'from'          => 'user2',
1718                         'to'            => 'user1',
1719                         'state'         => 'read',
1720                         'subject'       => 'S2',
1721                         'timemodifier'  => 2,
1722                     ),
1723                     array(
1724                         'from'          => 'user1',
1725                         'to'            => 'user2',
1726                         'state'         => 'read',
1727                         'subject'       => 'S3',
1728                         'timemodifier'  => 3,
1729                     ),
1730                     array(
1731                         'from'          => 'user1',
1732                         'to'            => 'user2',
1733                         'state'         => 'read',
1734                         'subject'       => 'S4',
1735                         'timemodifier'  => 4,
1736                     ),
1737                     array(
1738                         'from'          => 'user1',
1739                         'to'            => 'user2',
1740                         'state'         => 'unread',
1741                         'subject'       => 'S5',
1742                         'timemodifier'  => 5,
1743                     ),
1744                     array(
1745                         'from'          => 'user2',
1746                         'to'            => 'user1',
1747                         'state'         => 'unread',
1748                         'subject'       => 'S6',
1749                         'timemodifier'  => 6,
1750                     ),
1751                     array(
1752                         'from'          => 'user1',
1753                         'to'            => 'user2',
1754                         'state'         => 'unread',
1755                         'subject'       => 'S7',
1756                         'timemodifier'  => 7,
1757                     ),
1758                     array(
1759                         'from'          => 'user1',
1760                         'to'            => 'user2',
1761                         'state'         => 'unread',
1762                         'subject'       => 'S8',
1763                         'timemodifier'  => 8,
1764                     ),
1765                 ),
1766                 'expectations' => array(
1767                     // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1768                     'user1' => array(
1769                         array(
1770                             'messageposition'   => 0,
1771                             'with'              => 'user2',
1772                             'subject'           => '<p>S8</p>',
1773                             'unreadcount'       => 1,
1774                         ),
1775                     ),
1776                     'user2' => array(
1777                         array(
1778                             'messageposition'   => 0,
1779                             'with'              => 'user1',
1780                             'subject'           => '<p>S8</p>',
1781                             'unreadcount'       => 3,
1782                         ),
1783                     ),
1784                 ),
1785             ),
1786         );
1787     }
1789     /**
1790      * Test get_conversations with a mixture of messages.
1791      *
1792      * @dataProvider get_conversations_mixed_provider
1793      * @param array $usersdata The list of users to create for this test.
1794      * @param array $messagesdata The list of messages to create.
1795      * @param array $expectations The list of expected outcomes.
1796      */
1797     public function test_get_conversations_mixed($usersdata, $contacts, $messagesdata, $expectations) {
1798         global $DB;
1800         // Create all of the users.
1801         $users = array();
1802         foreach ($usersdata as $username) {
1803             $users[$username] = $this->getDataGenerator()->create_user(array('username' => $username));
1804         }
1806         foreach ($contacts as $username => $contact) {
1807             foreach ($contact as $contactname => $blocked) {
1808                 $record = new stdClass();
1809                 $record->userid     = $users[$username]->id;
1810                 $record->contactid  = $users[$contactname]->id;
1811                 $record->blocked    = $blocked;
1812                 $record->id = $DB->insert_record('message_contacts', $record);
1813             }
1814         }
1816         $defaulttimecreated = time();
1817         foreach ($messagesdata as $messagedata) {
1818             $from       = $users[$messagedata['from']];
1819             $to         = $users[$messagedata['to']];
1820             $subject    = $messagedata['subject'];
1822             if (isset($messagedata['state']) && $messagedata['state'] == 'unread') {
1823                 $messageid = $this->send_fake_message($from, $to, $subject);
1824             } else {
1825                 // If there is no state, or the state is not 'unread', assume the message is read.
1826                 $messageid = message_post_message($from, $to, $subject, FORMAT_PLAIN);
1827             }
1829             $updatemessage = new stdClass();
1830             $updatemessage->id = $messageid;
1831             if (isset($messagedata['timecreated'])) {
1832                 $updatemessage->timecreated = $messagedata['timecreated'];
1833             } else if (isset($messagedata['timemodifier'])) {
1834                 $updatemessage->timecreated = $defaulttimecreated + $messagedata['timemodifier'];
1835             } else {
1836                 $updatemessage->timecreated = $defaulttimecreated;
1837             }
1839             $DB->update_record('messages', $updatemessage);
1840         }
1842         foreach ($expectations as $username => $data) {
1843             // Get the recent conversations for the specified user.
1844             $user = $users[$username];
1845             $conversations = array_values(\core_message\api::get_conversations($user->id));
1846             foreach ($data as $expectation) {
1847                 $otheruser = $users[$expectation['with']];
1848                 $conversation = $conversations[$expectation['messageposition']];
1849                 $this->assertEquals($otheruser->id, $conversation->members[$otheruser->id]->id);
1850                 $this->assertEquals($expectation['subject'], $conversation->messages[0]->text);
1851                 $this->assertEquals($expectation['unreadcount'], $conversation->unreadcount);
1852             }
1853         }
1854     }
1856     /**
1857      * Tests retrieving contacts.
1858      */
1859     public function test_get_contacts() {
1860         // Create some users.
1861         $user1 = self::getDataGenerator()->create_user();
1863         // Set as the user.
1864         $this->setUser($user1);
1866         $user2 = new stdClass();
1867         $user2->firstname = 'User';
1868         $user2->lastname = 'A';
1869         $user2 = self::getDataGenerator()->create_user($user2);
1871         $user3 = new stdClass();
1872         $user3->firstname = 'User';
1873         $user3->lastname = 'B';
1874         $user3 = self::getDataGenerator()->create_user($user3);
1876         $user4 = new stdClass();
1877         $user4->firstname = 'User';
1878         $user4->lastname = 'C';
1879         $user4 = self::getDataGenerator()->create_user($user4);
1881         $user5 = new stdClass();
1882         $user5->firstname = 'User';
1883         $user5->lastname = 'D';
1884         $user5 = self::getDataGenerator()->create_user($user5);
1886         // Add some users as contacts.
1887         \core_message\api::add_contact($user1->id, $user2->id);
1888         \core_message\api::add_contact($user1->id, $user3->id);
1889         \core_message\api::add_contact($user1->id, $user4->id);
1891         // Retrieve the contacts.
1892         $contacts = \core_message\api::get_contacts($user1->id);
1894         // Confirm the data is correct.
1895         $this->assertEquals(3, count($contacts));
1896         usort($contacts, ['static', 'sort_contacts']);
1898         $contact1 = $contacts[0];
1899         $contact2 = $contacts[1];
1900         $contact3 = $contacts[2];
1902         $this->assertEquals($user2->id, $contact1->userid);
1903         $this->assertEmpty($contact1->useridfrom);
1904         $this->assertFalse($contact1->ismessaging);
1905         $this->assertNull($contact1->lastmessage);
1906         $this->assertNull($contact1->messageid);
1907         $this->assertNull($contact1->isonline);
1908         $this->assertFalse($contact1->isread);
1909         $this->assertFalse($contact1->isblocked);
1910         $this->assertNull($contact1->unreadcount);
1912         $this->assertEquals($user3->id, $contact2->userid);
1913         $this->assertEmpty($contact2->useridfrom);
1914         $this->assertFalse($contact2->ismessaging);
1915         $this->assertNull($contact2->lastmessage);
1916         $this->assertNull($contact2->messageid);
1917         $this->assertNull($contact2->isonline);
1918         $this->assertFalse($contact2->isread);
1919         $this->assertFalse($contact2->isblocked);
1920         $this->assertNull($contact2->unreadcount);
1922         $this->assertEquals($user4->id, $contact3->userid);
1923         $this->assertEmpty($contact3->useridfrom);
1924         $this->assertFalse($contact3->ismessaging);
1925         $this->assertNull($contact3->lastmessage);
1926         $this->assertNull($contact3->messageid);
1927         $this->assertNull($contact3->isonline);
1928         $this->assertFalse($contact3->isread);
1929         $this->assertFalse($contact3->isblocked);
1930         $this->assertNull($contact3->unreadcount);
1931     }
1933     /**
1934      * Tests retrieving messages.
1935      */
1936     public function test_get_messages() {
1937         // Create some users.
1938         $user1 = self::getDataGenerator()->create_user();
1939         $user2 = self::getDataGenerator()->create_user();
1941         // The person doing the search.
1942         $this->setUser($user1);
1944         // Send some messages back and forth.
1945         $time = 1;
1946         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1947         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1948         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1949         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1951         // Retrieve the messages.
1952         $messages = \core_message\api::get_messages($user1->id, $user2->id);
1954         // Confirm the message data is correct.
1955         $this->assertEquals(4, count($messages));
1957         $message1 = $messages[0];
1958         $message2 = $messages[1];
1959         $message3 = $messages[2];
1960         $message4 = $messages[3];
1962         $this->assertEquals($user1->id, $message1->useridfrom);
1963         $this->assertEquals($user2->id, $message1->useridto);
1964         $this->assertTrue($message1->displayblocktime);
1965         $this->assertContains('Yo!', $message1->text);
1967         $this->assertEquals($user2->id, $message2->useridfrom);
1968         $this->assertEquals($user1->id, $message2->useridto);
1969         $this->assertFalse($message2->displayblocktime);
1970         $this->assertContains('Sup mang?', $message2->text);
1972         $this->assertEquals($user1->id, $message3->useridfrom);
1973         $this->assertEquals($user2->id, $message3->useridto);
1974         $this->assertFalse($message3->displayblocktime);
1975         $this->assertContains('Writing PHPUnit tests!', $message3->text);
1977         $this->assertEquals($user2->id, $message4->useridfrom);
1978         $this->assertEquals($user1->id, $message4->useridto);
1979         $this->assertFalse($message4->displayblocktime);
1980         $this->assertContains('Word.', $message4->text);
1981     }
1983     /**
1984      * Tests retrieving conversation messages.
1985      */
1986     public function test_get_conversation_messages() {
1987         // Create some users.
1988         $user1 = self::getDataGenerator()->create_user();
1989         $user2 = self::getDataGenerator()->create_user();
1991         // Create conversation.
1992         $conversation = \core_message\api::create_conversation(
1993             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1994             [$user1->id, $user2->id]
1995         );
1997         // The person doing the search.
1998         $this->setUser($user1);
2000         // Send some messages back and forth.
2001         $time = 1;
2002         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2003         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2004         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2005         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2007         // Retrieve the messages.
2008         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2010         // Confirm the conversation id is correct.
2011         $this->assertEquals($conversation->id, $convmessages['id']);
2013         // Confirm the message data is correct.
2014         $messages = $convmessages['messages'];
2015         $this->assertEquals(4, count($messages));
2016         $message1 = $messages[0];
2017         $message2 = $messages[1];
2018         $message3 = $messages[2];
2019         $message4 = $messages[3];
2021         $this->assertEquals($user1->id, $message1->useridfrom);
2022         $this->assertContains('Yo!', $message1->text);
2024         $this->assertEquals($user2->id, $message2->useridfrom);
2025         $this->assertContains('Sup mang?', $message2->text);
2027         $this->assertEquals($user1->id, $message3->useridfrom);
2028         $this->assertContains('Writing PHPUnit tests!', $message3->text);
2030         $this->assertEquals($user1->id, $message4->useridfrom);
2031         $this->assertContains('Word.', $message4->text);
2033         // Confirm the members data is correct.
2034         $members = $convmessages['members'];
2035         $this->assertEquals(2, count($members));
2036     }
2038     /**
2039      * Tests retrieving group conversation messages.
2040      */
2041     public function test_get_group_conversation_messages() {
2042         // Create some users.
2043         $user1 = self::getDataGenerator()->create_user();
2044         $user2 = self::getDataGenerator()->create_user();
2045         $user3 = self::getDataGenerator()->create_user();
2046         $user4 = self::getDataGenerator()->create_user();
2048         // Create group conversation.
2049         $conversation = \core_message\api::create_conversation(
2050             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2051             [$user1->id, $user2->id, $user3->id, $user4->id]
2052         );
2054         // The person doing the search.
2055         $this->setUser($user1);
2057         // Send some messages back and forth.
2058         $time = 1;
2059         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2060         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2061         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2062         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2063         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Yeah!', $time + 5);
2065         // Retrieve the messages.
2066         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2068         // Confirm the conversation id is correct.
2069         $this->assertEquals($conversation->id, $convmessages['id']);
2071         // Confirm the message data is correct.
2072         $messages = $convmessages['messages'];
2073         $this->assertEquals(5, count($messages));
2075         $message1 = $messages[0];
2076         $message2 = $messages[1];
2077         $message3 = $messages[2];
2078         $message4 = $messages[3];
2079         $message5 = $messages[4];
2081         $this->assertEquals($user1->id, $message1->useridfrom);
2082         $this->assertContains('Yo!', $message1->text);
2084         $this->assertEquals($user2->id, $message2->useridfrom);
2085         $this->assertContains('Sup mang?', $message2->text);
2087         $this->assertEquals($user3->id, $message3->useridfrom);
2088         $this->assertContains('Writing PHPUnit tests!', $message3->text);
2090         $this->assertEquals($user1->id, $message4->useridfrom);
2091         $this->assertContains('Word.', $message4->text);
2093         $this->assertEquals($user2->id, $message5->useridfrom);
2094         $this->assertContains('Yeah!', $message5->text);
2096         // Confirm the members data is correct.
2097         $members = $convmessages['members'];
2098         $this->assertEquals(3, count($members));
2099     }
2101     /**
2102      * Test verifying the sorting param for get_conversation_messages is respected().
2103      */
2104     public function test_get_conversation_messages_sorting() {
2105         // Create some users.
2106         $user1 = self::getDataGenerator()->create_user();
2107         $user2 = self::getDataGenerator()->create_user();
2108         $user3 = self::getDataGenerator()->create_user();
2110         // Create conversations - 1 group and 1 individual.
2111         $conversation = \core_message\api::create_conversation(
2112             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2113             [$user1->id, $user2->id]
2114         );
2115         $conversation2 = \core_message\api::create_conversation(
2116             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2117             [$user1->id, $user2->id, $user3->id]
2118         );
2120         // Send some messages back and forth.
2121         $time = 1;
2122         $m1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2123         $m2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2124         $m3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2125         $m4id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2127         $gm1id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Yo!', $time + 1);
2128         $gm2id = testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Sup mang?', $time + 2);
2129         $gm3id = testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'Writing PHPUnit tests!', $time + 3);
2130         $gm4id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Word.', $time + 4);
2132         // The person doing the search.
2133         $this->setUser($user1);
2135         // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2136         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2137         $messages = $convmessages['messages'];
2138         $this->assertEquals($m1id, $messages[0]->id);
2139         $this->assertEquals($m2id, $messages[1]->id);
2140         $this->assertEquals($m3id, $messages[2]->id);
2141         $this->assertEquals($m4id, $messages[3]->id);
2143         // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2144         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated DESC');
2145         $messages = $convmessages['messages'];
2146         $this->assertEquals($m1id, $messages[3]->id);
2147         $this->assertEquals($m2id, $messages[2]->id);
2148         $this->assertEquals($m3id, $messages[1]->id);
2149         $this->assertEquals($m4id, $messages[0]->id);
2151         // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2152         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id);
2153         $messages = $convmessages['messages'];
2154         $this->assertEquals($gm1id, $messages[0]->id);
2155         $this->assertEquals($gm2id, $messages[1]->id);
2156         $this->assertEquals($gm3id, $messages[2]->id);
2157         $this->assertEquals($gm4id, $messages[3]->id);
2159         // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2160         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id, 0, 0, 'timecreated DESC');
2161         $messages = $convmessages['messages'];
2162         $this->assertEquals($gm1id, $messages[3]->id);
2163         $this->assertEquals($gm2id, $messages[2]->id);
2164         $this->assertEquals($gm3id, $messages[1]->id);
2165         $this->assertEquals($gm4id, $messages[0]->id);
2166     }
2168     /**
2169      * Test retrieving conversation messages by providing a minimum timecreated value.
2170      */
2171     public function test_get_conversation_messages_time_from_only() {
2172         // Create some users.
2173         $user1 = self::getDataGenerator()->create_user();
2174         $user2 = self::getDataGenerator()->create_user();
2175         $user3 = self::getDataGenerator()->create_user();
2176         $user4 = self::getDataGenerator()->create_user();
2178         // Create group conversation.
2179         $conversation = \core_message\api::create_conversation(
2180             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2181             [$user1->id, $user2->id, $user3->id, $user4->id]
2182         );
2184         // The person doing the search.
2185         $this->setUser($user1);
2187         // Send some messages back and forth.
2188         $time = 1;
2189         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2190         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2191         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2192         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2194         // Retrieve the messages from $time, which should be all of them.
2195         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC', $time);
2197         // Confirm the conversation id is correct.
2198         $this->assertEquals($conversation->id, $convmessages['id']);
2200         // Confirm the message data is correct.
2201         $messages = $convmessages['messages'];
2202         $this->assertEquals(4, count($messages));
2204         $message1 = $messages[0];
2205         $message2 = $messages[1];
2206         $message3 = $messages[2];
2207         $message4 = $messages[3];
2209         $this->assertContains('Message 1', $message1->text);
2210         $this->assertContains('Message 2', $message2->text);
2211         $this->assertContains('Message 3', $message3->text);
2212         $this->assertContains('Message 4', $message4->text);
2214         // Confirm the members data is correct.
2215         $members = $convmessages['members'];
2216         $this->assertEquals(3, count($members));
2218         // Retrieve the messages from $time + 3, which should only be the 2 last messages.
2219         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2220             'timecreated ASC', $time + 3);
2222         // Confirm the conversation id is correct.
2223         $this->assertEquals($conversation->id, $convmessages['id']);
2225         // Confirm the message data is correct.
2226         $messages = $convmessages['messages'];
2227         $this->assertEquals(2, count($messages));
2229         $message1 = $messages[0];
2230         $message2 = $messages[1];
2232         $this->assertContains('Message 3', $message1->text);
2233         $this->assertContains('Message 4', $message2->text);
2235         // Confirm the members data is correct.
2236         $members = $convmessages['members'];
2237         $this->assertEquals(2, count($members));
2238     }
2240     /**
2241      * Test retrieving conversation messages by providing a maximum timecreated value.
2242      */
2243     public function test_get_conversation_messages_time_to_only() {
2244         // Create some users.
2245         $user1 = self::getDataGenerator()->create_user();
2246         $user2 = self::getDataGenerator()->create_user();
2247         $user3 = self::getDataGenerator()->create_user();
2248         $user4 = self::getDataGenerator()->create_user();
2250         // Create group conversation.
2251         $conversation = \core_message\api::create_conversation(
2252             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2253             [$user1->id, $user2->id, $user3->id, $user4->id]
2254         );
2256         // The person doing the search.
2257         $this->setUser($user1);
2259         // Send some messages back and forth.
2260         $time = 1;
2261         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2262         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2263         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2264         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2266         // Retrieve the messages up until $time + 4, which should be all of them.
2267         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2268             0, $time + 4);
2270         // Confirm the conversation id is correct.
2271         $this->assertEquals($conversation->id, $convmessages['id']);
2273         // Confirm the message data is correct.
2274         $messages = $convmessages['messages'];
2275         $this->assertEquals(4, count($messages));
2277         $message1 = $messages[0];
2278         $message2 = $messages[1];
2279         $message3 = $messages[2];
2280         $message4 = $messages[3];
2282         $this->assertContains('Message 1', $message1->text);
2283         $this->assertContains('Message 2', $message2->text);
2284         $this->assertContains('Message 3', $message3->text);
2285         $this->assertContains('Message 4', $message4->text);
2287         // Confirm the members data is correct.
2288         $members = $convmessages['members'];
2289         $this->assertEquals(3, count($members));
2291         // Retrieve the messages up until $time + 2, which should be the first two.
2292         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2293             0, $time + 2);
2295         // Confirm the conversation id is correct.
2296         $this->assertEquals($conversation->id, $convmessages['id']);
2298         // Confirm the message data is correct.
2299         $messages = $convmessages['messages'];
2300         $this->assertEquals(2, count($messages));
2302         $message1 = $messages[0];
2303         $message2 = $messages[1];
2305         $this->assertContains('Message 1', $message1->text);
2306         $this->assertContains('Message 2', $message2->text);
2308         // Confirm the members data is correct.
2309         $members = $convmessages['members'];
2310         $this->assertEquals(2, count($members));
2311     }
2313     /**
2314      * Test retrieving conversation messages by providing a minimum and maximum timecreated value.
2315      */
2316     public function test_get_conversation_messages_time_from_and_to() {
2317         // Create some users.
2318         $user1 = self::getDataGenerator()->create_user();
2319         $user2 = self::getDataGenerator()->create_user();
2320         $user3 = self::getDataGenerator()->create_user();
2321         $user4 = self::getDataGenerator()->create_user();
2323         // Create group conversation.
2324         $conversation = \core_message\api::create_conversation(
2325             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2326             [$user1->id, $user2->id, $user3->id, $user4->id]
2327         );
2329         // The person doing the search.
2330         $this->setUser($user1);
2332         // Send some messages back and forth.
2333         $time = 1;
2334         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2335         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2336         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2337         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2339         // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
2340         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2341             'timecreated ASC', $time + 2, $time + 3);
2343         // Confirm the conversation id is correct.
2344         $this->assertEquals($conversation->id, $convmessages['id']);
2346         // Confirm the message data is correct.
2347         $messages = $convmessages['messages'];
2348         $this->assertEquals(2, count($messages));
2350         $message1 = $messages[0];
2351         $message2 = $messages[1];
2353         $this->assertContains('Message 2', $message1->text);
2354         $this->assertContains('Message 3', $message2->text);
2356         // Confirm the members data is correct.
2357         $members = $convmessages['members'];
2358         $this->assertEquals(2, count($members));
2359     }
2362     /**
2363      * Test retrieving conversation messages by providing a limitfrom value.
2364      */
2365     public function test_get_conversation_messages_limitfrom_only() {
2366         // Create some users.
2367         $user1 = self::getDataGenerator()->create_user();
2368         $user2 = self::getDataGenerator()->create_user();
2369         $user3 = self::getDataGenerator()->create_user();
2370         $user4 = self::getDataGenerator()->create_user();
2372         // Create group conversation.
2373         $conversation = \core_message\api::create_conversation(
2374             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2375             [$user1->id, $user2->id, $user3->id, $user4->id]
2376         );
2378         // The person doing the search.
2379         $this->setUser($user1);
2381         // Send some messages back and forth.
2382         $time = 1;
2383         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2384         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2385         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2386         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2388         // Retrieve the messages from $time, which should be all of them.
2389         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2);
2391         // Confirm the conversation id is correct.
2392         $messages = $convmessages['messages'];
2393         $this->assertEquals($conversation->id, $convmessages['id']);
2395         // Confirm the message data is correct.
2396         $this->assertEquals(2, count($messages));
2398         $message1 = $messages[0];
2399         $message2 = $messages[1];
2401         $this->assertContains('Message 3', $message1->text);
2402         $this->assertContains('Message 4', $message2->text);
2404         // Confirm the members data is correct.
2405         $members = $convmessages['members'];
2406         $this->assertEquals(2, count($members));
2407     }
2409     /**
2410      * Test retrieving conversation messages by providing a limitnum value.
2411      */
2412     public function test_get_conversation_messages_limitnum() {
2413         // Create some users.
2414         $user1 = self::getDataGenerator()->create_user();
2415         $user2 = self::getDataGenerator()->create_user();
2416         $user3 = self::getDataGenerator()->create_user();
2417         $user4 = self::getDataGenerator()->create_user();
2419         // Create group conversation.
2420         $conversation = \core_message\api::create_conversation(
2421             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2422             [$user1->id, $user2->id, $user3->id, $user4->id]
2423         );
2425         // The person doing the search.
2426         $this->setUser($user1);
2428         // Send some messages back and forth.
2429         $time = 1;
2430         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2431         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2432         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2433         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2435         // Retrieve the messages from $time, which should be all of them.
2436         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2, 1);
2438         // Confirm the conversation id is correct.
2439         $messages = $convmessages['messages'];
2440         $this->assertEquals($conversation->id, $convmessages['id']);
2442         // Confirm the message data is correct.
2443         $messages = $convmessages['messages'];
2444         $this->assertEquals(1, count($messages));
2446         $message1 = $messages[0];
2448         $this->assertContains('Message 3', $message1->text);
2450         // Confirm the members data is correct.
2451         $members = $convmessages['members'];
2452         $this->assertEquals(1, count($members));
2453     }
2455     /**
2456      * Tests retrieving most recent message.
2457      */
2458     public function test_get_most_recent_message() {
2459         // Create some users.
2460         $user1 = self::getDataGenerator()->create_user();
2461         $user2 = self::getDataGenerator()->create_user();
2463         // The person doing the search.
2464         $this->setUser($user1);
2466         // Send some messages back and forth.
2467         $time = 1;
2468         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2469         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2470         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2471         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2473         // Retrieve the most recent messages.
2474         $message = \core_message\api::get_most_recent_message($user1->id, $user2->id);
2476         // Check the results are correct.
2477         $this->assertEquals($user2->id, $message->useridfrom);
2478         $this->assertEquals($user1->id, $message->useridto);
2479         $this->assertContains('Word.', $message->text);
2480     }
2482     /**
2483      * Tests retrieving most recent conversation message.
2484      */
2485     public function test_get_most_recent_conversation_message() {
2486         // Create some users.
2487         $user1 = self::getDataGenerator()->create_user();
2488         $user2 = self::getDataGenerator()->create_user();
2489         $user3 = self::getDataGenerator()->create_user();
2491         // Create group conversation.
2492         $conversation = \core_message\api::create_conversation(
2493             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2494             [$user1->id, $user2->id, $user3->id]
2495         );
2497         // The person getting the most recent conversation message.
2498         $this->setUser($user1);
2500         // Send some messages back and forth.
2501         $time = 1;
2502         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2503         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2504         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2505         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Word.', $time + 4);
2507         // Retrieve the most recent messages.
2508         $message = \core_message\api::get_most_recent_conversation_message($conversation->id, $user1->id);
2510         // Check the results are correct.
2511         $this->assertEquals($user2->id, $message->useridfrom);
2512         $this->assertContains('Word.', $message->text);
2513     }
2515     /**
2516      * Tests retrieving a user's profile.
2517      */
2518     public function test_get_profile() {
2519         // Create some users.
2520         $user1 = self::getDataGenerator()->create_user();
2522         $user2 = new stdClass();
2523         $user2->country = 'AU';
2524         $user2->city = 'Perth';
2525         $user2 = self::getDataGenerator()->create_user($user2);
2527         // The person doing the search.
2528         $this->setUser($user1);
2530         // Get the profile.
2531         $profile = \core_message\api::get_profile($user1->id, $user2->id);
2533         $this->assertEquals($user2->id, $profile->userid);
2534         $this->assertEmpty($profile->email);
2535         $this->assertEmpty($profile->country);
2536         $this->assertEmpty($profile->city);
2537         $this->assertEquals(fullname($user2), $profile->fullname);
2538         $this->assertNull($profile->isonline);
2539         $this->assertFalse($profile->isblocked);
2540         $this->assertFalse($profile->iscontact);
2541     }
2543     /**
2544      * Tests retrieving a user's profile.
2545      */
2546     public function test_get_profile_as_admin() {
2547         // The person doing the search.
2548         $this->setAdminUser();
2550         // Create some users.
2551         $user1 = self::getDataGenerator()->create_user();
2553         $user2 = new stdClass();
2554         $user2->country = 'AU';
2555         $user2->city = 'Perth';
2556         $user2 = self::getDataGenerator()->create_user($user2);
2558         // Get the profile.
2559         $profile = \core_message\api::get_profile($user1->id, $user2->id);
2561         $this->assertEquals($user2->id, $profile->userid);
2562         $this->assertEquals($user2->email, $profile->email);
2563         $this->assertEquals($user2->country, $profile->country);
2564         $this->assertEquals($user2->city, $profile->city);
2565         $this->assertEquals(fullname($user2), $profile->fullname);
2566         $this->assertFalse($profile->isonline);
2567         $this->assertFalse($profile->isblocked);
2568         $this->assertFalse($profile->iscontact);
2569     }
2571     /**
2572      * Tests checking if a user can mark all messages as read.
2573      */
2574     public function test_can_mark_all_messages_as_read() {
2575         // Set as the admin.
2576         $this->setAdminUser();
2578         // Create some users.
2579         $user1 = self::getDataGenerator()->create_user();
2580         $user2 = self::getDataGenerator()->create_user();
2581         $user3 = self::getDataGenerator()->create_user();
2583         // Send some messages back and forth.
2584         $time = 1;
2585         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2586         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2587         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2588         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2590         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2592         // The admin can do anything.
2593         $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
2595         // Set as the user 1.
2596         $this->setUser($user1);
2598         // The user can mark the messages as he is in the conversation.
2599         $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
2601         // User 1 can not mark the messages read for user 2.
2602         $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user2->id, $conversationid));
2604         // This user is not a part of the conversation.
2605         $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user3->id, $conversationid));
2606     }
2608     /**
2609      * Tests checking if a user can delete a conversation.
2610      */
2611     public function test_can_delete_conversation() {
2612         // Set as the admin.
2613         $this->setAdminUser();
2615         // Create some users.
2616         $user1 = self::getDataGenerator()->create_user();
2617         $user2 = self::getDataGenerator()->create_user();
2619         // Send some messages back and forth.
2620         $time = 1;
2621         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2622         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2623         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2624         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2626         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2628         // The admin can do anything.
2629         $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
2631         // Set as the user 1.
2632         $this->setUser($user1);
2634         // They can delete their own messages.
2635         $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
2637         // They can't delete someone elses.
2638         $this->assertFalse(\core_message\api::can_delete_conversation($user2->id, $conversationid));
2639     }
2641     /**
2642      * Tests deleting a conversation.
2643      */
2644     public function test_delete_conversation() {
2645         global $DB;
2647         // Create some users.
2648         $user1 = self::getDataGenerator()->create_user();
2649         $user2 = self::getDataGenerator()->create_user();
2651         // The person doing the search.
2652         $this->setUser($user1);
2654         // Send some messages back and forth.
2655         $time = 1;
2656         $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2657         $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2658         $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2659         $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2661         // Delete the conversation as user 1.
2662         \core_message\api::delete_conversation($user1->id, $user2->id);
2663         $this->assertDebuggingCalled();
2665         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2666         $this->assertCount(4, $muas);
2667         // Sort by id.
2668         ksort($muas);
2670         $mua1 = array_shift($muas);
2671         $mua2 = array_shift($muas);
2672         $mua3 = array_shift($muas);
2673         $mua4 = array_shift($muas);
2675         $this->assertEquals($user1->id, $mua1->userid);
2676         $this->assertEquals($m1id, $mua1->messageid);
2677         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
2679         $this->assertEquals($user1->id, $mua2->userid);
2680         $this->assertEquals($m2id, $mua2->messageid);
2681         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
2683         $this->assertEquals($user1->id, $mua3->userid);
2684         $this->assertEquals($m3id, $mua3->messageid);
2685         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
2687         $this->assertEquals($user1->id, $mua4->userid);
2688         $this->assertEquals($m4id, $mua4->messageid);
2689         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
2690     }
2692     /**
2693      * Tests deleting a conversation by conversation id.
2694      */
2695     public function test_delete_conversation_by_id() {
2696         global $DB;
2698         // Create some users.
2699         $user1 = self::getDataGenerator()->create_user();
2700         $user2 = self::getDataGenerator()->create_user();
2702         // The person doing the search.
2703         $this->setUser($user1);
2705         // Send some messages back and forth.
2706         $time = 1;
2707         $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2708         $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2709         $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2710         $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2712         // Delete the conversation as user 1.
2713         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2714         \core_message\api::delete_conversation_by_id($user1->id, $conversationid);
2716         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2717         $this->assertCount(4, $muas);
2718         // Sort by id.
2719         ksort($muas);
2721         $mua1 = array_shift($muas);
2722         $mua2 = array_shift($muas);
2723         $mua3 = array_shift($muas);
2724         $mua4 = array_shift($muas);
2726         $this->assertEquals($user1->id, $mua1->userid);
2727         $this->assertEquals($m1id, $mua1->messageid);
2728         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
2730         $this->assertEquals($user1->id, $mua2->userid);
2731         $this->assertEquals($m2id, $mua2->messageid);
2732         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
2734         $this->assertEquals($user1->id, $mua3->userid);
2735         $this->assertEquals($m3id, $mua3->messageid);
2736         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
2738         $this->assertEquals($user1->id, $mua4->userid);
2739         $this->assertEquals($m4id, $mua4->messageid);
2740         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
2741     }
2743     /**
2744      * Tests counting unread conversations.
2745      */
2746     public function test_count_unread_conversations() {
2747         $this->resetAfterTest(true);
2749         // Create some users.
2750         $user1 = self::getDataGenerator()->create_user();
2751         $user2 = self::getDataGenerator()->create_user();
2752         $user3 = self::getDataGenerator()->create_user();
2753         $user4 = self::getDataGenerator()->create_user();
2755         // The person wanting the conversation count.
2756         $this->setUser($user1);
2758         // Send some messages back and forth, have some different conversations with different users.
2759         $this->send_fake_message($user1, $user2, 'Yo!');
2760         $this->send_fake_message($user2, $user1, 'Sup mang?');
2761         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
2762         $this->send_fake_message($user2, $user1, 'Word.');
2764         $this->send_fake_message($user1, $user3, 'Booyah');
2765         $this->send_fake_message($user3, $user1, 'Whaaat?');
2766         $this->send_fake_message($user1, $user3, 'Nothing.');
2767         $this->send_fake_message($user3, $user1, 'Cool.');
2769         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
2770         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
2771         $this->send_fake_message($user1, $user4, 'Dope.');
2773         // Check the amount for the current user.
2774         $this->assertEquals(3, core_message\api::count_unread_conversations());
2776         // Check the amount for the second user.
2777         $this->assertEquals(1, core_message\api::count_unread_conversations($user2));
2778     }
2780     /**
2781      * Tests deleting a conversation.
2782      */
2783     public function test_get_all_message_preferences() {
2784         $user = self::getDataGenerator()->create_user();
2785         $this->setUser($user);
2787         // Set a couple of preferences to test.
2788         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
2789         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
2791         $processors = get_message_processors();
2792         $providers = message_get_providers_for_user($user->id);
2793         $prefs = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2795         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedin['popup']);
2796         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedoff['email']);
2797     }
2799     /**
2800      * Tests the user can post a message.
2801      */
2802     public function test_can_post_message() {
2803         // Create some users.
2804         $user1 = self::getDataGenerator()->create_user();
2805         $user2 = self::getDataGenerator()->create_user();
2807         // Set as the first user.
2808         $this->setUser($user1);
2810         // With the default privacy setting, users can't message them.
2811         $this->assertFalse(\core_message\api::can_post_message($user2));
2813         // Enrol users to the same course.
2814         $course = $this->getDataGenerator()->create_course();
2815         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
2816         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
2817         // After enrolling users to the course, they should be able to message them with the default privacy setting.
2818         $this->assertTrue(\core_message\api::can_post_message($user2));
2819     }
2821     /**
2822      * Tests the user can't post a message without proper capability.
2823      */
2824     public function test_can_post_message_without_sendmessage_cap() {
2825         global $DB;
2827         // Create some users.
2828         $user1 = self::getDataGenerator()->create_user();
2829         $user2 = self::getDataGenerator()->create_user();
2831         // Set as the user 1.
2832         $this->setUser($user1);
2834         // Remove the capability to send a message.
2835         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
2836         unassign_capability('moodle/site:sendmessage', $roleids['user'],
2837             context_system::instance());
2839         // Check that we can not post a message without the capability.
2840         $this->assertFalse(\core_message\api::can_post_message($user2));
2841     }
2843     /**
2844      * Tests the user can post a message when they are contact.
2845      */
2846     public function test_can_post_message_when_contact() {
2847         // Create some users.
2848         $user1 = self::getDataGenerator()->create_user();
2849         $user2 = self::getDataGenerator()->create_user();
2851         // Set as the first user.
2852         $this->setUser($user1);
2854         // Check that we can not send user2 a message.
2855         $this->assertFalse(\core_message\api::can_post_message($user2));
2857         // Add users as contacts.
2858         \core_message\api::add_contact($user1->id, $user2->id);
2860         // Check that the return result is now true.
2861         $this->assertTrue(\core_message\api::can_post_message($user2));
2862     }
2864     /**
2865      * Tests the user can't post a message if they are not a contact and the user
2866      * has requested messages only from contacts.
2867      */
2868     public function test_can_post_message_when_not_contact() {
2869         // Create some users.
2870         $user1 = self::getDataGenerator()->create_user();
2871         $user2 = self::getDataGenerator()->create_user();
2873         // Set as the first user.
2874         $this->setUser($user1);
2876         // Set the second user's preference to not receive messages from non-contacts.
2877         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
2879         // Check that we can not send user 2 a message.
2880         $this->assertFalse(\core_message\api::can_post_message($user2));
2881     }
2883     /**
2884      * Tests the user can't post a message if they are blocked.
2885      */
2886     public function test_can_post_message_when_blocked() {
2887         // Create some users.
2888         $user1 = self::getDataGenerator()->create_user();
2889         $user2 = self::getDataGenerator()->create_user();
2891         // Set the user.
2892         $this->setUser($user1);
2894         // Block the second user.
2895         \core_message\api::block_user($user1->id, $user2->id);
2897         // Check that the second user can no longer send the first user a message.
2898         $this->assertFalse(\core_message\api::can_post_message($user1, $user2));
2899     }
2901     /**
2902      * Tests the user can post a message when site-wide messaging setting is enabled,
2903      * even if they are not a contact and are not members of the same course.
2904      */
2905     public function test_can_post_message_site_messaging_setting() {
2906         // Create some users.
2907         $user1 = self::getDataGenerator()->create_user();
2908         $user2 = self::getDataGenerator()->create_user();
2910         // Set as the first user.
2911         $this->setUser($user1);
2913         // By default, user only can be messaged by contacts and members of any of his/her courses.
2914         $this->assertFalse(\core_message\api::can_post_message($user2));
2916         // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
2917         set_config('messagingallusers', true);
2919         // Set the second user's preference to receive messages from everybody.
2920         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
2922         // Check that we can send user2 a message.
2923         $this->assertTrue(\core_message\api::can_post_message($user2));
2925         // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
2926         // and members sharing a course with her.
2927         set_config('messagingallusers', false);
2929         // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
2930         $this->assertFalse(\core_message\api::can_post_message($user2));
2932         // Enrol users to the same course.
2933         $course = $this->getDataGenerator()->create_course();
2934         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
2935         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
2936         // Check that we can send user2 a message because they are sharing a course.
2937         $this->assertTrue(\core_message\api::can_post_message($user2));
2939         // Set the second user's preference to receive messages only from contacts.
2940         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
2941         // Check that now the user2 can't be contacted because user1 is not their contact.
2942         $this->assertFalse(\core_message\api::can_post_message($user2));
2944         // Make contacts user1 and user2.
2945         \core_message\api::add_contact($user2->id, $user1->id);
2946         // Check that we can send user2 a message because they are contacts.
2947         $this->assertTrue(\core_message\api::can_post_message($user2));
2948     }
2950     /**
2951      * Tests the user with the messageanyuser capability can post a message.
2952      */
2953     public function test_can_post_message_with_messageanyuser_cap() {
2954         global $DB;
2956         // Create some users.
2957         $teacher1 = self::getDataGenerator()->create_user();
2958         $student1 = self::getDataGenerator()->create_user();
2959         $student2 = self::getDataGenerator()->create_user();
2961         // Create users not enrolled in any course.
2962         $user1 = self::getDataGenerator()->create_user();
2964         // Create a course.
2965         $course1 = $this->getDataGenerator()->create_course();
2967         // Enrol the users in the course.
2968         $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher');
2969         $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student');
2970         $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student');
2972         // Set some student preferences to not receive messages from non-contacts.
2973         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $student1->id);
2975         // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
2976         $this->assertTrue(\core_message\api::can_post_message($student1, $teacher1));
2977         // Check that the teacher can't contact user1 because it's not his teacher.
2978         $this->assertFalse(\core_message\api::can_post_message($user1, $teacher1));
2980         // Remove the messageanyuser capability from the course1 for teachers.
2981         $coursecontext = context_course::instance($course1->id);
2982         $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
2983         assign_capability('moodle/site:messageanyuser', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
2984         $coursecontext->mark_dirty();
2986         // Check that we can't send user1 a message because they are not contacts.
2987         $this->assertFalse(\core_message\api::can_post_message($student1, $teacher1));
2988         // However, teacher can message student2 because they are sharing a course.
2989         $this->assertTrue(\core_message\api::can_post_message($student2, $teacher1));
2990     }
2992     /**
2993      * Verify the expected behaviour of the can_send_message_to_conversation() method for authenticated users with default settings.
2994      */
2995     public function test_can_send_message_to_conversation_basic() {
2996         // Create some users.
2997         $user1 = self::getDataGenerator()->create_user();
2998         $user2 = self::getDataGenerator()->create_user();
2999         $user3 = self::getDataGenerator()->create_user();
3001         // Create an individual conversation between user1 and user2.
3002         $ic1 = \core_message\api::create_conversation(
3003             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3004             [
3005                 $user1->id,
3006                 $user2->id
3007             ]
3008         );
3010         // Create a group conversation between and users 1, 2 and 3.
3011         $gc1 = \core_message\api::create_conversation(
3012             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3013             [
3014                 $user1->id,
3015                 $user2->id,
3016                 $user3->id
3017             ]
3018         );
3020         // For group conversations, there are no user privacy checks, so only membership in the conversation is needed.
3021         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3023         // For individual conversations, the default privacy setting of 'only contacts and course members' applies.
3024         // Users are not in the same course, nor are they contacts, so messages cannot be sent.
3025         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3027         // Enrol the users into the same course.
3028         $course = $this->getDataGenerator()->create_course();
3029         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3030         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3032         // After enrolling users to the course, they should be able to message them with the default privacy setting.
3033         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3034     }
3036     /**
3037      * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the sendmessage capability.
3038      */
3039     public function test_can_send_message_to_conversation_sendmessage_cap() {
3040         global $DB;
3042         $user1 = self::getDataGenerator()->create_user();
3043         $user2 = self::getDataGenerator()->create_user();
3044         $user3 = self::getDataGenerator()->create_user();
3046         // Enrol the users into the same course.
3047         $course = $this->getDataGenerator()->create_course();
3048         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3049         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3050         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3052         // Create an individual conversation between user1 and user2.
3053         $ic1 = \core_message\api::create_conversation(
3054             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3055             [
3056                 $user1->id,
3057                 $user2->id
3058             ]
3059         );
3061         // Group conversation between and users 1, 2 and 3.
3062         $gc1 = \core_message\api::create_conversation(
3063             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3064             [
3065                 $user1->id,
3066                 $user2->id,
3067                 $user3->id
3068             ]
3069         );
3071         // Default settings - user1 can send a message to both conversations.
3072         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3073         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3075         // Remove the capability to send a message.
3076         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3077         unassign_capability('moodle/site:sendmessage', $roleids['user'], context_system::instance());
3079         // Verify that a user cannot send a message to either an individual or a group conversation.
3080         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3081         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3082     }
3084     /**
3085      * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the messageanyuser capability.
3086      */
3087     public function test_can_send_message_to_conversation_messageanyuser_cap() {
3088         global $DB;
3090         $user1 = self::getDataGenerator()->create_user();
3091         $user2 = self::getDataGenerator()->create_user();
3092         $user3 = self::getDataGenerator()->create_user();
3094         // Enrol the users into the same course.
3095         $course = $this->getDataGenerator()->create_course();
3096         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3097         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3098         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3100         // Create an individual conversation between user1 and user2.
3101         $ic1 = \core_message\api::create_conversation(
3102             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3103             [
3104                 $user1->id,
3105                 $user2->id
3106             ]
3107         );
3109         // Group conversation between and users 1, 2 and 3.
3110         $gc1 = \core_message\api::create_conversation(
3111             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3112             [
3113                 $user1->id,
3114                 $user2->id,
3115                 $user3->id
3116             ]
3117         );
3119         // Update the message preference for user2, so they can only be messaged by contacts.
3120         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3122         // Verify that the user cannot be contacted in the individual conversation and that groups are unaffected.
3123         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3124         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3126         // Assign the 'messageanyuser' capability to user1 at system context.
3127         $systemcontext = context_system::instance();
3128         $authenticateduser = $DB->get_record('role', ['shortname' => 'user']);
3129         assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, $systemcontext->id);
3131         // Check that user1 can now message user2 due to the capability, and that group conversations is again unaffected.
3132         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3133         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3134     }
3136     /**
3137      * Test verifying that users cannot send messages to conversations they are not a part of.
3138      */
3139     public function test_can_post_message_to_conversation_non_member() {
3140         // Create some users.
3141         $user1 = self::getDataGenerator()->create_user();
3142         $user2 = self::getDataGenerator()->create_user();
3143         $user3 = self::getDataGenerator()->create_user();
3144         $user4 = self::getDataGenerator()->create_user();
3146         // Enrol the users into the same course.
3147         $course = $this->getDataGenerator()->create_course();
3148         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3149         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3150         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3151         $this->getDataGenerator()->enrol_user($user4->id, $course->id);
3153         // Create an individual conversation between user1 and user2.
3154         $ic1 = \core_message\api::create_conversation(
3155             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3156             [
3157                 $user1->id,
3158                 $user2->id
3159             ]
3160         );
3162         // Create a group conversation between and users 1, 2 and 3.
3163         $gc1 = \core_message\api::create_conversation(
3164             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3165             [
3166                 $user1->id,
3167                 $user2->id,
3168                 $user3->id
3169             ]
3170         );
3172         // Verify, non members cannot send a message.
3173         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $gc1->id));
3174         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user4->id, $ic1->id));
3175     }
3177     /**
3178      * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts only.
3179      */
3180     public function test_can_send_message_to_conversation_privacy_contacts_only() {
3181         // Create some users.
3182         $user1 = self::getDataGenerator()->create_user();
3183         $user2 = self::getDataGenerator()->create_user();
3184         $user3 = self::getDataGenerator()->create_user();
3186         // Create an individual conversation between user1 and user2.
3187         $ic1 = \core_message\api::create_conversation(
3188             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3189             [
3190                 $user1->id,
3191                 $user2->id
3192             ]
3193         );
3195         // Create a group conversation between and users 1, 2 and 3.
3196         $gc1 = \core_message\api::create_conversation(
3197             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3198             [
3199                 $user1->id,
3200                 $user2->id,
3201                 $user3->id
3202             ]
3203         );
3205         // Set the message privacy preference to 'contacts only' for user 2.
3206         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3208         // Verify that user1 cannot send a message to the individual conversation, but that the group conversation is unaffected.
3209         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3210         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3212         // Now, simulate a contact request (and approval) between user1 and user2.
3213         \core_message\api::create_contact_request($user1->id, $user2->id);
3214         \core_message\api::confirm_contact_request($user1->id, $user2->id);
3216         // Verify user1 can now message user2 again via their individual conversation.
3217         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3218     }
3220     /**
3221      * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts / course members.
3222      */
3223     public function test_can_send_message_to_conversation_privacy_contacts_course() {
3224         // Create some users.
3225         $user1 = self::getDataGenerator()->create_user();
3226         $user2 = self::getDataGenerator()->create_user();
3227         $user3 = self::getDataGenerator()->create_user();
3229         // Set the message privacy preference to 'contacts + course members' for user 2.
3230         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
3232         // Create an individual conversation between user1 and user2.
3233         $ic1 = \core_message\api::create_conversation(
3234             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3235             [
3236                 $user1->id,
3237                 $user2->id
3238             ]
3239         );
3241         // Create a group conversation between and users 1, 2 and 3.
3242         $gc1 = \core_message\api::create_conversation(
3243             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3244             [
3245                 $user1->id,
3246                 $user2->id,
3247                 $user3->id
3248             ]
3249         );
3251         // Verify that users in a group conversation can message one another (i.e. privacy controls ignored).
3252         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $gc1->id));
3254         // Verify that user1 can not message user2 unless they are either contacts, or share a course.
3255         $this->assertFalse(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3257         // Enrol the users into the same course.
3258         $course = $this->getDataGenerator()->create_course();
3259         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3260         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3261         $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3263         // Verify that user1 can send a message to user2, based on the shared course, without being a contact.
3264         $this->assertFalse(\core_message\api::is_contact($user1->id, $user2->id));
3265         $this->assertTrue(\core_message\api::can_send_message_to_conversation($user1->id, $ic1->id));
3266     }
3268     /**
3269      * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to any user.
3270      */
3271     public function test_can_send_message_to_conversation_privacy_sitewide() {
3272         // Create some users.
3273         $user1 = self::getDataGenerator()->create_user();
3274         $user2 = self::getDataGenerator()->create_user();
3275         $user3 = self::getDataGenerator()->create_user();
3277         // Create an individual conversation between user1 and user2.
3278         $ic1 = \core_message\api::create_conversation(
3279             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3280             [
3281                 $user1->id,
3282                 $user2->id
3283             ]
3284         );
3286         // Create a group conversation between and users 1, 2 and 3.
3287         $gc1 = \core_message\api::create_conversation(
3288             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3289             [
3290                 $user1->id,
3291                 $user2->id,
3292                 $user3->id
3293             ]
3294         );
3296         // By default, the messaging privacy dictates that users can only be contacted by contacts, and members of their courses.