MDL-63923: core_my: card sizes clean and boost
[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             }
1093             $this->assertObjectHasAttribute('messages', $conv);
1094             foreach ($conv->messages as $message) {
1095                 $this->assertObjectHasAttribute('id', $message);
1096                 $this->assertObjectHasAttribute('useridfrom', $message);
1097                 $this->assertObjectHasAttribute('text', $message);
1098                 $this->assertObjectHasAttribute('timecreated', $message);
1099             }
1100         }
1101     }
1103     /**
1104      * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately.
1105      */
1106     public function test_get_conversations_message_format() {
1107         global $DB;
1108         // Create some users.
1109         $user1 = self::getDataGenerator()->create_user();
1110         $user2 = self::getDataGenerator()->create_user();
1112         // Create conversation.
1113         $conversation = \core_message\api::create_conversation(
1114             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1115             [$user1->id, $user2->id]
1116         );
1118         // Send some messages back and forth.
1119         $time = 1;
1120         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1);
1121         $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2);
1123         // Verify the format of the html message.
1124         $message = $DB->get_record('messages', ['id' => $mid]);
1125         $expectedmessagetext = message_format_message_text($message);
1126         $conversations = \core_message\api::get_conversations($user1->id);
1127         $messages = $conversations[0]->messages;
1128         $this->assertEquals($expectedmessagetext, $messages[0]->text);
1129     }
1131     /**
1132      * Tests retrieving conversations with a limit and offset to ensure pagination works correctly.
1133      */
1134     public function test_get_conversations_limit_offset() {
1135         // Get a bunch of conversations, some group, some individual and in different states.
1136         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1137             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1139         // Get all conversations for user1, limited to 1 result.
1140         $conversations = core_message\api::get_conversations($user1->id, 0, 1);
1142         // Verify the first conversation.
1143         $this->assertCount(1, $conversations);
1144         $conversation = array_shift($conversations);
1145         $this->assertEquals($conversation->id, $gc3->id);
1147         // Verify the next conversation.
1148         $conversations = \core_message\api::get_conversations($user1->id, 1, 1);
1149         $this->assertCount(1, $conversations);
1150         $this->assertEquals($gc2->id, $conversations[0]->id);
1152         // Verify the next conversation.
1153         $conversations = \core_message\api::get_conversations($user1->id, 2, 1);
1154         $this->assertCount(1, $conversations);
1155         $this->assertEquals($ic2->id, $conversations[0]->id);
1157         // Skip one and get both empty conversations.
1158         $conversations = \core_message\api::get_conversations($user1->id, 4, 2);
1159         $this->assertCount(2, $conversations);
1160         $this->assertEquals($gc5->id, $conversations[0]->id);
1161         $this->assertEmpty($conversations[0]->messages);
1162         $this->assertEquals($gc4->id, $conversations[1]->id);
1163         $this->assertEmpty($conversations[1]->messages);
1165         // Ask for an offset that doesn't exist and verify no conversations are returned.
1166         $conversations = \core_message\api::get_conversations($user1->id, 10, 1);
1167         $this->assertCount(0, $conversations);
1168     }
1170     /**
1171      * Test verifying the type filtering behaviour of the
1172      */
1173     public function test_get_conversations_type_filter() {
1174         // Get a bunch of conversations, some group, some individual and in different states.
1175         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1176             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1178         // Verify we can ask for only individual conversations.
1179         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1180             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1181         $this->assertCount(2, $conversations);
1183         // Verify we can ask for only group conversations.
1184         $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1185             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP);
1186         $this->assertCount(4, $conversations);
1188         // Verify an exception is thrown if an unrecognized type is specified.
1189         $this->expectException(\moodle_exception::class);
1190         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 0);
1191     }
1193     /**
1194      * Tests retrieving conversations when a conversation contains a deleted user.
1195      */
1196     public function test_get_conversations_with_deleted_user() {
1197         // Get a bunch of conversations, some group, some individual and in different states.
1198         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1199             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1201         // Delete the second user and retrieve the conversations.
1202         // We should have 5, as $ic1 drops off the list.
1203         // Group conversations remain albeit with less members.
1204         delete_user($user2);
1205         $conversations = \core_message\api::get_conversations($user1->id);
1206         $this->assertCount(5, $conversations);
1207         $this->assertEquals($gc3->id, $conversations[0]->id);
1208         $this->assertcount(1, $conversations[0]->members);
1209         $this->assertEquals($gc2->id, $conversations[1]->id);
1210         $this->assertcount(1, $conversations[1]->members);
1211         $this->assertEquals($ic2->id, $conversations[2]->id);
1212         $this->assertEquals($gc5->id, $conversations[3]->id);
1213         $this->assertEquals($gc4->id, $conversations[4]->id);
1215         // Delete a user from a group conversation where that user had sent the most recent message.
1216         // This user will still be present in the members array, as will the message in the messages array.
1217         delete_user($user4);
1218         $conversations = \core_message\api::get_conversations($user1->id);
1219         $this->assertCount(5, $conversations);
1220         $this->assertEquals($gc2->id, $conversations[1]->id);
1221         $this->assertcount(1, $conversations[1]->members);
1222         $this->assertEquals($user4->id, $conversations[1]->members[$user4->id]->id);
1223         $this->assertcount(1, $conversations[1]->messages);
1224         $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1226         // Delete the third user and retrieve the conversations.
1227         // We should have 4, as $ic1, $ic2 drop off the list.
1228         // Group conversations remain albeit with less members.
1229         delete_user($user3);
1230         $conversations = \core_message\api::get_conversations($user1->id);
1231         $this->assertCount(4, $conversations);
1232         $this->assertEquals($gc3->id, $conversations[0]->id);
1233         $this->assertcount(1, $conversations[0]->members);
1234         $this->assertEquals($gc2->id, $conversations[1]->id);
1235         $this->assertcount(1, $conversations[1]->members);
1236         $this->assertEquals($gc5->id, $conversations[2]->id);
1237         $this->assertEquals($gc4->id, $conversations[3]->id);
1238     }
1240     /**
1241      * Test confirming the behaviour of get_conversations() when users delete all messages.
1242      */
1243     public function test_get_conversations_deleted_messages() {
1244         // Get a bunch of conversations, some group, some individual and in different states.
1245         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1246             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1248         $conversations = \core_message\api::get_conversations($user1->id);
1249         $this->assertCount(6, $conversations);
1251         // Delete all messages from a group conversation the user is in - it should be returned.
1252         $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $gc2->id));
1253         $convmessages = \core_message\api::get_conversation_messages($user1->id, $gc2->id);
1254         $messages = $convmessages['messages'];
1255         foreach ($messages as $message) {
1256             \core_message\api::delete_message($user1->id, $message->id);
1257         }
1258         $conversations = \core_message\api::get_conversations($user1->id);
1259         $this->assertCount(6, $conversations);
1260         $this->assertContains($gc2->id, array_column($conversations, 'id'));
1262         // Delete all messages from an individual conversation the user is in - it should not be returned.
1263         $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $ic1->id));
1264         $convmessages = \core_message\api::get_conversation_messages($user1->id, $ic1->id);
1265         $messages = $convmessages['messages'];
1266         foreach ($messages as $message) {
1267             \core_message\api::delete_message($user1->id, $message->id);
1268         }
1269         $conversations = \core_message\api::get_conversations($user1->id);
1270         $this->assertCount(5, $conversations);
1271         $this->assertNotContains($ic1->id, array_column($conversations, 'id'));
1272     }
1274     /**
1275      * Test verifying the behaviour of get_conversations() when fetching favourite conversations.
1276      */
1277     public function test_get_conversations_favourite_conversations() {
1278         // Get a bunch of conversations, some group, some individual and in different states.
1279         list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1280             $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1282         // Try to get ONLY favourite conversations, when no favourites exist.
1283         $this->assertEquals([], \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1285         // Try to get NO favourite conversations, when no favourites exist.
1286         $this->assertCount(6, \core_message\api::get_conversations($user1->id, 0, 20, null, false));
1288         // Mark a few conversations as favourites.
1289         \core_message\api::set_favourite_conversation($ic1->id, $user1->id);
1290         \core_message\api::set_favourite_conversation($gc2->id, $user1->id);
1291         \core_message\api::set_favourite_conversation($gc5->id, $user1->id);
1293         // Get the conversations, first with no restrictions, confirming the favourite status of the conversations.
1294         $conversations = \core_message\api::get_conversations($user1->id);
1295         $this->assertCount(6, $conversations);
1296         foreach ($conversations as $conv) {
1297             if (in_array($conv->id, [$ic1->id, $gc2->id, $gc5->id])) {
1298                 $this->assertTrue($conv->isfavourite);
1299             }
1300         }
1302         // Now, get ONLY favourite conversations.
1303         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1304         $this->assertCount(3, $conversations);
1305         foreach ($conversations as $conv) {
1306             $this->assertTrue($conv->isfavourite);
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->assertCount(2, $conversations);
1313         foreach ($conversations as $conv) {
1314             $this->assertTrue($conv->isfavourite);
1315         }
1317         // And NO favourite conversations.
1318         $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1319         $this->assertCount(3, $conversations);
1320         foreach ($conversations as $conv) {
1321             $this->assertFalse($conv->isfavourite);
1322         }
1323     }
1325     /**
1326      * Test verifying that group linked conversations are returned and contain a subname matching the course name.
1327      */
1328     public function test_get_conversations_group_linked() {
1329         global $CFG;
1331         // Create some users.
1332         $user1 = self::getDataGenerator()->create_user();
1333         $user2 = self::getDataGenerator()->create_user();
1334         $user3 = self::getDataGenerator()->create_user();
1336         $course1 = $this->getDataGenerator()->create_course();
1338         // Create a group with a linked conversation and a valid image.
1339         $this->setAdminUser();
1340         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1341         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1342         $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
1343         $group1 = $this->getDataGenerator()->create_group([
1344             'courseid' => $course1->id,
1345             'enablemessaging' => 1,
1346             'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
1347         ]);
1349         // Add users to group1.
1350         $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1351         $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
1353         // Verify the group with the image works as expected.
1354         $conversations = \core_message\api::get_conversations($user1->id);
1355         $this->assertEquals(2, $conversations[0]->membercount);
1356         $this->assertEquals($course1->shortname, $conversations[0]->subname);
1357         $groupimageurl = get_group_picture_url($group1, $group1->courseid, true);
1358         $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1360         // Create a group with a linked conversation and without any image.
1361         $group2 = $this->getDataGenerator()->create_group([
1362             'courseid' => $course1->id,
1363             'enablemessaging' => 1,
1364         ]);
1366         // Add users to group2.
1367         $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1368         $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id));
1370         // Verify the group without any image works as expected too.
1371         $conversations = \core_message\api::get_conversations($user3->id);
1372         $this->assertEquals(2, $conversations[0]->membercount);
1373         $this->assertEquals($course1->shortname, $conversations[0]->subname);
1374         $groupimageurl = get_group_picture_url($group2, $group2->courseid, true);
1375         $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1376     }
1378    /**
1379     * The data provider for get_conversations_mixed.
1380     *
1381     * This provides sets of data to for testing.
1382     * @return array
1383     */
1384    public function get_conversations_mixed_provider() {
1385        return array(
1386             'Test that conversations with messages contacts is correctly ordered.' => array(
1387                 'users' => array(
1388                     'user1',
1389                     'user2',
1390                     'user3',
1391                 ),
1392                 'contacts' => array(
1393                 ),
1394                 'messages' => array(
1395                     array(
1396                         'from'          => 'user1',
1397                         'to'            => 'user2',
1398                         'state'         => 'unread',
1399                         'subject'       => 'S1',
1400                     ),
1401                     array(
1402                         'from'          => 'user2',
1403                         'to'            => 'user1',
1404                         'state'         => 'unread',
1405                         'subject'       => 'S2',
1406                     ),
1407                     array(
1408                         'from'          => 'user1',
1409                         'to'            => 'user2',
1410                         'state'         => 'unread',
1411                         'timecreated'   => 0,
1412                         'subject'       => 'S3',
1413                     ),
1414                     array(
1415                         'from'          => 'user1',
1416                         'to'            => 'user3',
1417                         'state'         => 'read',
1418                         'timemodifier'  => 1,
1419                         'subject'       => 'S4',
1420                     ),
1421                     array(
1422                         'from'          => 'user3',
1423                         'to'            => 'user1',
1424                         'state'         => 'read',
1425                         'timemodifier'  => 1,
1426                         'subject'       => 'S5',
1427                     ),
1428                     array(
1429                         'from'          => 'user1',
1430                         'to'            => 'user3',
1431                         'state'         => 'read',
1432                         'timecreated'   => 0,
1433                         'subject'       => 'S6',
1434                     ),
1435                 ),
1436                 'expectations' => array(
1437                     'user1' => array(
1438                         // User1 has conversed most recently with user3. The most recent message is M5.
1439                         array(
1440                             'messageposition'   => 0,
1441                             'with'              => 'user3',
1442                             'subject'           => '<p>S5</p>',
1443                             'unreadcount'       => 0,
1444                         ),
1445                         // User1 has also conversed with user2. The most recent message is S2.
1446                         array(
1447                             'messageposition'   => 1,
1448                             'with'              => 'user2',
1449                             'subject'           => '<p>S2</p>',
1450                             'unreadcount'       => 1,
1451                         ),
1452                     ),
1453                     'user2' => array(
1454                         // User2 has only conversed with user1. Their most recent shared message was S2.
1455                         array(
1456                             'messageposition'   => 0,
1457                             'with'              => 'user1',
1458                             'subject'           => '<p>S2</p>',
1459                             'unreadcount'       => 2,
1460                         ),
1461                     ),
1462                     'user3' => array(
1463                         // User3 has only conversed with user1. Their most recent shared message was S5.
1464                         array(
1465                             'messageposition'   => 0,
1466                             'with'              => 'user1',
1467                             'subject'           => '<p>S5</p>',
1468                             'unreadcount'       => 0,
1469                         ),
1470                     ),
1471                 ),
1472             ),
1473             'Test conversations with a single user, where some messages are read and some are not.' => array(
1474                 'users' => array(
1475                     'user1',
1476                     'user2',
1477                 ),
1478                 'contacts' => array(
1479                 ),
1480                 'messages' => array(
1481                     array(
1482                         'from'          => 'user1',
1483                         'to'            => 'user2',
1484                         'state'         => 'read',
1485                         'subject'       => 'S1',
1486                     ),
1487                     array(
1488                         'from'          => 'user2',
1489                         'to'            => 'user1',
1490                         'state'         => 'read',
1491                         'subject'       => 'S2',
1492                     ),
1493                     array(
1494                         'from'          => 'user1',
1495                         'to'            => 'user2',
1496                         'state'         => 'unread',
1497                         'timemodifier'  => 1,
1498                         'subject'       => 'S3',
1499                     ),
1500                     array(
1501                         'from'          => 'user1',
1502                         'to'            => 'user2',
1503                         'state'         => 'unread',
1504                         'timemodifier'  => 1,
1505                         'subject'       => 'S4',
1506                     ),
1507                 ),
1508                 'expectations' => array(
1509                     // The most recent message between user1 and user2 was S4.
1510                     'user1' => array(
1511                         array(
1512                             'messageposition'   => 0,
1513                             'with'              => 'user2',
1514                             'subject'           => '<p>S4</p>',
1515                             'unreadcount'       => 0,
1516                         ),
1517                     ),
1518                     'user2' => array(
1519                         // The most recent message between user1 and user2 was S4.
1520                         array(
1521                             'messageposition'   => 0,
1522                             'with'              => 'user1',
1523                             'subject'           => '<p>S4</p>',
1524                             'unreadcount'       => 2,
1525                         ),
1526                     ),
1527                 ),
1528             ),
1529             'Test conversations with a single user, where some messages are read and some are not, and messages ' .
1530             'are out of order' => array(
1531             // This can happen through a combination of factors including multi-master DB replication with messages
1532             // read somehow (e.g. API).
1533                 'users' => array(
1534                     'user1',
1535                     'user2',
1536                 ),
1537                 'contacts' => array(
1538                 ),
1539                 'messages' => array(
1540                     array(
1541                         'from'          => 'user1',
1542                         'to'            => 'user2',
1543                         'state'         => 'read',
1544                         'subject'       => 'S1',
1545                         'timemodifier'  => 1,
1546                     ),
1547                     array(
1548                         'from'          => 'user2',
1549                         'to'            => 'user1',
1550                         'state'         => 'read',
1551                         'subject'       => 'S2',
1552                         'timemodifier'  => 2,
1553                     ),
1554                     array(
1555                         'from'          => 'user1',
1556                         'to'            => 'user2',
1557                         'state'         => 'unread',
1558                         'subject'       => 'S3',
1559                     ),
1560                     array(
1561                         'from'          => 'user1',
1562                         'to'            => 'user2',
1563                         'state'         => 'unread',
1564                         'subject'       => 'S4',
1565                     ),
1566                 ),
1567                 'expectations' => array(
1568                     // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1569                     'user1' => array(
1570                         array(
1571                             'messageposition'   => 0,
1572                             'with'              => 'user2',
1573                             'subject'           => '<p>S2</p>',
1574                             'unreadcount'       => 0,
1575                         ),
1576                     ),
1577                     'user2' => array(
1578                         array(
1579                             'messageposition'   => 0,
1580                             'with'              => 'user1',
1581                             'subject'           => '<p>S2</p>',
1582                             'unreadcount'       => 2
1583                         ),
1584                     ),
1585                 ),
1586             ),
1587             'Test unread message count is correct for both users' => 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                         'timemodifier'  => 1,
1601                     ),
1602                     array(
1603                         'from'          => 'user2',
1604                         'to'            => 'user1',
1605                         'state'         => 'read',
1606                         'subject'       => 'S2',
1607                         'timemodifier'  => 2,
1608                     ),
1609                     array(
1610                         'from'          => 'user1',
1611                         'to'            => 'user2',
1612                         'state'         => 'read',
1613                         'subject'       => 'S3',
1614                         'timemodifier'  => 3,
1615                     ),
1616                     array(
1617                         'from'          => 'user1',
1618                         'to'            => 'user2',
1619                         'state'         => 'read',
1620                         'subject'       => 'S4',
1621                         'timemodifier'  => 4,
1622                     ),
1623                     array(
1624                         'from'          => 'user1',
1625                         'to'            => 'user2',
1626                         'state'         => 'unread',
1627                         'subject'       => 'S5',
1628                         'timemodifier'  => 5,
1629                     ),
1630                     array(
1631                         'from'          => 'user2',
1632                         'to'            => 'user1',
1633                         'state'         => 'unread',
1634                         'subject'       => 'S6',
1635                         'timemodifier'  => 6,
1636                     ),
1637                     array(
1638                         'from'          => 'user1',
1639                         'to'            => 'user2',
1640                         'state'         => 'unread',
1641                         'subject'       => 'S7',
1642                         'timemodifier'  => 7,
1643                     ),
1644                     array(
1645                         'from'          => 'user1',
1646                         'to'            => 'user2',
1647                         'state'         => 'unread',
1648                         'subject'       => 'S8',
1649                         'timemodifier'  => 8,
1650                     ),
1651                 ),
1652                 'expectations' => array(
1653                     // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1654                     'user1' => array(
1655                         array(
1656                             'messageposition'   => 0,
1657                             'with'              => 'user2',
1658                             'subject'           => '<p>S8</p>',
1659                             'unreadcount'       => 1,
1660                         ),
1661                     ),
1662                     'user2' => array(
1663                         array(
1664                             'messageposition'   => 0,
1665                             'with'              => 'user1',
1666                             'subject'           => '<p>S8</p>',
1667                             'unreadcount'       => 3,
1668                         ),
1669                     ),
1670                 ),
1671             ),
1672         );
1673     }
1675     /**
1676      * Test get_conversations with a mixture of messages.
1677      *
1678      * @dataProvider get_conversations_mixed_provider
1679      * @param array $usersdata The list of users to create for this test.
1680      * @param array $messagesdata The list of messages to create.
1681      * @param array $expectations The list of expected outcomes.
1682      */
1683     public function test_get_conversations_mixed($usersdata, $contacts, $messagesdata, $expectations) {
1684         global $DB;
1686         // Create all of the users.
1687         $users = array();
1688         foreach ($usersdata as $username) {
1689             $users[$username] = $this->getDataGenerator()->create_user(array('username' => $username));
1690         }
1692         foreach ($contacts as $username => $contact) {
1693             foreach ($contact as $contactname => $blocked) {
1694                 $record = new stdClass();
1695                 $record->userid     = $users[$username]->id;
1696                 $record->contactid  = $users[$contactname]->id;
1697                 $record->blocked    = $blocked;
1698                 $record->id = $DB->insert_record('message_contacts', $record);
1699             }
1700         }
1702         $defaulttimecreated = time();
1703         foreach ($messagesdata as $messagedata) {
1704             $from       = $users[$messagedata['from']];
1705             $to         = $users[$messagedata['to']];
1706             $subject    = $messagedata['subject'];
1708             if (isset($messagedata['state']) && $messagedata['state'] == 'unread') {
1709                 $messageid = $this->send_fake_message($from, $to, $subject);
1710             } else {
1711                 // If there is no state, or the state is not 'unread', assume the message is read.
1712                 $messageid = message_post_message($from, $to, $subject, FORMAT_PLAIN);
1713             }
1715             $updatemessage = new stdClass();
1716             $updatemessage->id = $messageid;
1717             if (isset($messagedata['timecreated'])) {
1718                 $updatemessage->timecreated = $messagedata['timecreated'];
1719             } else if (isset($messagedata['timemodifier'])) {
1720                 $updatemessage->timecreated = $defaulttimecreated + $messagedata['timemodifier'];
1721             } else {
1722                 $updatemessage->timecreated = $defaulttimecreated;
1723             }
1725             $DB->update_record('messages', $updatemessage);
1726         }
1728         foreach ($expectations as $username => $data) {
1729             // Get the recent conversations for the specified user.
1730             $user = $users[$username];
1731             $conversations = array_values(\core_message\api::get_conversations($user->id));
1732             foreach ($data as $expectation) {
1733                 $otheruser = $users[$expectation['with']];
1734                 $conversation = $conversations[$expectation['messageposition']];
1735                 $this->assertEquals($otheruser->id, $conversation->members[$otheruser->id]->id);
1736                 $this->assertEquals($expectation['subject'], $conversation->messages[0]->text);
1737                 $this->assertEquals($expectation['unreadcount'], $conversation->unreadcount);
1738             }
1739         }
1740     }
1742     /**
1743      * Tests retrieving contacts.
1744      */
1745     public function test_get_contacts() {
1746         // Create some users.
1747         $user1 = self::getDataGenerator()->create_user();
1749         // Set as the user.
1750         $this->setUser($user1);
1752         $user2 = new stdClass();
1753         $user2->firstname = 'User';
1754         $user2->lastname = 'A';
1755         $user2 = self::getDataGenerator()->create_user($user2);
1757         $user3 = new stdClass();
1758         $user3->firstname = 'User';
1759         $user3->lastname = 'B';
1760         $user3 = self::getDataGenerator()->create_user($user3);
1762         $user4 = new stdClass();
1763         $user4->firstname = 'User';
1764         $user4->lastname = 'C';
1765         $user4 = self::getDataGenerator()->create_user($user4);
1767         $user5 = new stdClass();
1768         $user5->firstname = 'User';
1769         $user5->lastname = 'D';
1770         $user5 = self::getDataGenerator()->create_user($user5);
1772         // Add some users as contacts.
1773         \core_message\api::add_contact($user1->id, $user2->id);
1774         \core_message\api::add_contact($user1->id, $user3->id);
1775         \core_message\api::add_contact($user1->id, $user4->id);
1777         // Retrieve the contacts.
1778         $contacts = \core_message\api::get_contacts($user1->id);
1780         // Confirm the data is correct.
1781         $this->assertEquals(3, count($contacts));
1782         usort($contacts, ['static', 'sort_contacts']);
1784         $contact1 = $contacts[0];
1785         $contact2 = $contacts[1];
1786         $contact3 = $contacts[2];
1788         $this->assertEquals($user2->id, $contact1->userid);
1789         $this->assertEmpty($contact1->useridfrom);
1790         $this->assertFalse($contact1->ismessaging);
1791         $this->assertNull($contact1->lastmessage);
1792         $this->assertNull($contact1->messageid);
1793         $this->assertNull($contact1->isonline);
1794         $this->assertFalse($contact1->isread);
1795         $this->assertFalse($contact1->isblocked);
1796         $this->assertNull($contact1->unreadcount);
1798         $this->assertEquals($user3->id, $contact2->userid);
1799         $this->assertEmpty($contact2->useridfrom);
1800         $this->assertFalse($contact2->ismessaging);
1801         $this->assertNull($contact2->lastmessage);
1802         $this->assertNull($contact2->messageid);
1803         $this->assertNull($contact2->isonline);
1804         $this->assertFalse($contact2->isread);
1805         $this->assertFalse($contact2->isblocked);
1806         $this->assertNull($contact2->unreadcount);
1808         $this->assertEquals($user4->id, $contact3->userid);
1809         $this->assertEmpty($contact3->useridfrom);
1810         $this->assertFalse($contact3->ismessaging);
1811         $this->assertNull($contact3->lastmessage);
1812         $this->assertNull($contact3->messageid);
1813         $this->assertNull($contact3->isonline);
1814         $this->assertFalse($contact3->isread);
1815         $this->assertFalse($contact3->isblocked);
1816         $this->assertNull($contact3->unreadcount);
1817     }
1819     /**
1820      * Tests retrieving messages.
1821      */
1822     public function test_get_messages() {
1823         // Create some users.
1824         $user1 = self::getDataGenerator()->create_user();
1825         $user2 = self::getDataGenerator()->create_user();
1827         // The person doing the search.
1828         $this->setUser($user1);
1830         // Send some messages back and forth.
1831         $time = 1;
1832         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1833         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1834         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1835         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1837         // Retrieve the messages.
1838         $messages = \core_message\api::get_messages($user1->id, $user2->id);
1839         $this->assertDebuggingCalledCount(3);
1841         // Confirm the message data is correct.
1842         $this->assertEquals(4, count($messages));
1844         $message1 = $messages[0];
1845         $message2 = $messages[1];
1846         $message3 = $messages[2];
1847         $message4 = $messages[3];
1849         $this->assertEquals($user1->id, $message1->useridfrom);
1850         $this->assertEquals($user2->id, $message1->useridto);
1851         $this->assertTrue($message1->displayblocktime);
1852         $this->assertContains('Yo!', $message1->text);
1854         $this->assertEquals($user2->id, $message2->useridfrom);
1855         $this->assertEquals($user1->id, $message2->useridto);
1856         $this->assertFalse($message2->displayblocktime);
1857         $this->assertContains('Sup mang?', $message2->text);
1859         $this->assertEquals($user1->id, $message3->useridfrom);
1860         $this->assertEquals($user2->id, $message3->useridto);
1861         $this->assertFalse($message3->displayblocktime);
1862         $this->assertContains('Writing PHPUnit tests!', $message3->text);
1864         $this->assertEquals($user2->id, $message4->useridfrom);
1865         $this->assertEquals($user1->id, $message4->useridto);
1866         $this->assertFalse($message4->displayblocktime);
1867         $this->assertContains('Word.', $message4->text);
1868     }
1870     /**
1871      * Tests retrieving conversation messages.
1872      */
1873     public function test_get_conversation_messages() {
1874         // Create some users.
1875         $user1 = self::getDataGenerator()->create_user();
1876         $user2 = self::getDataGenerator()->create_user();
1878         // Create conversation.
1879         $conversation = \core_message\api::create_conversation(
1880             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1881             [$user1->id, $user2->id]
1882         );
1884         // The person doing the search.
1885         $this->setUser($user1);
1887         // Send some messages back and forth.
1888         $time = 1;
1889         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
1890         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
1891         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
1892         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
1894         // Retrieve the messages.
1895         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
1897         // Confirm the conversation id is correct.
1898         $this->assertEquals($conversation->id, $convmessages['id']);
1900         // Confirm the message data is correct.
1901         $messages = $convmessages['messages'];
1902         $this->assertEquals(4, count($messages));
1903         $message1 = $messages[0];
1904         $message2 = $messages[1];
1905         $message3 = $messages[2];
1906         $message4 = $messages[3];
1908         $this->assertEquals($user1->id, $message1->useridfrom);
1909         $this->assertContains('Yo!', $message1->text);
1911         $this->assertEquals($user2->id, $message2->useridfrom);
1912         $this->assertContains('Sup mang?', $message2->text);
1914         $this->assertEquals($user1->id, $message3->useridfrom);
1915         $this->assertContains('Writing PHPUnit tests!', $message3->text);
1917         $this->assertEquals($user1->id, $message4->useridfrom);
1918         $this->assertContains('Word.', $message4->text);
1920         // Confirm the members data is correct.
1921         $members = $convmessages['members'];
1922         $this->assertEquals(2, count($members));
1923     }
1925     /**
1926      * Tests retrieving group conversation messages.
1927      */
1928     public function test_get_group_conversation_messages() {
1929         // Create some users.
1930         $user1 = self::getDataGenerator()->create_user();
1931         $user2 = self::getDataGenerator()->create_user();
1932         $user3 = self::getDataGenerator()->create_user();
1933         $user4 = self::getDataGenerator()->create_user();
1935         // Create group conversation.
1936         $conversation = \core_message\api::create_conversation(
1937             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1938             [$user1->id, $user2->id, $user3->id, $user4->id]
1939         );
1941         // The person doing the search.
1942         $this->setUser($user1);
1944         // Send some messages back and forth.
1945         $time = 1;
1946         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
1947         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
1948         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
1949         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
1950         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Yeah!', $time + 5);
1952         // Retrieve the messages.
1953         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
1955         // Confirm the conversation id is correct.
1956         $this->assertEquals($conversation->id, $convmessages['id']);
1958         // Confirm the message data is correct.
1959         $messages = $convmessages['messages'];
1960         $this->assertEquals(5, count($messages));
1962         $message1 = $messages[0];
1963         $message2 = $messages[1];
1964         $message3 = $messages[2];
1965         $message4 = $messages[3];
1966         $message5 = $messages[4];
1968         $this->assertEquals($user1->id, $message1->useridfrom);
1969         $this->assertContains('Yo!', $message1->text);
1971         $this->assertEquals($user2->id, $message2->useridfrom);
1972         $this->assertContains('Sup mang?', $message2->text);
1974         $this->assertEquals($user3->id, $message3->useridfrom);
1975         $this->assertContains('Writing PHPUnit tests!', $message3->text);
1977         $this->assertEquals($user1->id, $message4->useridfrom);
1978         $this->assertContains('Word.', $message4->text);
1980         $this->assertEquals($user2->id, $message5->useridfrom);
1981         $this->assertContains('Yeah!', $message5->text);
1983         // Confirm the members data is correct.
1984         $members = $convmessages['members'];
1985         $this->assertEquals(3, count($members));
1986     }
1988     /**
1989      * Test verifying the sorting param for get_conversation_messages is respected().
1990      */
1991     public function test_get_conversation_messages_sorting() {
1992         // Create some users.
1993         $user1 = self::getDataGenerator()->create_user();
1994         $user2 = self::getDataGenerator()->create_user();
1995         $user3 = self::getDataGenerator()->create_user();
1997         // Create conversations - 1 group and 1 individual.
1998         $conversation = \core_message\api::create_conversation(
1999             \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2000             [$user1->id, $user2->id]
2001         );
2002         $conversation2 = \core_message\api::create_conversation(
2003             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2004             [$user1->id, $user2->id, $user3->id]
2005         );
2007         // Send some messages back and forth.
2008         $time = 1;
2009         $m1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2010         $m2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2011         $m3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2012         $m4id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2014         $gm1id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Yo!', $time + 1);
2015         $gm2id = testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Sup mang?', $time + 2);
2016         $gm3id = testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'Writing PHPUnit tests!', $time + 3);
2017         $gm4id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Word.', $time + 4);
2019         // The person doing the search.
2020         $this->setUser($user1);
2022         // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2023         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2024         $messages = $convmessages['messages'];
2025         $this->assertEquals($m1id, $messages[0]->id);
2026         $this->assertEquals($m2id, $messages[1]->id);
2027         $this->assertEquals($m3id, $messages[2]->id);
2028         $this->assertEquals($m4id, $messages[3]->id);
2030         // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2031         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated DESC');
2032         $messages = $convmessages['messages'];
2033         $this->assertEquals($m1id, $messages[3]->id);
2034         $this->assertEquals($m2id, $messages[2]->id);
2035         $this->assertEquals($m3id, $messages[1]->id);
2036         $this->assertEquals($m4id, $messages[0]->id);
2038         // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2039         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id);
2040         $messages = $convmessages['messages'];
2041         $this->assertEquals($gm1id, $messages[0]->id);
2042         $this->assertEquals($gm2id, $messages[1]->id);
2043         $this->assertEquals($gm3id, $messages[2]->id);
2044         $this->assertEquals($gm4id, $messages[3]->id);
2046         // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2047         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id, 0, 0, 'timecreated DESC');
2048         $messages = $convmessages['messages'];
2049         $this->assertEquals($gm1id, $messages[3]->id);
2050         $this->assertEquals($gm2id, $messages[2]->id);
2051         $this->assertEquals($gm3id, $messages[1]->id);
2052         $this->assertEquals($gm4id, $messages[0]->id);
2053     }
2055     /**
2056      * Test retrieving conversation messages by providing a minimum timecreated value.
2057      */
2058     public function test_get_conversation_messages_time_from_only() {
2059         // Create some users.
2060         $user1 = self::getDataGenerator()->create_user();
2061         $user2 = self::getDataGenerator()->create_user();
2062         $user3 = self::getDataGenerator()->create_user();
2063         $user4 = self::getDataGenerator()->create_user();
2065         // Create group conversation.
2066         $conversation = \core_message\api::create_conversation(
2067             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2068             [$user1->id, $user2->id, $user3->id, $user4->id]
2069         );
2071         // The person doing the search.
2072         $this->setUser($user1);
2074         // Send some messages back and forth.
2075         $time = 1;
2076         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2077         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2078         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2079         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2081         // Retrieve the messages from $time, which should be all of them.
2082         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC', $time);
2084         // Confirm the conversation id is correct.
2085         $this->assertEquals($conversation->id, $convmessages['id']);
2087         // Confirm the message data is correct.
2088         $messages = $convmessages['messages'];
2089         $this->assertEquals(4, count($messages));
2091         $message1 = $messages[0];
2092         $message2 = $messages[1];
2093         $message3 = $messages[2];
2094         $message4 = $messages[3];
2096         $this->assertContains('Message 1', $message1->text);
2097         $this->assertContains('Message 2', $message2->text);
2098         $this->assertContains('Message 3', $message3->text);
2099         $this->assertContains('Message 4', $message4->text);
2101         // Confirm the members data is correct.
2102         $members = $convmessages['members'];
2103         $this->assertEquals(3, count($members));
2105         // Retrieve the messages from $time + 3, which should only be the 2 last messages.
2106         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2107             'timecreated ASC', $time + 3);
2109         // Confirm the conversation id is correct.
2110         $this->assertEquals($conversation->id, $convmessages['id']);
2112         // Confirm the message data is correct.
2113         $messages = $convmessages['messages'];
2114         $this->assertEquals(2, count($messages));
2116         $message1 = $messages[0];
2117         $message2 = $messages[1];
2119         $this->assertContains('Message 3', $message1->text);
2120         $this->assertContains('Message 4', $message2->text);
2122         // Confirm the members data is correct.
2123         $members = $convmessages['members'];
2124         $this->assertEquals(2, count($members));
2125     }
2127     /**
2128      * Test retrieving conversation messages by providing a maximum timecreated value.
2129      */
2130     public function test_get_conversation_messages_time_to_only() {
2131         // Create some users.
2132         $user1 = self::getDataGenerator()->create_user();
2133         $user2 = self::getDataGenerator()->create_user();
2134         $user3 = self::getDataGenerator()->create_user();
2135         $user4 = self::getDataGenerator()->create_user();
2137         // Create group conversation.
2138         $conversation = \core_message\api::create_conversation(
2139             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2140             [$user1->id, $user2->id, $user3->id, $user4->id]
2141         );
2143         // The person doing the search.
2144         $this->setUser($user1);
2146         // Send some messages back and forth.
2147         $time = 1;
2148         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2149         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2150         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2151         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2153         // Retrieve the messages up until $time + 4, which should be all of them.
2154         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2155             0, $time + 4);
2157         // Confirm the conversation id is correct.
2158         $this->assertEquals($conversation->id, $convmessages['id']);
2160         // Confirm the message data is correct.
2161         $messages = $convmessages['messages'];
2162         $this->assertEquals(4, count($messages));
2164         $message1 = $messages[0];
2165         $message2 = $messages[1];
2166         $message3 = $messages[2];
2167         $message4 = $messages[3];
2169         $this->assertContains('Message 1', $message1->text);
2170         $this->assertContains('Message 2', $message2->text);
2171         $this->assertContains('Message 3', $message3->text);
2172         $this->assertContains('Message 4', $message4->text);
2174         // Confirm the members data is correct.
2175         $members = $convmessages['members'];
2176         $this->assertEquals(3, count($members));
2178         // Retrieve the messages up until $time + 2, which should be the first two.
2179         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2180             0, $time + 2);
2182         // Confirm the conversation id is correct.
2183         $this->assertEquals($conversation->id, $convmessages['id']);
2185         // Confirm the message data is correct.
2186         $messages = $convmessages['messages'];
2187         $this->assertEquals(2, count($messages));
2189         $message1 = $messages[0];
2190         $message2 = $messages[1];
2192         $this->assertContains('Message 1', $message1->text);
2193         $this->assertContains('Message 2', $message2->text);
2195         // Confirm the members data is correct.
2196         $members = $convmessages['members'];
2197         $this->assertEquals(2, count($members));
2198     }
2200     /**
2201      * Test retrieving conversation messages by providing a minimum and maximum timecreated value.
2202      */
2203     public function test_get_conversation_messages_time_from_and_to() {
2204         // Create some users.
2205         $user1 = self::getDataGenerator()->create_user();
2206         $user2 = self::getDataGenerator()->create_user();
2207         $user3 = self::getDataGenerator()->create_user();
2208         $user4 = self::getDataGenerator()->create_user();
2210         // Create group conversation.
2211         $conversation = \core_message\api::create_conversation(
2212             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2213             [$user1->id, $user2->id, $user3->id, $user4->id]
2214         );
2216         // The person doing the search.
2217         $this->setUser($user1);
2219         // Send some messages back and forth.
2220         $time = 1;
2221         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2222         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2223         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2224         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2226         // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
2227         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2228             'timecreated ASC', $time + 2, $time + 3);
2230         // Confirm the conversation id is correct.
2231         $this->assertEquals($conversation->id, $convmessages['id']);
2233         // Confirm the message data is correct.
2234         $messages = $convmessages['messages'];
2235         $this->assertEquals(2, count($messages));
2237         $message1 = $messages[0];
2238         $message2 = $messages[1];
2240         $this->assertContains('Message 2', $message1->text);
2241         $this->assertContains('Message 3', $message2->text);
2243         // Confirm the members data is correct.
2244         $members = $convmessages['members'];
2245         $this->assertEquals(2, count($members));
2246     }
2249     /**
2250      * Test retrieving conversation messages by providing a limitfrom value.
2251      */
2252     public function test_get_conversation_messages_limitfrom_only() {
2253         // Create some users.
2254         $user1 = self::getDataGenerator()->create_user();
2255         $user2 = self::getDataGenerator()->create_user();
2256         $user3 = self::getDataGenerator()->create_user();
2257         $user4 = self::getDataGenerator()->create_user();
2259         // Create group conversation.
2260         $conversation = \core_message\api::create_conversation(
2261             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2262             [$user1->id, $user2->id, $user3->id, $user4->id]
2263         );
2265         // The person doing the search.
2266         $this->setUser($user1);
2268         // Send some messages back and forth.
2269         $time = 1;
2270         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2271         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2272         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2273         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2275         // Retrieve the messages from $time, which should be all of them.
2276         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2);
2278         // Confirm the conversation id is correct.
2279         $messages = $convmessages['messages'];
2280         $this->assertEquals($conversation->id, $convmessages['id']);
2282         // Confirm the message data is correct.
2283         $this->assertEquals(2, count($messages));
2285         $message1 = $messages[0];
2286         $message2 = $messages[1];
2288         $this->assertContains('Message 3', $message1->text);
2289         $this->assertContains('Message 4', $message2->text);
2291         // Confirm the members data is correct.
2292         $members = $convmessages['members'];
2293         $this->assertEquals(2, count($members));
2294     }
2296     /**
2297      * Test retrieving conversation messages by providing a limitnum value.
2298      */
2299     public function test_get_conversation_messages_limitnum() {
2300         // Create some users.
2301         $user1 = self::getDataGenerator()->create_user();
2302         $user2 = self::getDataGenerator()->create_user();
2303         $user3 = self::getDataGenerator()->create_user();
2304         $user4 = self::getDataGenerator()->create_user();
2306         // Create group conversation.
2307         $conversation = \core_message\api::create_conversation(
2308             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2309             [$user1->id, $user2->id, $user3->id, $user4->id]
2310         );
2312         // The person doing the search.
2313         $this->setUser($user1);
2315         // Send some messages back and forth.
2316         $time = 1;
2317         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2318         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2319         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2320         testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2322         // Retrieve the messages from $time, which should be all of them.
2323         $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2, 1);
2325         // Confirm the conversation id is correct.
2326         $messages = $convmessages['messages'];
2327         $this->assertEquals($conversation->id, $convmessages['id']);
2329         // Confirm the message data is correct.
2330         $messages = $convmessages['messages'];
2331         $this->assertEquals(1, count($messages));
2333         $message1 = $messages[0];
2335         $this->assertContains('Message 3', $message1->text);
2337         // Confirm the members data is correct.
2338         $members = $convmessages['members'];
2339         $this->assertEquals(1, count($members));
2340     }
2342     /**
2343      * Tests retrieving most recent message.
2344      */
2345     public function test_get_most_recent_message() {
2346         // Create some users.
2347         $user1 = self::getDataGenerator()->create_user();
2348         $user2 = self::getDataGenerator()->create_user();
2350         // The person doing the search.
2351         $this->setUser($user1);
2353         // Send some messages back and forth.
2354         $time = 1;
2355         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2356         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2357         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2358         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2360         // Retrieve the most recent messages.
2361         $message = \core_message\api::get_most_recent_message($user1->id, $user2->id);
2362         $this->assertDebuggingCalledCount(3);
2364         // Check the results are correct.
2365         $this->assertEquals($user2->id, $message->useridfrom);
2366         $this->assertEquals($user1->id, $message->useridto);
2367         $this->assertContains('Word.', $message->text);
2368     }
2370     /**
2371      * Tests retrieving most recent conversation message.
2372      */
2373     public function test_get_most_recent_conversation_message() {
2374         // Create some users.
2375         $user1 = self::getDataGenerator()->create_user();
2376         $user2 = self::getDataGenerator()->create_user();
2377         $user3 = self::getDataGenerator()->create_user();
2379         // Create group conversation.
2380         $conversation = \core_message\api::create_conversation(
2381             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2382             [$user1->id, $user2->id, $user3->id]
2383         );
2385         // The person getting the most recent conversation message.
2386         $this->setUser($user1);
2388         // Send some messages back and forth.
2389         $time = 1;
2390         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2391         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2392         testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2393         testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Word.', $time + 4);
2395         // Retrieve the most recent messages.
2396         $message = \core_message\api::get_most_recent_conversation_message($conversation->id, $user1->id);
2398         // Check the results are correct.
2399         $this->assertEquals($user2->id, $message->useridfrom);
2400         $this->assertContains('Word.', $message->text);
2401     }
2403     /**
2404      * Tests retrieving a user's profile.
2405      */
2406     public function test_get_profile() {
2407         // Create some users.
2408         $user1 = self::getDataGenerator()->create_user();
2410         $user2 = new stdClass();
2411         $user2->country = 'AU';
2412         $user2->city = 'Perth';
2413         $user2 = self::getDataGenerator()->create_user($user2);
2415         // The person doing the search.
2416         $this->setUser($user1);
2418         // Get the profile.
2419         $profile = \core_message\api::get_profile($user1->id, $user2->id);
2421         $this->assertEquals($user2->id, $profile->userid);
2422         $this->assertEmpty($profile->email);
2423         $this->assertEmpty($profile->country);
2424         $this->assertEmpty($profile->city);
2425         $this->assertEquals(fullname($user2), $profile->fullname);
2426         $this->assertNull($profile->isonline);
2427         $this->assertFalse($profile->isblocked);
2428         $this->assertFalse($profile->iscontact);
2429     }
2431     /**
2432      * Tests retrieving a user's profile.
2433      */
2434     public function test_get_profile_as_admin() {
2435         // The person doing the search.
2436         $this->setAdminUser();
2438         // Create some users.
2439         $user1 = self::getDataGenerator()->create_user();
2441         $user2 = new stdClass();
2442         $user2->country = 'AU';
2443         $user2->city = 'Perth';
2444         $user2 = self::getDataGenerator()->create_user($user2);
2446         // Get the profile.
2447         $profile = \core_message\api::get_profile($user1->id, $user2->id);
2449         $this->assertEquals($user2->id, $profile->userid);
2450         $this->assertEquals($user2->email, $profile->email);
2451         $this->assertEquals($user2->country, $profile->country);
2452         $this->assertEquals($user2->city, $profile->city);
2453         $this->assertEquals(fullname($user2), $profile->fullname);
2454         $this->assertFalse($profile->isonline);
2455         $this->assertFalse($profile->isblocked);
2456         $this->assertFalse($profile->iscontact);
2457     }
2459     /**
2460      * Tests checking if a user can mark all messages as read.
2461      */
2462     public function test_can_mark_all_messages_as_read() {
2463         // Set as the admin.
2464         $this->setAdminUser();
2466         // Create some users.
2467         $user1 = self::getDataGenerator()->create_user();
2468         $user2 = self::getDataGenerator()->create_user();
2469         $user3 = self::getDataGenerator()->create_user();
2471         // Send some messages back and forth.
2472         $time = 1;
2473         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2474         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2475         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2476         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2478         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2480         // The admin can do anything.
2481         $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
2483         // Set as the user 1.
2484         $this->setUser($user1);
2486         // The user can mark the messages as he is in the conversation.
2487         $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
2489         // User 1 can not mark the messages read for user 2.
2490         $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user2->id, $conversationid));
2492         // This user is not a part of the conversation.
2493         $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user3->id, $conversationid));
2494     }
2496     /**
2497      * Tests checking if a user can delete a conversation.
2498      */
2499     public function test_can_delete_conversation() {
2500         // Set as the admin.
2501         $this->setAdminUser();
2503         // Create some users.
2504         $user1 = self::getDataGenerator()->create_user();
2505         $user2 = self::getDataGenerator()->create_user();
2507         // Send some messages back and forth.
2508         $time = 1;
2509         $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2510         $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2511         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2512         $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2514         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2516         // The admin can do anything.
2517         $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
2519         // Set as the user 1.
2520         $this->setUser($user1);
2522         // They can delete their own messages.
2523         $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
2525         // They can't delete someone elses.
2526         $this->assertFalse(\core_message\api::can_delete_conversation($user2->id, $conversationid));
2527     }
2529     /**
2530      * Tests deleting a conversation.
2531      */
2532     public function test_delete_conversation() {
2533         global $DB;
2535         // Create some users.
2536         $user1 = self::getDataGenerator()->create_user();
2537         $user2 = self::getDataGenerator()->create_user();
2539         // The person doing the search.
2540         $this->setUser($user1);
2542         // Send some messages back and forth.
2543         $time = 1;
2544         $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2545         $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2546         $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2547         $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2549         // Delete the conversation as user 1.
2550         \core_message\api::delete_conversation($user1->id, $user2->id);
2551         $this->assertDebuggingCalled();
2553         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2554         $this->assertCount(4, $muas);
2555         // Sort by id.
2556         ksort($muas);
2558         $mua1 = array_shift($muas);
2559         $mua2 = array_shift($muas);
2560         $mua3 = array_shift($muas);
2561         $mua4 = array_shift($muas);
2563         $this->assertEquals($user1->id, $mua1->userid);
2564         $this->assertEquals($m1id, $mua1->messageid);
2565         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
2567         $this->assertEquals($user1->id, $mua2->userid);
2568         $this->assertEquals($m2id, $mua2->messageid);
2569         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
2571         $this->assertEquals($user1->id, $mua3->userid);
2572         $this->assertEquals($m3id, $mua3->messageid);
2573         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
2575         $this->assertEquals($user1->id, $mua4->userid);
2576         $this->assertEquals($m4id, $mua4->messageid);
2577         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
2578     }
2580     /**
2581      * Tests deleting a conversation by conversation id.
2582      */
2583     public function test_delete_conversation_by_id() {
2584         global $DB;
2586         // Create some users.
2587         $user1 = self::getDataGenerator()->create_user();
2588         $user2 = self::getDataGenerator()->create_user();
2590         // The person doing the search.
2591         $this->setUser($user1);
2593         // Send some messages back and forth.
2594         $time = 1;
2595         $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2596         $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2597         $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2598         $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2600         // Delete the conversation as user 1.
2601         $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
2602         \core_message\api::delete_conversation_by_id($user1->id, $conversationid);
2604         $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2605         $this->assertCount(4, $muas);
2606         // Sort by id.
2607         ksort($muas);
2609         $mua1 = array_shift($muas);
2610         $mua2 = array_shift($muas);
2611         $mua3 = array_shift($muas);
2612         $mua4 = array_shift($muas);
2614         $this->assertEquals($user1->id, $mua1->userid);
2615         $this->assertEquals($m1id, $mua1->messageid);
2616         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
2618         $this->assertEquals($user1->id, $mua2->userid);
2619         $this->assertEquals($m2id, $mua2->messageid);
2620         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
2622         $this->assertEquals($user1->id, $mua3->userid);
2623         $this->assertEquals($m3id, $mua3->messageid);
2624         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
2626         $this->assertEquals($user1->id, $mua4->userid);
2627         $this->assertEquals($m4id, $mua4->messageid);
2628         $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
2629     }
2631     /**
2632      * Tests counting unread conversations.
2633      */
2634     public function test_count_unread_conversations() {
2635         $this->resetAfterTest(true);
2637         // Create some users.
2638         $user1 = self::getDataGenerator()->create_user();
2639         $user2 = self::getDataGenerator()->create_user();
2640         $user3 = self::getDataGenerator()->create_user();
2641         $user4 = self::getDataGenerator()->create_user();
2643         // The person wanting the conversation count.
2644         $this->setUser($user1);
2646         // Send some messages back and forth, have some different conversations with different users.
2647         $this->send_fake_message($user1, $user2, 'Yo!');
2648         $this->send_fake_message($user2, $user1, 'Sup mang?');
2649         $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
2650         $this->send_fake_message($user2, $user1, 'Word.');
2652         $this->send_fake_message($user1, $user3, 'Booyah');
2653         $this->send_fake_message($user3, $user1, 'Whaaat?');
2654         $this->send_fake_message($user1, $user3, 'Nothing.');
2655         $this->send_fake_message($user3, $user1, 'Cool.');
2657         $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
2658         $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
2659         $this->send_fake_message($user1, $user4, 'Dope.');
2661         // Check the amount for the current user.
2662         $this->assertEquals(3, core_message\api::count_unread_conversations());
2664         // Check the amount for the second user.
2665         $this->assertEquals(1, core_message\api::count_unread_conversations($user2));
2666     }
2668     /**
2669      * Tests deleting a conversation.
2670      */
2671     public function test_get_all_message_preferences() {
2672         $user = self::getDataGenerator()->create_user();
2673         $this->setUser($user);
2675         // Set a couple of preferences to test.
2676         set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
2677         set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
2679         $processors = get_message_processors();
2680         $providers = message_get_providers_for_user($user->id);
2681         $prefs = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2683         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedin['popup']);
2684         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedoff['email']);
2685     }
2687     /**
2688      * Tests the user can post a message.
2689      */
2690     public function test_can_post_message() {
2691         // Create some users.
2692         $user1 = self::getDataGenerator()->create_user();
2693         $user2 = self::getDataGenerator()->create_user();
2695         // Set as the first user.
2696         $this->setUser($user1);
2698         // With the default privacy setting, users can't message them.
2699         $this->assertFalse(\core_message\api::can_post_message($user2));
2701         // Enrol users to the same course.
2702         $course = $this->getDataGenerator()->create_course();
2703         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
2704         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
2705         // After enrolling users to the course, they should be able to message them with the default privacy setting.
2706         $this->assertTrue(\core_message\api::can_post_message($user2));
2707     }
2709     /**
2710      * Tests the user can't post a message without proper capability.
2711      */
2712     public function test_can_post_message_without_sendmessage_cap() {
2713         global $DB;
2715         // Create some users.
2716         $user1 = self::getDataGenerator()->create_user();
2717         $user2 = self::getDataGenerator()->create_user();
2719         // Set as the user 1.
2720         $this->setUser($user1);
2722         // Remove the capability to send a message.
2723         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
2724         unassign_capability('moodle/site:sendmessage', $roleids['user'],
2725             context_system::instance());
2727         // Check that we can not post a message without the capability.
2728         $this->assertFalse(\core_message\api::can_post_message($user2));
2729     }
2731     /**
2732      * Tests the user can post a message when they are contact.
2733      */
2734     public function test_can_post_message_when_contact() {
2735         // Create some users.
2736         $user1 = self::getDataGenerator()->create_user();
2737         $user2 = self::getDataGenerator()->create_user();
2739         // Set as the first user.
2740         $this->setUser($user1);
2742         // Check that we can not send user2 a message.
2743         $this->assertFalse(\core_message\api::can_post_message($user2));
2745         // Add users as contacts.
2746         \core_message\api::add_contact($user1->id, $user2->id);
2748         // Check that the return result is now true.
2749         $this->assertTrue(\core_message\api::can_post_message($user2));
2750     }
2752     /**
2753      * Tests the user can't post a message if they are not a contact and the user
2754      * has requested messages only from contacts.
2755      */
2756     public function test_can_post_message_when_not_contact() {
2757         // Create some users.
2758         $user1 = self::getDataGenerator()->create_user();
2759         $user2 = self::getDataGenerator()->create_user();
2761         // Set as the first user.
2762         $this->setUser($user1);
2764         // Set the second user's preference to not receive messages from non-contacts.
2765         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
2767         // Check that we can not send user 2 a message.
2768         $this->assertFalse(\core_message\api::can_post_message($user2));
2769     }
2771     /**
2772      * Tests the user can't post a message if they are blocked.
2773      */
2774     public function test_can_post_message_when_blocked() {
2775         // Create some users.
2776         $user1 = self::getDataGenerator()->create_user();
2777         $user2 = self::getDataGenerator()->create_user();
2779         // Set the user.
2780         $this->setUser($user1);
2782         // Block the second user.
2783         \core_message\api::block_user($user1->id, $user2->id);
2785         // Check that the second user can no longer send the first user a message.
2786         $this->assertFalse(\core_message\api::can_post_message($user1, $user2));
2787     }
2789     /**
2790      * Tests the user can post a message when site-wide messaging setting is enabled,
2791      * even if they are not a contact and are not members of the same course.
2792      */
2793     public function test_can_post_message_site_messaging_setting() {
2794         // Create some users.
2795         $user1 = self::getDataGenerator()->create_user();
2796         $user2 = self::getDataGenerator()->create_user();
2798         // Set as the first user.
2799         $this->setUser($user1);
2801         // By default, user only can be messaged by contacts and members of any of his/her courses.
2802         $this->assertFalse(\core_message\api::can_post_message($user2));
2804         // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
2805         set_config('messagingallusers', true);
2807         // Set the second user's preference to receive messages from everybody.
2808         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
2810         // Check that we can send user2 a message.
2811         $this->assertTrue(\core_message\api::can_post_message($user2));
2813         // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
2814         // and members sharing a course with her.
2815         set_config('messagingallusers', false);
2817         // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
2818         $this->assertFalse(\core_message\api::can_post_message($user2));
2820         // Enrol users to the same course.
2821         $course = $this->getDataGenerator()->create_course();
2822         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
2823         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
2824         // Check that we can send user2 a message because they are sharing a course.
2825         $this->assertTrue(\core_message\api::can_post_message($user2));
2827         // Set the second user's preference to receive messages only from contacts.
2828         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
2829         // Check that now the user2 can't be contacted because user1 is not their contact.
2830         $this->assertFalse(\core_message\api::can_post_message($user2));
2832         // Make contacts user1 and user2.
2833         \core_message\api::add_contact($user2->id, $user1->id);
2834         // Check that we can send user2 a message because they are contacts.
2835         $this->assertTrue(\core_message\api::can_post_message($user2));
2836     }
2838     /**
2839      * Tests the user with the messageanyuser capability can post a message.
2840      */
2841     public function test_can_post_message_with_messageanyuser_cap() {
2842         global $DB;
2844         // Create some users.
2845         $teacher1 = self::getDataGenerator()->create_user();
2846         $student1 = self::getDataGenerator()->create_user();
2847         $student2 = self::getDataGenerator()->create_user();
2849         // Create users not enrolled in any course.
2850         $user1 = self::getDataGenerator()->create_user();
2852         // Create a course.
2853         $course1 = $this->getDataGenerator()->create_course();
2855         // Enrol the users in the course.
2856         $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher');
2857         $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student');
2858         $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student');
2860         // Set some student preferences to not receive messages from non-contacts.
2861         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $student1->id);
2863         // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
2864         $this->assertTrue(\core_message\api::can_post_message($student1, $teacher1));
2865         // Check that the teacher can't contact user1 because it's not his teacher.
2866         $this->assertFalse(\core_message\api::can_post_message($user1, $teacher1));
2868         // Remove the messageanyuser capability from the course1 for teachers.
2869         $coursecontext = context_course::instance($course1->id);
2870         $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
2871         assign_capability('moodle/site:messageanyuser', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
2872         $coursecontext->mark_dirty();
2874         // Check that we can't send user1 a message because they are not contacts.
2875         $this->assertFalse(\core_message\api::can_post_message($student1, $teacher1));
2876         // However, teacher can message student2 because they are sharing a course.
2877         $this->assertTrue(\core_message\api::can_post_message($student2, $teacher1));
2878     }
2880     /**
2881      * Tests get_user_privacy_messaging_preference method.
2882      */
2883     public function test_get_user_privacy_messaging_preference() {
2884         // Create some users.
2885         $user1 = self::getDataGenerator()->create_user();
2886         $user2 = self::getDataGenerator()->create_user();
2887         $user3 = self::getDataGenerator()->create_user();
2889         // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
2890         set_config('messagingallusers', true);
2892         // Set some user preferences.
2893         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user1->id);
2894         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
2896         // Check the returned value for each user.
2897         $this->assertEquals(
2898             \core_message\api::MESSAGE_PRIVACY_SITE,
2899             \core_message\api::get_user_privacy_messaging_preference($user1->id)
2900         );
2901         $this->assertEquals(
2902             \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS,
2903             \core_message\api::get_user_privacy_messaging_preference($user2->id)
2904         );
2905         $this->assertEquals(
2906             \core_message\api::MESSAGE_PRIVACY_SITE,
2907             \core_message\api::get_user_privacy_messaging_preference($user3->id)
2908         );
2910         // Disable site-wide messagging privacy setting. The user will be able to receive messages from members of their course.
2911         set_config('messagingallusers', false);
2913         // Check the returned value for each user.
2914         $this->assertEquals(
2915             \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER,
2916             \core_message\api::get_user_privacy_messaging_preference($user1->id)
2917         );
2918         $this->assertEquals(
2919             \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS,
2920             \core_message\api::get_user_privacy_messaging_preference($user2->id)
2921         );
2922         $this->assertEquals(
2923             \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER,
2924             \core_message\api::get_user_privacy_messaging_preference($user3->id)
2925         );
2926     }
2928     /**
2929      * Tests that when blocking messages from non-contacts is enabled that
2930      * non-contacts trying to send a message return false.
2931      */
2932     public function test_is_user_non_contact_blocked() {
2933         // Create some users.
2934         $user1 = self::getDataGenerator()->create_user();
2935         $user2 = self::getDataGenerator()->create_user();
2937         // Set as the first user.
2938         $this->setUser($user1);
2940         // By default, user only can be messaged by contacts and members of any of his/her courses.
2941         $this->assertTrue(\core_message\api::is_user_non_contact_blocked($user2));
2942         $this->assertDebuggingCalled();
2944         // Enable all users privacy messaging and check now the default user's preference has been set to allow receiving
2945         // messages from everybody.
2946         set_config('messagingallusers', true);
2947         // Check that the return result is now false because any site user can contact him/her.
2948         $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
2949         $this->assertDebuggingCalled();
2951         // Set the second user's preference to not receive messages from non-contacts.
2952         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
2953         // Check that the return result is still true (because is even more restricted).
2954         $this->assertTrue(\core_message\api::is_user_non_contact_blocked($user2));
2955         $this->assertDebuggingCalled();
2957         // Add the first user as a contact for the second user.
2958         \core_message\api::add_contact($user2->id, $user1->id);
2960         // Check that the return result is now false.
2961         $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
2962         $this->assertDebuggingCalled();
2964         // Set the second user's preference to receive messages from course members.
2965         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
2966         // Check that the return result is still false (because $user1 is still his/her contact).
2967         $this->assertFalse(\core_message\api::is_user_non_contact_blocked($user2));
2968         $this->assertDebuggingCalled();
2969     }
2971     /**
2972      * Tests that we return true when a user is blocked, or false
2973      * if they are not blocked.
2974      */
2975     public function test_is_user_blocked() {
2976         // Create some users.
2977         $user1 = self::getDataGenerator()->create_user();
2978         $user2 = self::getDataGenerator()->create_user();
2980         // Set the user.
2981         $this->setUser($user1);
2983         // User shouldn't be blocked.
2984         $this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
2985         $this->assertDebuggingCalled();
2987         // Block the user.
2988         \core_message\api::block_user($user1->id, $user2->id);
2990         // User should be blocked.
2991         $this->assertTrue(\core_message\api::is_user_blocked($user1->id, $user2->id));
2992         $this->assertDebuggingCalled();
2994         // Unblock the user.
2995         \core_message\api::unblock_user($user1->id, $user2->id);
2996         $this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
2997         $this->assertDebuggingCalled();
2998     }
3000     /**
3001      * Tests that the admin is not blocked even if someone has chosen to block them.
3002      */
3003     public function test_is_user_blocked_as_admin() {
3004         // Create a user.
3005         $user1 = self::getDataGenerator()->create_user();
3007         // Set the user.
3008         $this->setUser($user1);
3010         // Block the admin user.
3011         \core_message\api::block_user($user1->id, 2);
3013         // Now change to the admin user.
3014         $this->setAdminUser();
3016         // As the admin you should still be able to send messages to the user.
3017         $this->assertFalse(\core_message\api::is_user_blocked($user1->id));
3018         $this->assertDebuggingCalled();
3019     }
3021     /*
3022      * Tes get_message_processor api.
3023      */
3024     public function test_get_message_processor() {
3025         $processors = get_message_processors(true);
3026         if (empty($processors)) {
3027             $this->markTestSkipped("No message processors found");
3028         }
3030         $name = key($processors);
3031         $processor = current($processors);
3032         $testprocessor = \core_message\api::get_message_processor($name);
3033         $this->assertEquals($processor->name, $testprocessor->name);
3034         $this->assertEquals($processor->enabled, $testprocessor->enabled);
3035         $this->assertEquals($processor->available, $testprocessor->available);
3036         $this->assertEquals($processor->configured, $testprocessor->configured);
3038         // Disable processor and test.
3039         \core_message\api::update_processor_status($testprocessor, 0);
3040         $testprocessor = \core_message\api::get_message_processor($name, true);
3041         $this->assertEmpty($testprocessor);
3042         $testprocessor = \core_message\api::get_message_processor($name);
3043         $this->assertEquals($processor->name, $testprocessor->name);
3044         $this->assertEquals(0, $testprocessor->enabled);
3046         // Enable again and test.
3047         \core_message\api::update_processor_status($testprocessor, 1);
3048         $testprocessor = \core_message\api::get_message_processor($name, true);
3049         $this->assertEquals($processor->name, $testprocessor->name);
3050         $this->assertEquals(1, $testprocessor->enabled);
3051         $testprocessor = \core_message\api::get_message_processor($name);
3052         $this->assertEquals($processor->name, $testprocessor->name);
3053         $this->assertEquals(1, $testprocessor->enabled);
3054     }
3056     /**
3057      * Test method update_processor_status.
3058      */
3059     public function test_update_processor_status() {
3060         $processors = get_message_processors();
3061         if (empty($processors)) {
3062             $this->markTestSkipped("No message processors found");
3063         }
3064         $name = key($processors);
3065         $testprocessor = current($processors);
3067         // Enable.
3068         \core_message\api::update_processor_status($testprocessor, 1);
3069         $testprocessor = \core_message\api::get_message_processor($name);
3070         $this->assertEquals(1, $testprocessor->enabled);
3072         // Disable.
3073         \core_message\api::update_processor_status($testprocessor, 0);
3074         $testprocessor = \core_message\api::get_message_processor($name);
3075         $this->assertEquals(0, $testprocessor->enabled);
3077         // Enable again.
3078         \core_message\api::update_processor_status($testprocessor, 1);
3079         $testprocessor = \core_message\api::get_message_processor($name);
3080         $this->assertEquals(1, $testprocessor->enabled);
3081     }
3083     /**
3084      * Test method is_user_enabled.
3085      */
3086     public function is_user_enabled() {
3087         $processors = get_message_processors();
3088         if (empty($processors)) {
3089             $this->markTestSkipped("No message processors found");
3090         }
3091         $name = key($processors);
3092         $testprocessor = current($processors);
3094         // Enable.
3095         \core_message\api::update_processor_status($testprocessor, 1);
3096         $status = \core_message\api::is_processor_enabled($name);
3097         $this->assertEquals(1, $status);
3099         // Disable.
3100         \core_message\api::update_processor_status($testprocessor, 0);
3101         $status = \core_message\api::is_processor_enabled($name);
3102         $this->assertEquals(0, $status);
3104         // Enable again.
3105         \core_message\api::update_processor_status($testprocessor, 1);
3106         $status = \core_message\api::is_processor_enabled($name);
3107         $this->assertEquals(1, $status);
3108     }
3110     /**
3111      * Test retrieving messages by providing a minimum timecreated value.
3112      */
3113     public function test_get_messages_time_from_only() {
3114         // Create some users.
3115         $user1 = self::getDataGenerator()->create_user();
3116         $user2 = self::getDataGenerator()->create_user();
3118         // The person doing the search.
3119         $this->setUser($user1);
3121         // Send some messages back and forth.
3122         $time = 1;
3123         $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
3124         $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
3125         $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
3126         $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
3128         // Retrieve the messages from $time, which should be all of them.
3129         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time);
3130         $this->assertDebuggingCalledCount(3);
3132         // Confirm the message data is correct.
3133         $this->assertEquals(4, count($messages));
3135         $message1 = $messages[0];
3136         $message2 = $messages[1];
3137         $message3 = $messages[2];
3138         $message4 = $messages[3];
3140         $this->assertContains('Message 1', $message1->text);
3141         $this->assertContains('Message 2', $message2->text);
3142         $this->assertContains('Message 3', $message3->text);
3143         $this->assertContains('Message 4', $message4->text);
3145         // Retrieve the messages from $time + 3, which should only be the 2 last messages.
3146         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 3);
3147         $this->assertDebuggingCalledCount(3);
3149         // Confirm the message data is correct.
3150         $this->assertEquals(2, count($messages));
3152         $message1 = $messages[0];
3153         $message2 = $messages[1];
3155         $this->assertContains('Message 3', $message1->text);
3156         $this->assertContains('Message 4', $message2->text);
3157     }
3159     /**
3160      * Test retrieving messages by providing a maximum timecreated value.
3161      */
3162     public function test_get_messages_time_to_only() {
3163         // Create some users.
3164         $user1 = self::getDataGenerator()->create_user();
3165         $user2 = self::getDataGenerator()->create_user();
3167         // The person doing the search.
3168         $this->setUser($user1);
3170         // Send some messages back and forth.
3171         $time = 1;
3172         $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
3173         $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
3174         $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
3175         $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
3177         // Retrieve the messages up until $time + 4, which should be all of them.
3178         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 4);
3179         $this->assertDebuggingCalledCount(3);
3181         // Confirm the message data is correct.
3182         $this->assertEquals(4, count($messages));
3184         $message1 = $messages[0];
3185         $message2 = $messages[1];
3186         $message3 = $messages[2];
3187         $message4 = $messages[3];
3189         $this->assertContains('Message 1', $message1->text);
3190         $this->assertContains('Message 2', $message2->text);
3191         $this->assertContains('Message 3', $message3->text);
3192         $this->assertContains('Message 4', $message4->text);
3194         // Retrieve the messages up until $time + 2, which should be the first two.
3195         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 2);
3196         $this->assertDebuggingCalledCount(3);
3198         // Confirm the message data is correct.
3199         $this->assertEquals(2, count($messages));
3201         $message1 = $messages[0];
3202         $message2 = $messages[1];
3204         $this->assertContains('Message 1', $message1->text);
3205         $this->assertContains('Message 2', $message2->text);
3206     }
3208     /**
3209      * Test retrieving messages by providing a minimum and maximum timecreated value.
3210      */
3211     public function test_get_messages_time_from_and_to() {
3212         // Create some users.
3213         $user1 = self::getDataGenerator()->create_user();
3214         $user2 = self::getDataGenerator()->create_user();
3216         // The person doing the search.
3217         $this->setUser($user1);
3219         // Send some messages back and forth.
3220         $time = 1;
3221         $this->send_fake_message($user1, $user2, 'Message 1', 0, $time + 1);
3222         $this->send_fake_message($user2, $user1, 'Message 2', 0, $time + 2);
3223         $this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
3224         $this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
3226         // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
3227         $messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 2, $time + 3);
3228         $this->assertDebuggingCalledCount(3);
3230         // Confirm the message data is correct.
3231         $this->assertEquals(2, count($messages));
3233         $message1 = $messages[0];
3234         $message2 = $messages[1];
3236         $this->assertContains('Message 2', $message1->text);
3237         $this->assertContains('Message 3', $message2->text);
3238     }
3240     /**
3241      * Test returning blocked users.
3242      */
3243     public function test_get_blocked_users() {
3244         global $USER;
3246         // Set this user as the admin.
3247         $this->setAdminUser();
3249         // Create a user to add to the admin's contact list.
3250         $user1 = $this->getDataGenerator()->create_user();
3251         $user2 = $this->getDataGenerator()->create_user();
3253         // Add users to the admin's contact list.
3254         \core_message\api::block_user($USER->id, $user2->id);
3256         $this->assertCount(1, \core_message\api::get_blocked_users($USER->id));
3258         // Block other user.
3259         \core_message\api::block_user($USER->id, $user1->id);
3260         $this->assertCount(2, \core_message\api::get_blocked_users($USER->id));
3262         // Test deleting users.
3263         delete_user($user1);
3264         $this->assertCount(1, \core_message\api::get_blocked_users($USER->id));
3265     }
3267     /**
3268      * Test returning contacts with unread message count.
3269      */
3270     public function test_get_contacts_with_unread_message_count() {
3271         global $DB;
3273         $user1 = self::getDataGenerator()->create_user();
3274         $user2 = self::getDataGenerator()->create_user();
3275         $user3 = self::getDataGenerator()->create_user();
3276         $user4 = self::getDataGenerator()->create_user();
3278         // Add the users to each of their contacts.
3279         \core_message\api::add_contact($user1->id, $user2->id);
3280         \core_message\api::add_contact($user2->id, $user3->id);
3282         $this->send_fake_message($user1, $user2);
3283         $this->send_fake_message($user1, $user2);
3284         $this->send_fake_message($user1, $user2);
3285         $message4id = $this->send_fake_message($user1, $user2);
3287         $this->send_fake_message($user3, $user2);
3288         $message6id = $this->send_fake_message($user3, $user2);
3289         $this->send_fake_message($user3, $user2);
3290         $this->send_fake_message($user3, $user2);
3291         $this->send_fake_message($user3, $user2);
3293         // Send a message that should never be included as the user is not a contact.
3294         $this->send_fake_message($user4, $user2);
3296         // Get the contacts and the unread message count.
3297         $messages = \core_message\api::get_contacts_with_unread_message_count($user2->id);
3299         // Confirm the size is correct.
3300         $this->assertCount(2, $messages);
3301         ksort($messages);
3303         $messageinfo1 = array_shift($messages);
3304         $messageinfo2 = array_shift($messages);
3306         $this->assertEquals($user1->id, $messageinfo1->id);
3307         $this->assertEquals(4, $messageinfo1->messagecount);
3308         $this->assertEquals($user3->id, $messageinfo2->id);
3309         $this->assertEquals(5, $messageinfo2->messagecount);
3311         // Mark some of the messages as read.
3312         $m4 = $DB->get_record('messages', ['id' => $message4id]);
3313         $m6 = $DB->get_record('messages', ['id' => $message6id]);
3314         \core_message\api::mark_message_as_read($user2->id, $m4);