weekly release 3.8dev
[moodle.git] / message / tests / api_test.php
CommitLineData
79f6c36c
MN
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/>.
16
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 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29
30require_once($CFG->dirroot . '/message/tests/messagelib_test.php');
31
fb04293b
SA
32use \core_message\tests\helper as testhelper;
33
79f6c36c
MN
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 */
42class core_message_api_testcase extends core_message_messagelib_testcase {
43
1f64514d 44 public function test_mark_all_read_for_user_touser() {
79f6c36c
MN
45 $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
46 $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
47
7d69958e
RW
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);
79f6c36c
MN
51 $this->send_fake_message($sender, $recipient);
52 $this->send_fake_message($sender, $recipient);
53 $this->send_fake_message($sender, $recipient);
54
55 \core_message\api::mark_all_read_for_user($recipient->id);
74ad60bf 56 $this->assertDebuggingCalled();
79f6c36c
MN
57 $this->assertEquals(message_count_unread_messages($recipient), 0);
58 }
59
1f64514d 60 public function test_mark_all_read_for_user_touser_with_fromuser() {
79f6c36c
MN
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'));
64
7d69958e
RW
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);
79f6c36c
MN
68 $this->send_fake_message($sender1, $recipient);
69 $this->send_fake_message($sender1, $recipient);
70 $this->send_fake_message($sender1, $recipient);
7d69958e
RW
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);
79f6c36c
MN
74 $this->send_fake_message($sender2, $recipient);
75 $this->send_fake_message($sender2, $recipient);
76 $this->send_fake_message($sender2, $recipient);
77
78 \core_message\api::mark_all_read_for_user($recipient->id, $sender1->id);
74ad60bf 79 $this->assertDebuggingCalled();
29c3b0b4 80 $this->assertEquals(message_count_unread_messages($recipient), 3);
79f6c36c
MN
81 }
82
1f64514d 83 public function test_mark_all_read_for_user_touser_with_type() {
79f6c36c
MN
84 $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
85 $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
86
7d69958e
RW
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);
79f6c36c
MN
90 $this->send_fake_message($sender, $recipient);
91 $this->send_fake_message($sender, $recipient);
92 $this->send_fake_message($sender, $recipient);
93
94 \core_message\api::mark_all_read_for_user($recipient->id, 0, MESSAGE_TYPE_NOTIFICATION);
74ad60bf 95 $this->assertDebuggingCalled();
79f6c36c
MN
96 $this->assertEquals(message_count_unread_messages($recipient), 3);
97
98 \core_message\api::mark_all_read_for_user($recipient->id, 0, MESSAGE_TYPE_MESSAGE);
74ad60bf 99 $this->assertDebuggingCalled();
79f6c36c
MN
100 $this->assertEquals(message_count_unread_messages($recipient), 0);
101 }
102
5b0769db
MN
103 /**
104 * Test count_blocked_users.
5b0769db 105 */
1f64514d 106 public function test_count_blocked_users() {
f219eac7
MN
107 global $USER;
108
5b0769db
MN
109 // Set this user as the admin.
110 $this->setAdminUser();
111
f219eac7 112 // Create user to add to the admin's block list.
5b0769db 113 $user1 = $this->getDataGenerator()->create_user();
f7dfa9ba 114 $user2 = $this->getDataGenerator()->create_user();
5b0769db
MN
115
116 $this->assertEquals(0, \core_message\api::count_blocked_users());
117
f219eac7
MN
118 // Add 1 blocked user to admin's blocked user list.
119 \core_message\api::block_user($USER->id, $user1->id);
5b0769db 120
f219eac7 121 $this->assertEquals(0, \core_message\api::count_blocked_users($user1));
5b0769db
MN
122 $this->assertEquals(1, \core_message\api::count_blocked_users());
123 }
1f64514d
MN
124
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);
134
135 // The person doing the search.
136 $this->setUser($user1);
137
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);
144
145 // Block the second user.
f219eac7 146 \core_message\api::block_user($user1->id, $user2->id);
1f64514d
MN
147
148 $user3 = new stdClass();
149 $user3->firstname = 'User';
150 $user3->lastname = 'Three';
151 $user3 = self::getDataGenerator()->create_user($user3);
152
153 // Create a course.
154 $course1 = new stdClass();
155 $course1->fullname = 'Course';
156 $course1->shortname = 'One';
157 $course1 = $this->getDataGenerator()->create_course($course1);
158
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);
162
163 // Perform a search.
164 $results = \core_message\api::search_users_in_course($user1->id, $course1->id, 'User');
165
166 $this->assertEquals(1, count($results));
167
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);
cb805753 174 $this->assertNull($user->isonline);
1f64514d
MN
175 $this->assertFalse($user->isread);
176 $this->assertTrue($user->isblocked);
177 $this->assertNull($user->unreadcount);
178 }
179
180 /**
181 * Tests searching users.
182 */
183 public function test_search_users() {
09a05b79
AN
184 global $DB;
185
1f64514d
MN
186 // Create some users.
187 $user1 = new stdClass();
188 $user1->firstname = 'User';
189 $user1->lastname = 'One';
190 $user1 = self::getDataGenerator()->create_user($user1);
191
192 // Set as the user performing the search.
193 $this->setUser($user1);
194
195 $user2 = new stdClass();
196 $user2->firstname = 'User search';
197 $user2->lastname = 'Two';
198 $user2 = self::getDataGenerator()->create_user($user2);
199
200 $user3 = new stdClass();
201 $user3->firstname = 'User search';
202 $user3->lastname = 'Three';
203 $user3 = self::getDataGenerator()->create_user($user3);
204
205 $user4 = new stdClass();
206 $user4->firstname = 'User';
207 $user4->lastname = 'Four';
208 $user4 = self::getDataGenerator()->create_user($user4);
209
210 $user5 = new stdClass();
211 $user5->firstname = 'User search';
212 $user5->lastname = 'Five';
213 $user5 = self::getDataGenerator()->create_user($user5);
214
215 $user6 = new stdClass();
216 $user6->firstname = 'User';
217 $user6->lastname = 'Six';
218 $user6 = self::getDataGenerator()->create_user($user6);
219
220 // Create some courses.
221 $course1 = new stdClass();
222 $course1->fullname = 'Course search';
223 $course1->shortname = 'One';
224 $course1 = $this->getDataGenerator()->create_course($course1);
225
226 $course2 = new stdClass();
227 $course2->fullname = 'Course';
228 $course2->shortname = 'Two';
229 $course2 = $this->getDataGenerator()->create_course($course2);
230
231 $course3 = new stdClass();
232 $course3->fullname = 'Course';
233 $course3->shortname = 'Three search';
234 $course3 = $this->getDataGenerator()->create_course($course3);
235
87d4ab65
AG
236 $course4 = new stdClass();
237 $course4->fullname = 'Course Four';
238 $course4->shortname = 'CF100';
239 $course4 = $this->getDataGenerator()->create_course($course4);
240
09a05b79
AN
241 $course5 = new stdClass();
242 $course5->fullname = 'Course';
243 $course5->shortname = 'Five search';
244 $course5 = $this->getDataGenerator()->create_course($course5);
245
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);
87d4ab65 251
1f64514d 252 // Add some users as contacts.
f219eac7
MN
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);
1f64514d 256
09a05b79
AN
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);
09a05b79 260
548cac7d
AA
261 // Perform a search $CFG->messagingallusers setting enabled.
262 set_config('messagingallusers', 1);
1f64514d
MN
263 list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
264
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);
269
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);
274
275 // Check that we retrieved the correct non-contacts.
276 $this->assertEquals(1, count($noncontacts));
277 $this->assertEquals($user5->id, $noncontacts[0]->userid);
278 }
279
548cac7d
AA
280 /**
281 * Tests searching users with empty result.
282 */
283 public function test_search_users_with_empty_result() {
284
285 // Create some users.
286 $user1 = new stdClass();
287 $user1->firstname = 'User';
288 $user1->lastname = 'One';
289 $user1 = self::getDataGenerator()->create_user($user1);
290
291 // Set as the user performing the search.
292 $this->setUser($user1);
293
294 $user2 = new stdClass();
295 $user2->firstname = 'User';
296 $user2->lastname = 'Two';
297 $user2 = self::getDataGenerator()->create_user($user2);
298
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');
302
303 // Check results are empty.
304 $this->assertEquals(0, count($contacts));
305 $this->assertEquals(0, count($courses));
306 $this->assertEquals(0, count($noncontacts));
307 }
308
309 /**
41485be2
JD
310 * Tests searching for users when site-wide messaging is disabled.
311 *
312 * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
313 * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
314 * profile.
548cac7d 315 */
41485be2 316 public function test_message_search_users_messagingallusers_disabled() {
3edac090 317 global $DB;
41485be2
JD
318 $this->resetAfterTest();
319
548cac7d 320 // Create some users.
41485be2 321 $users = [];
3edac090 322 foreach (range(1, 8) as $i) {
41485be2
JD
323 $user = new stdClass();
324 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
325 $user->lastname = $i;
326 $user = $this->getDataGenerator()->create_user($user);
327 $users[$i] = $user;
328 }
329
330 // Enrol a few users in the same course, but leave them as non-contacts.
331 $course1 = $this->getDataGenerator()->create_course();
3edac090
JD
332 $course2 = $this->getDataGenerator()->create_course();
333
41485be2
JD
334 $this->setAdminUser();
335 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
336 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
337 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
338
339 // Add some other users as contacts.
340 \core_message\api::add_contact($users[1]->id, $users[2]->id);
341 \core_message\api::add_contact($users[3]->id, $users[1]->id);
342 \core_message\api::add_contact($users[1]->id, $users[4]->id);
343
3edac090
JD
344 // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
345 $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher');
346 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
347 set_config('coursecontact', $teacherrole->id);
348
41485be2
JD
349 // Create individual conversations between some users, one contact and one non-contact.
350 $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
351 [$users[1]->id, $users[2]->id]);
352 $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
353 [$users[6]->id, $users[1]->id]);
354
355 // Create a group conversation between 4 users, including a contact and a non-contact.
356 $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
357 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
548cac7d
AA
358
359 // Set as the user performing the search.
41485be2 360 $this->setUser($users[1]);
548cac7d 361
41485be2
JD
362 // Perform a search with $CFG->messagingallusers disabled.
363 set_config('messagingallusers', 0);
364 $result = \core_message\api::message_search_users($users[1]->id, 'search');
548cac7d 365
41485be2
JD
366 // Confirm that we returns contacts and non-contacts.
367 $this->assertArrayHasKey(0, $result);
368 $this->assertArrayHasKey(1, $result);
369 $contacts = $result[0];
370 $noncontacts = $result[1];
548cac7d 371
41485be2
JD
372 // Check that we retrieved the correct contacts.
373 $this->assertCount(2, $contacts);
374 $this->assertEquals($users[2]->id, $contacts[0]->id);
375 $this->assertEquals($users[3]->id, $contacts[1]->id);
548cac7d 376
41485be2
JD
377 // Verify the correct conversations were returned for the contacts.
378 $this->assertCount(2, $contacts[0]->conversations);
379 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
380 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
548cac7d 381
41485be2 382 $this->assertCount(0, $contacts[1]->conversations);
548cac7d 383
41485be2 384 // Check that we retrieved the correct non-contacts.
3edac090
JD
385 // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles
386 // are visible in that course. This excludes users like course contacts.
888a467a
AA
387 $this->assertCount(3, $noncontacts);
388 // Self-conversation first.
389 $this->assertEquals($users[1]->id, $noncontacts[0]->id);
390 $this->assertEquals($users[6]->id, $noncontacts[1]->id);
391 $this->assertEquals($users[7]->id, $noncontacts[2]->id);
548cac7d 392
41485be2 393 // Verify the correct conversations were returned for the non-contacts.
888a467a 394 $this->assertCount(1, $noncontacts[1]->conversations);
41485be2 395 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
888a467a 396 $noncontacts[1]->conversations[$ic2->id]->type);
548cac7d 397
888a467a
AA
398 $this->assertCount(1, $noncontacts[2]->conversations);
399 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
41485be2 400 }
548cac7d 401
41485be2
JD
402 /**
403 * Tests searching for users when site-wide messaging is enabled.
404 *
3edac090
JD
405 * This test verifies that any contacts are returned, as well as any non-contacts,
406 * provided the searching user can view their profile.
41485be2
JD
407 */
408 public function test_message_search_users_messagingallusers_enabled() {
3edac090 409 global $DB;
41485be2
JD
410 $this->resetAfterTest();
411
412 // Create some users.
413 $users = [];
3edac090 414 foreach (range(1, 9) as $i) {
41485be2
JD
415 $user = new stdClass();
416 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
417 $user->lastname = $i;
418 $user = $this->getDataGenerator()->create_user($user);
419 $users[$i] = $user;
420 }
421
41485be2 422 $course1 = $this->getDataGenerator()->create_course();
3edac090
JD
423 $coursecontext = \context_course::instance($course1->id);
424
425 // Enrol a few users in the same course, but leave them as non-contacts.
41485be2 426 $this->setAdminUser();
3edac090
JD
427 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id, 'student');
428 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id, 'student');
429 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id, 'student');
41485be2
JD
430
431 // Add some other users as contacts.
432 \core_message\api::add_contact($users[1]->id, $users[2]->id);
433 \core_message\api::add_contact($users[3]->id, $users[1]->id);
434 \core_message\api::add_contact($users[1]->id, $users[4]->id);
435
3edac090
JD
436 // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
437 $this->getDataGenerator()->enrol_user($users[9]->id, $course1->id, 'editingteacher');
438 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
439 set_config('coursecontact', $teacherrole->id);
440
888a467a
AA
441 // Get self-conversation.
442 $selfconversation = \core_message\api::get_self_conversation($users[1]->id);
443
41485be2
JD
444 // Create individual conversations between some users, one contact and one non-contact.
445 $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
446 [$users[1]->id, $users[2]->id]);
447 $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
448 [$users[6]->id, $users[1]->id]);
449
450 // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
451 $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
452 [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
453
454 // Set as the user performing the search.
455 $this->setUser($users[1]);
456
457 // Perform a search with $CFG->messagingallusers enabled.
548cac7d 458 set_config('messagingallusers', 1);
41485be2
JD
459 $result = \core_message\api::message_search_users($users[1]->id, 'search');
460
461 // Confirm that we returns contacts and non-contacts.
462 $this->assertArrayHasKey(0, $result);
463 $this->assertArrayHasKey(1, $result);
464 $contacts = $result[0];
465 $noncontacts = $result[1];
548cac7d
AA
466
467 // Check that we retrieved the correct contacts.
468 $this->assertCount(2, $contacts);
41485be2
JD
469 $this->assertEquals($users[2]->id, $contacts[0]->id);
470 $this->assertEquals($users[3]->id, $contacts[1]->id);
471
472 // Verify the correct conversations were returned for the contacts.
473 $this->assertCount(2, $contacts[0]->conversations);
474 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
475 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
476
477 $this->assertCount(0, $contacts[1]->conversations);
548cac7d
AA
478
479 // Check that we retrieved the correct non-contacts.
3edac090
JD
480 // If site wide messaging is enabled, we expect to only be able to search for users whose profiles we can view.
481 // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1.
888a467a
AA
482 // Consider first conversations is self-conversation.
483 $this->assertCount(4, $noncontacts);
484 $this->assertEquals($users[1]->id, $noncontacts[0]->id);
485 $this->assertEquals($users[6]->id, $noncontacts[1]->id);
486 $this->assertEquals($users[7]->id, $noncontacts[2]->id);
487 $this->assertEquals($users[9]->id, $noncontacts[3]->id);
488
41485be2 489 $this->assertCount(1, $noncontacts[1]->conversations);
888a467a
AA
490 $this->assertCount(1, $noncontacts[2]->conversations);
491 $this->assertCount(0, $noncontacts[3]->conversations);
492
493 // Verify the correct conversations were returned for the non-contacts.
494 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
495 $noncontacts[0]->conversations[$selfconversation->id]->type);
496
497 $this->assertCount(1, $noncontacts[1]->conversations);
498 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
499 $noncontacts[1]->conversations[$ic2->id]->type);
500
501 $this->assertCount(1, $noncontacts[2]->conversations);
502 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
503
504 $this->assertCount(0, $noncontacts[3]->conversations);
41485be2
JD
505 }
506
734b198f
SA
507 /**
508 * Verify searching for users find themselves when they have self-conversations.
509 */
510 public function test_message_search_users_self_conversations() {
511 $this->resetAfterTest();
512
513 // Create some users.
514 $user1 = new stdClass();
515 $user1->firstname = 'User';
516 $user1->lastname = 'One';
517 $user1 = $this->getDataGenerator()->create_user($user1);
518 $user2 = new stdClass();
519 $user2->firstname = 'User';
520 $user2->lastname = 'Two';
521 $user2 = $this->getDataGenerator()->create_user($user2);
522
888a467a
AA
523 // Get self-conversation for user1.
524 $sc1 = \core_message\api::get_self_conversation($user1->id);
734b198f
SA
525 testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
526
527 // Perform a search as user1.
528 $this->setUser($user1);
529 $result = \core_message\api::message_search_users($user1->id, 'One');
530
531 // Check user1 is found as non-contacts.
532 $this->assertCount(0, $result[0]);
533 $this->assertCount(1, $result[1]);
534 }
535
41485be2
JD
536 /**
537 * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
538 */
539 public function test_message_search_users_with_empty_result() {
540 $this->resetAfterTest();
541
542 // Create some users, but make sure neither will match the search term.
543 $user1 = new stdClass();
544 $user1->firstname = 'User';
545 $user1->lastname = 'One';
546 $user1 = $this->getDataGenerator()->create_user($user1);
547 $user2 = new stdClass();
548 $user2->firstname = 'User';
549 $user2->lastname = 'Two';
550 $user2 = $this->getDataGenerator()->create_user($user2);
551
552 // Perform a search as user1.
553 $this->setUser($user1);
554 $result = \core_message\api::message_search_users($user1->id, 'search');
555
556 // Check results are empty.
557 $this->assertCount(0, $result[0]);
558 $this->assertCount(0, $result[1]);
559 }
560
561 /**
562 * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
563 */
564 public function test_message_search_users_limit_offset() {
565 $this->resetAfterTest();
566
567 // Create 20 users.
568 $users = [];
569 foreach (range(1, 20) as $i) {
570 $user = new stdClass();
571 $user->firstname = "User search";
572 $user->lastname = $i;
573 $user = $this->getDataGenerator()->create_user($user);
574 $users[$i] = $user;
575 }
576
577 // Enrol the first 9 users in the same course, but leave them as non-contacts.
578 $this->setAdminUser();
579 $course1 = $this->getDataGenerator()->create_course();
888a467a 580 foreach (range(1, 8) as $i) {
41485be2
JD
581 $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
582 }
583
584 // Add 5 users, starting at the 11th user, as contacts for user1.
585 foreach (range(11, 15) as $i) {
586 \core_message\api::add_contact($users[1]->id, $users[$i]->id);
587 }
588
589 // Set as the user performing the search.
590 $this->setUser($users[1]);
591
592 // Search using a limit of 3.
593 // This tests the case where we have more results than the limit for both contacts and non-contacts.
594 $result = \core_message\api::message_search_users($users[1]->id, 'search', 0, 3);
595 $contacts = $result[0];
596 $noncontacts = $result[1];
597
598 // Check that we retrieved the correct contacts.
599 $this->assertCount(3, $contacts);
600 $this->assertEquals($users[11]->id, $contacts[0]->id);
601 $this->assertEquals($users[12]->id, $contacts[1]->id);
602 $this->assertEquals($users[13]->id, $contacts[2]->id);
603
604 // Check that we retrieved the correct non-contacts.
888a467a 605 // Consider first conversations is self-conversation.
41485be2 606 $this->assertCount(3, $noncontacts);
888a467a
AA
607 $this->assertEquals($users[1]->id, $noncontacts[0]->id);
608 $this->assertEquals($users[2]->id, $noncontacts[1]->id);
609 $this->assertEquals($users[3]->id, $noncontacts[2]->id);
41485be2
JD
610
611 // Now, offset to get the next batch of results.
612 // We expect to see 2 contacts, and 3 non-contacts.
613 $result = \core_message\api::message_search_users($users[1]->id, 'search', 3, 3);
614 $contacts = $result[0];
615 $noncontacts = $result[1];
616 $this->assertCount(2, $contacts);
617 $this->assertEquals($users[14]->id, $contacts[0]->id);
618 $this->assertEquals($users[15]->id, $contacts[1]->id);
619
548cac7d 620 $this->assertCount(3, $noncontacts);
888a467a
AA
621 $this->assertEquals($users[4]->id, $noncontacts[0]->id);
622 $this->assertEquals($users[5]->id, $noncontacts[1]->id);
623 $this->assertEquals($users[6]->id, $noncontacts[2]->id);
41485be2
JD
624
625 // Now, offset to get the next batch of results.
626 // We expect to see 0 contacts, and 2 non-contacts.
627 $result = \core_message\api::message_search_users($users[1]->id, 'search', 6, 3);
628 $contacts = $result[0];
629 $noncontacts = $result[1];
630 $this->assertCount(0, $contacts);
631
632 $this->assertCount(2, $noncontacts);
888a467a
AA
633 $this->assertEquals($users[7]->id, $noncontacts[0]->id);
634 $this->assertEquals($users[8]->id, $noncontacts[1]->id);
41485be2 635 }
548cac7d 636
41485be2
JD
637 /**
638 * Tests searching users as a user having the 'moodle/user:viewdetails' capability.
639 */
640 public function test_message_search_users_with_cap() {
641 $this->resetAfterTest();
642 global $DB;
643
644 // Create some users.
645 $users = [];
646 foreach (range(1, 8) as $i) {
647 $user = new stdClass();
648 $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
649 $user->lastname = $i;
650 $user = $this->getDataGenerator()->create_user($user);
651 $users[$i] = $user;
652 }
653
654 // Enrol a few users in the same course, but leave them as non-contacts.
655 $course1 = $this->getDataGenerator()->create_course();
656 $this->setAdminUser();
657 $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
658 $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
659 $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
660
661 // Add some other users as contacts.
662 \core_message\api::add_contact($users[1]->id, $users[2]->id);
663 \core_message\api::add_contact($users[3]->id, $users[1]->id);
664 \core_message\api::add_contact($users[1]->id, $users[4]->id);
665
666 // Set as the user performing the search.
667 $this->setUser($users[1]);
668
669 // Grant the authenticated user role the capability 'user:viewdetails' at site context.
670 $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
671 assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, context_system::instance());
672
673 // Perform a search with $CFG->messagingallusers disabled.
548cac7d 674 set_config('messagingallusers', 0);
41485be2
JD
675 $result = \core_message\api::message_search_users($users[1]->id, 'search');
676 $contacts = $result[0];
677 $noncontacts = $result[1];
548cac7d
AA
678
679 // Check that we retrieved the correct contacts.
680 $this->assertCount(2, $contacts);
41485be2
JD
681 $this->assertEquals($users[2]->id, $contacts[0]->id);
682 $this->assertEquals($users[3]->id, $contacts[1]->id);
548cac7d
AA
683
684 // Check that we retrieved the correct non-contacts.
3edac090 685 // Site-wide messaging is disabled, so we expect to be able to search for any users whose profiles we can view.
888a467a
AA
686 // Consider first conversations is self-conversation.
687 $this->assertCount(3, $noncontacts);
688 $this->assertEquals($users[1]->id, $noncontacts[0]->id);
689 $this->assertEquals($users[6]->id, $noncontacts[1]->id);
690 $this->assertEquals($users[7]->id, $noncontacts[2]->id);
41485be2
JD
691 }
692
693 /**
694 * Tests searching users with messaging disabled.
695 */
696 public function test_message_search_users_messaging_disabled() {
697 $this->resetAfterTest();
698
699 // Create a user.
700 $user = $this->getDataGenerator()->create_user();
701
702 // Disable messaging.
703 set_config('messaging', 0);
704
705 // Ensure an exception is thrown.
706 $this->expectException('moodle_exception');
707 \core_message\api::message_search_users($user->id, 'User');
548cac7d
AA
708 }
709
710 /**
711 * Tests getting conversations between 2 users.
712 */
713 public function test_get_conversations_between_users() {
714 // Create some users.
715 $user1 = new stdClass();
716 $user1->firstname = 'User';
717 $user1->lastname = 'One';
718 $user1 = self::getDataGenerator()->create_user($user1);
719
720 $user2 = new stdClass();
721 $user2->firstname = 'User';
722 $user2->lastname = 'Two';
723 $user2 = self::getDataGenerator()->create_user($user2);
724
725 $user3 = new stdClass();
726 $user3->firstname = 'User search';
727 $user3->lastname = 'Three';
728 $user3 = self::getDataGenerator()->create_user($user3);
729
730 $user4 = new stdClass();
731 $user4->firstname = 'User';
732 $user4->lastname = 'Four';
733 $user4 = self::getDataGenerator()->create_user($user4);
734
735 $user5 = new stdClass();
736 $user5->firstname = 'User';
737 $user5->lastname = 'Five';
738 $user5 = self::getDataGenerator()->create_user($user5);
739
740 $user6 = new stdClass();
741 $user6->firstname = 'User search';
742 $user6->lastname = 'Six';
743 $user6 = self::getDataGenerator()->create_user($user6);
744
745 // Add some users as contacts.
746 \core_message\api::add_contact($user1->id, $user2->id);
747 \core_message\api::add_contact($user6->id, $user1->id);
748
749 // Create private conversations with some users.
750 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
751 array($user1->id, $user2->id));
752 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
753 array($user3->id, $user1->id));
754
755 // Create a group conversation with users.
756 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
757 array($user1->id, $user2->id, $user3->id, $user4->id),
758 'Project chat');
759
760 // Check that we retrieved the correct conversations.
761 $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user2->id));
762 $this->assertCount(2, \core_message\api::get_conversations_between_users($user2->id, $user1->id));
763 $this->assertCount(2, \core_message\api::get_conversations_between_users($user1->id, $user3->id));
764 $this->assertCount(2, \core_message\api::get_conversations_between_users($user3->id, $user1->id));
765 $this->assertCount(1, \core_message\api::get_conversations_between_users($user1->id, $user4->id));
766 $this->assertCount(1, \core_message\api::get_conversations_between_users($user4->id, $user1->id));
767 $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user5->id));
768 $this->assertCount(0, \core_message\api::get_conversations_between_users($user5->id, $user1->id));
769 $this->assertCount(0, \core_message\api::get_conversations_between_users($user1->id, $user6->id));
770 $this->assertCount(0, \core_message\api::get_conversations_between_users($user6->id, $user1->id));
771 }
772
734b198f
SA
773 /**
774 * Tests getting self-conversations.
775 */
776 public function test_get_self_conversation() {
777 // Create some users.
778 $user1 = new stdClass();
779 $user1->firstname = 'User';
780 $user1->lastname = 'One';
781 $user1 = self::getDataGenerator()->create_user($user1);
782
783 $user2 = new stdClass();
784 $user2->firstname = 'User';
785 $user2->lastname = 'Two';
786 $user2 = self::getDataGenerator()->create_user($user2);
787
788 $user3 = new stdClass();
789 $user3->firstname = 'User search';
790 $user3->lastname = 'Three';
791 $user3 = self::getDataGenerator()->create_user($user3);
792
793 // Add some users as contacts.
794 \core_message\api::add_contact($user1->id, $user2->id);
795 \core_message\api::add_contact($user3->id, $user1->id);
796
797 // Create private conversations with some users.
798 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
799 array($user1->id, $user2->id));
800 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
801 array($user3->id, $user1->id));
802
803 // Create a group conversation with users.
804 $gc = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
805 array($user1->id, $user2->id, $user3->id),
806 'Project chat');
807
888a467a 808 // Get self-conversations.
734b198f
SA
809 $rsc1 = \core_message\api::get_self_conversation($user1->id);
810 $rsc2 = \core_message\api::get_self_conversation($user2->id);
811 $rsc3 = \core_message\api::get_self_conversation($user3->id);
812
888a467a
AA
813 // Send message to self-conversation.
814 testhelper::send_fake_message_to_conversation($user1, $rsc1->id, 'Message to myself!');
815
734b198f 816 // Check that we retrieved the correct conversations.
888a467a
AA
817 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, $rsc1->type);
818 $members = \core_message\api::get_conversation_members($user1->id, $rsc1->id);
819 $this->assertCount(1, $members);
820 $member = reset($members);
821 $this->assertEquals($user1->id, $member->id);
822
823 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, $rsc2->type);
824 $members = \core_message\api::get_conversation_members($user2->id, $rsc2->id);
825 $this->assertCount(1, $members);
826 $member = reset($members);
827 $this->assertEquals($user2->id, $member->id);
828
829 \core_message\api::delete_all_conversation_data($rsc3->id);
7918a0ea
JD
830 $selfconversation = \core_message\api::get_self_conversation($user3->id);
831 $members = \core_message\api::get_conversation_members($user1->id, $selfconversation->id);
832 $this->assertCount(1, $members);
734b198f
SA
833 }
834
1f64514d
MN
835 /**
836 * Tests searching messages.
837 */
838 public function test_search_messages() {
27674261
SA
839 $this->resetAfterTest();
840
1f64514d
MN
841 // Create some users.
842 $user1 = self::getDataGenerator()->create_user();
843 $user2 = self::getDataGenerator()->create_user();
f219eac7 844 $user3 = self::getDataGenerator()->create_user();
1f64514d
MN
845
846 // The person doing the search.
847 $this->setUser($user1);
848
888a467a
AA
849 // Get self-conversation.
850 $sc = \core_message\api::get_self_conversation($user1->id);
734b198f 851
27674261
SA
852 // Create group conversation.
853 $gc = \core_message\api::create_conversation(
854 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
855 [$user1->id, $user2->id, $user3->id]
856 );
857
1f64514d
MN
858 // Send some messages back and forth.
859 $time = 1;
734b198f
SA
860 testhelper::send_fake_message_to_conversation($user1, $sc->id, 'Test message to self!', $time);
861 testhelper::send_fake_message_to_conversation($user1, $gc->id, 'My hero!', $time + 1);
862 $this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time + 2);
863 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 3);
864 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 4);
865 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 5);
866 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 6);
f219eac7 867
d2708759
JD
868 $convid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
869 $conv2id = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
870
f219eac7
MN
871 // Block user 3.
872 \core_message\api::block_user($user1->id, $user3->id);
1f64514d
MN
873
874 // Perform a search.
875 $messages = \core_message\api::search_messages($user1->id, 'o');
876
877 // Confirm the data is correct.
734b198f 878 $this->assertEquals(5, count($messages));
1f64514d
MN
879 $message1 = $messages[0];
880 $message2 = $messages[1];
f219eac7 881 $message3 = $messages[2];
27674261 882 $message4 = $messages[3];
734b198f 883 $message5 = $messages[4];
1f64514d
MN
884
885 $this->assertEquals($user2->id, $message1->userid);
886 $this->assertEquals($user2->id, $message1->useridfrom);
887 $this->assertEquals(fullname($user2), $message1->fullname);
888 $this->assertTrue($message1->ismessaging);
889 $this->assertEquals('Word.', $message1->lastmessage);
890 $this->assertNotEmpty($message1->messageid);
cb805753 891 $this->assertNull($message1->isonline);
1f64514d
MN
892 $this->assertFalse($message1->isread);
893 $this->assertFalse($message1->isblocked);
894 $this->assertNull($message1->unreadcount);
d2708759 895 $this->assertEquals($convid, $message1->conversationid);
1f64514d
MN
896
897 $this->assertEquals($user2->id, $message2->userid);
898 $this->assertEquals($user1->id, $message2->useridfrom);
899 $this->assertEquals(fullname($user2), $message2->fullname);
900 $this->assertTrue($message2->ismessaging);
901 $this->assertEquals('Yo!', $message2->lastmessage);
902 $this->assertNotEmpty($message2->messageid);
cb805753 903 $this->assertNull($message2->isonline);
1f64514d
MN
904 $this->assertTrue($message2->isread);
905 $this->assertFalse($message2->isblocked);
906 $this->assertNull($message2->unreadcount);
d2708759 907 $this->assertEquals($convid, $message2->conversationid);
f219eac7
MN
908
909 $this->assertEquals($user3->id, $message3->userid);
910 $this->assertEquals($user3->id, $message3->useridfrom);
911 $this->assertEquals(fullname($user3), $message3->fullname);
912 $this->assertTrue($message3->ismessaging);
913 $this->assertEquals('Don\'t block me.', $message3->lastmessage);
914 $this->assertNotEmpty($message3->messageid);
915 $this->assertNull($message3->isonline);
916 $this->assertFalse($message3->isread);
917 $this->assertTrue($message3->isblocked);
918 $this->assertNull($message3->unreadcount);
d2708759 919 $this->assertEquals($conv2id, $message3->conversationid);
27674261
SA
920
921 // This is a group conversation. For now, search_messages returns only one of the other users on the conversation. It can't
922 // be guaranteed who will be returned in the first place, so we need to use the in_array to check all the possibilities.
923 $this->assertTrue(in_array($message4->userid, [$user2->id, $user3->id]));
924 $this->assertEquals($user1->id, $message4->useridfrom);
925 $this->assertTrue($message4->ismessaging);
926 $this->assertEquals('My hero!', $message4->lastmessage);
927 $this->assertNotEmpty($message4->messageid);
928 $this->assertNull($message4->isonline);
929 $this->assertTrue($message4->isread);
930 $this->assertNull($message4->unreadcount);
931 $this->assertEquals($gc->id, $message4->conversationid);
734b198f
SA
932
933 $this->assertEquals($user1->id, $message5->userid);
934 $this->assertEquals($user1->id, $message5->useridfrom);
935 $this->assertEquals(fullname($user1), $message5->fullname);
936 $this->assertTrue($message5->ismessaging);
937 $this->assertEquals('Test message to self!', $message5->lastmessage);
938 $this->assertNotEmpty($message5->messageid);
939 $this->assertFalse($message5->isonline);
940 $this->assertTrue($message5->isread);
941 $this->assertFalse($message5->isblocked);
942 $this->assertNull($message5->unreadcount);
943 $this->assertEquals($sc->id, $message5->conversationid);
1f64514d
MN
944 }
945
946 /**
b8ff2c44
JD
947 * Test verifying that favourited conversations can be retrieved.
948 */
949 public function test_get_favourite_conversations() {
950 // Create some users.
951 $user1 = self::getDataGenerator()->create_user();
952 $user2 = self::getDataGenerator()->create_user();
953 $user3 = self::getDataGenerator()->create_user();
954 $user4 = self::getDataGenerator()->create_user();
955
956 // The person doing the search.
957 $this->setUser($user1);
958
888a467a
AA
959 // Only self-conversation created.
960 $this->assertCount(1, \core_message\api::get_conversations($user1->id));
b8ff2c44
JD
961
962 // Create some conversations for user1.
963 $time = 1;
964 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
965 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
966 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
967 $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
968
969 $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
970 $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
971 $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
972 $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
973
974 $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
975 $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
976 $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
977
978 // Favourite the first 2 conversations for user1.
979 $convoids = [];
980 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
981 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
982 $user1context = context_user::instance($user1->id);
983 $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
984 foreach ($convoids as $convoid) {
985 $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
986 }
987
888a467a
AA
988 // We should have 4 conversations.
989 // Consider first conversations is self-conversation.
990 $this->assertCount(4, \core_message\api::get_conversations($user1->id));
b8ff2c44 991
888a467a 992 // And 3 favourited conversations (self-conversation included).
b8ff2c44 993 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
888a467a
AA
994 $this->assertCount(3, $conversations);
995 $conversations = \core_message\api::get_conversations(
996 $user1->id,
997 0,
998 20,
999 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
1000 true
1001 );
1002 $this->assertCount(1, $conversations);
b8ff2c44
JD
1003 }
1004
1005 /**
1006 * Tests retrieving favourite conversations with a limit and offset to ensure pagination works correctly.
1007 */
1008 public function test_get_favourite_conversations_limit_offset() {
1009 // Create some users.
1010 $user1 = self::getDataGenerator()->create_user();
1011 $user2 = self::getDataGenerator()->create_user();
1012 $user3 = self::getDataGenerator()->create_user();
1013 $user4 = self::getDataGenerator()->create_user();
1014
1015 // The person doing the search.
1016 $this->setUser($user1);
1017
888a467a
AA
1018 // Only self-conversation created.
1019 $this->assertCount(1, \core_message\api::get_conversations($user1->id));
b8ff2c44
JD
1020
1021 // Create some conversations for user1.
1022 $time = 1;
1023 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1024 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1025 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1026 $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1027
1028 $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1029 $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1030 $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1031 $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1032
1033 $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
1034 $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
1035 $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
1036
1037 // Favourite the all conversations for user1.
1038 $convoids = [];
1039 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1040 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1041 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user4->id]);
1042 $user1context = context_user::instance($user1->id);
1043 $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
1044 foreach ($convoids as $convoid) {
1045 $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
1046 }
1047
888a467a 1048 // Consider first conversations is self-conversation.
b8ff2c44 1049 // Get all records, using offset 0 and large limit.
888a467a 1050 $this->assertCount(4, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
b8ff2c44
JD
1051
1052 // Now, get 10 conversations starting at the second record. We should see 2 conversations.
888a467a 1053 $this->assertCount(3, \core_message\api::get_conversations($user1->id, 1, 10, null, true));
b8ff2c44
JD
1054
1055 // Now, try to get favourited conversations using an invalid offset.
888a467a 1056 $this->assertCount(0, \core_message\api::get_conversations($user1->id, 5, 10, null, true));
b8ff2c44
JD
1057 }
1058
1059 /**
1060 * Tests retrieving favourite conversations when a conversation contains a deleted user.
1061 */
1062 public function test_get_favourite_conversations_with_deleted_user() {
1063 // Create some users.
1064 $user1 = self::getDataGenerator()->create_user();
1065 $user2 = self::getDataGenerator()->create_user();
1066 $user3 = self::getDataGenerator()->create_user();
1067
1068 // Send some messages back and forth, have some different conversations with different users.
1069 $time = 1;
1070 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1071 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1072 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1073 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1074
1075 $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1076 $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1077 $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1078 $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1079
1080 // Favourite the all conversations for user1.
1081 $convoids = [];
1082 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1083 $convoids[] = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1084 $user1context = context_user::instance($user1->id);
1085 $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
1086 foreach ($convoids as $convoid) {
1087 $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
1088 }
1089
1090 // Delete the second user.
1091 delete_user($user2);
1092
1093 // Retrieve the conversations.
1094 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1095
0847aa12 1096 // We should have both conversations, despite the other user being soft-deleted.
888a467a
AA
1097 // Consider first conversations is self-conversation.
1098 $this->assertCount(3, $conversations);
b8ff2c44
JD
1099
1100 // Confirm the conversation is from the non-deleted user.
1101 $conversation = reset($conversations);
eb5865da 1102 $this->assertEquals($convoids[1], $conversation->id);
b8ff2c44
JD
1103 }
1104
1105 /**
1106 * Test confirming that conversations can be marked as favourites.
1107 */
1108 public function test_set_favourite_conversation() {
1109 // Create some users.
1110 $user1 = self::getDataGenerator()->create_user();
1111 $user2 = self::getDataGenerator()->create_user();
1112 $user3 = self::getDataGenerator()->create_user();
1113
1114 // Send some messages back and forth, have some different conversations with different users.
1115 $time = 1;
1116 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1117 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1118 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1119 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1120
1121 $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1122 $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1123 $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1124 $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1125
1126 // Favourite the first conversation as user 1.
1127 $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
9e189a91 1128 $favourite = \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
b8ff2c44 1129
888a467a
AA
1130 // Verify we have two favourite conversations a user 1.
1131 // Consider first conversations is self-conversation.
1132 $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
b8ff2c44 1133
888a467a
AA
1134 // Verify we have only one favourite as user2, despite being a member in that conversation.
1135 // Consider first conversations is self-conversation.
1136 $this->assertCount(1, \core_message\api::get_conversations($user2->id, 0, 20, null, true));
b8ff2c44 1137
9e189a91
RW
1138 // Try to favourite the same conversation again should just return the existing favourite.
1139 $repeatresult = \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
1140 $this->assertEquals($favourite->id, $repeatresult->id);
b8ff2c44
JD
1141 }
1142
1143 /**
1144 * Test verifying that trying to mark a non-existent conversation as a favourite, results in an exception.
1145 */
1146 public function test_set_favourite_conversation_nonexistent_conversation() {
1147 // Create some users.
1148 $user1 = self::getDataGenerator()->create_user();
1149 // Try to favourite a non-existent conversation.
1150 $this->expectException(\moodle_exception::class);
1151 \core_message\api::set_favourite_conversation(0, $user1->id);
1152 }
1153
1154 /**
1155 * Test verifying that a conversation cannot be marked as favourite unless the user is a member of that conversation.
1156 */
1157 public function test_set_favourite_conversation_non_member() {
1158 // Create some users.
1159 $user1 = self::getDataGenerator()->create_user();
1160 $user2 = self::getDataGenerator()->create_user();
1161 $user3 = self::getDataGenerator()->create_user();
1162
1163 // Send some messages back and forth, have some different conversations with different users.
1164 $time = 1;
1165 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1166 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1167 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1168 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1169
1170 $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1171 $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1172 $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1173 $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1174
1175 // Try to favourite the first conversation as user 3, who is not a member.
1176 $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1177 $this->expectException(\moodle_exception::class);
1178 \core_message\api::set_favourite_conversation($conversationid1, $user3->id);
1179 }
1180
1181 /**
1182 * Test confirming that those conversations marked as favourites can be unfavourited.
1183 */
1184 public function test_unset_favourite_conversation() {
1185 // Create some users.
1186 $user1 = self::getDataGenerator()->create_user();
1187 $user2 = self::getDataGenerator()->create_user();
1188 $user3 = self::getDataGenerator()->create_user();
1189
1190 // Send some messages back and forth, have some different conversations with different users.
1191 $time = 1;
1192 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1193 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1194 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1195 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1196
1197 $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
1198 $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
1199 $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
1200 $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
1201
1202 // Favourite the first conversation as user 1 and the second as user 3.
1203 $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1204 $conversationid2 = \core_message\api::get_conversation_between_users([$user1->id, $user3->id]);
1205 \core_message\api::set_favourite_conversation($conversationid1, $user1->id);
1206 \core_message\api::set_favourite_conversation($conversationid2, $user3->id);
1207
888a467a
AA
1208 // Verify we have two favourite conversations for both user 1 and user 3, counting self conversations.
1209 $this->assertCount(2, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1210 $this->assertCount(2, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
b8ff2c44
JD
1211
1212 // Now unfavourite the conversation as user 1.
1213 \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1214
888a467a
AA
1215 // Verify we have two favourite conversations user 3 only, and one for user1, counting self conversations.
1216 $this->assertCount(2, \core_message\api::get_conversations($user3->id, 0, 20, null, true));
1217 $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
b8ff2c44
JD
1218
1219 // Try to favourite the same conversation again as user 1.
1220 $this->expectException(\moodle_exception::class);
1221 \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1222 }
1223
1224 /**
1225 * Test verifying that a valid conversation cannot be unset as a favourite if it's not marked as a favourite.
1226 */
1227 public function test_unset_favourite_conversation_not_favourite() {
1228 // Create some users.
1229 $user1 = self::getDataGenerator()->create_user();
1230 $user2 = self::getDataGenerator()->create_user();
1231
1232 // Send some messages back and forth, have some different conversations with different users.
1233 $time = 1;
1234 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1235 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1236 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1237 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1238
1239 // Now try to unfavourite the conversation as user 1.
1240 $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
1241 $this->expectException(\moodle_exception::class);
1242 \core_message\api::unset_favourite_conversation($conversationid1, $user1->id);
1243 }
1244
1245 /**
1246 * Test verifying that a non-existent conversation cannot be unset as a favourite.
1247 */
1248 public function test_unset_favourite_conversation_non_existent_conversation() {
1249 // Create some users.
1250 $user1 = self::getDataGenerator()->create_user();
1251
1252 // Now try to unfavourite the conversation as user 1.
1253 $this->expectException(\moodle_exception::class);
1254 \core_message\api::unset_favourite_conversation(0, $user1->id);
1255 }
1256
1f64514d 1257 /**
eb5865da 1258 * Helper to seed the database with initial state.
1f64514d 1259 */
eb5865da 1260 protected function create_conversation_test_data() {
1f64514d
MN
1261 // Create some users.
1262 $user1 = self::getDataGenerator()->create_user();
1263 $user2 = self::getDataGenerator()->create_user();
1264 $user3 = self::getDataGenerator()->create_user();
1265 $user4 = self::getDataGenerator()->create_user();
1266
eb5865da 1267 $time = 1;
1f64514d 1268
eb5865da
JD
1269 // Create some conversations. We want:
1270 // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message.
1271 // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message.
1272 // 3) At least one of each type (group, individual) of which user1 IS NOT a member.
1273 // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering).
1274 // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member.
1275
1276 // Individual conversation, user1 is a member, last message from other user.
1277 $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1278 [$user1->id, $user2->id]);
1279 testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time);
1280 testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1);
1281
1282 // Individual conversation, user1 is a member, last message from user1.
1283 $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1284 [$user1->id, $user3->id]);
1285 testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2);
1286 testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3);
1287
1288 // Individual conversation, user1 is not a member.
1289 $ic3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1290 [$user2->id, $user3->id]);
1291 testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4);
1292 testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5);
1293
1294 // Group conversation, user1 is not a member.
1295 $gc1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1296 [$user2->id, $user3->id, $user4->id], 'Project discussions');
1297 testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6);
1298 testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7);
1299
1300 // Group conversation, user1 is a member, last message from another user.
1301 $gc2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1302 [$user1->id, $user3->id, $user4->id], 'Group chat');
1303 testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8);
1304 testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9);
1305 testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10);
1306
1307 // Group conversation, user1 is a member, last message from user1.
1308 $gc3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1309 [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!');
1310 testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11);
1311 testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12);
1312 testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13);
1313
1314 // Empty group conversations (x2), user1 is a member.
1315 $gc4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1316 [$user1->id, $user2->id, $user3->id], 'Empty group');
1317 $gc5 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1318 [$user1->id, $user2->id, $user4->id], 'Another empty group');
1319
1320 // Empty group conversation, user1 is NOT a member.
1321 $gc6 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1322 [$user2->id, $user3->id, $user4->id], 'Empty group 3');
1323
1324 return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6];
1325 }
bb2924d0 1326
eb5865da
JD
1327 /**
1328 * Test verifying get_conversations when no limits, offsets, type filters or favourite restrictions are used.
1329 */
1330 public function test_get_conversations_no_restrictions() {
74fc14e5 1331 global $DB;
888a467a 1332
eb5865da 1333 $user1 = self::getDataGenerator()->create_user();
888a467a
AA
1334 // Self-conversation should exists.
1335 $this->assertCount(1, \core_message\api::get_conversations($user1->id));
1f64514d 1336
eb5865da
JD
1337 // Get a bunch of conversations, some group, some individual and in different states.
1338 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1339 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1340
1341 // Get all conversations for user1.
1342 $conversations = core_message\api::get_conversations($user1->id);
1343
888a467a
AA
1344 // Verify there are 2 individual conversation, 2 group conversations, 2 empty group conversations,
1345 // and a self-conversation.
eb5865da
JD
1346 // The conversations with the most recent messages should be listed first, followed by the empty
1347 // conversations, with the most recently created first.
888a467a 1348 $this->assertCount(7, $conversations);
eb5865da
JD
1349 $typecounts = array_count_values(array_column($conversations, 'type'));
1350 $this->assertEquals(2, $typecounts[1]);
1351 $this->assertEquals(4, $typecounts[2]);
888a467a 1352 $this->assertEquals(1, $typecounts[3]);
eb5865da 1353
888a467a 1354 // Those conversations having messages should be listed after self-conversation, ordered by most recent message time.
eb5865da
JD
1355 $this->assertEquals($gc3->id, $conversations[0]->id);
1356 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[0]->type);
888a467a 1357 $this->assertFalse($conversations[1]->isfavourite);
eb5865da
JD
1358 $this->assertCount(1, $conversations[0]->members);
1359 $this->assertEquals(4, $conversations[0]->membercount);
1360 $this->assertCount(1, $conversations[0]->messages);
74fc14e5
JD
1361 $message = $DB->get_record('messages', ['id' => $conversations[0]->messages[0]->id]);
1362 $expectedmessagetext = message_format_message_text($message);
1363 $this->assertEquals($expectedmessagetext, $conversations[0]->messages[0]->text);
eb5865da
JD
1364 $this->assertEquals($user1->id, $conversations[0]->messages[0]->useridfrom);
1365
1366 $this->assertEquals($gc2->id, $conversations[1]->id);
1367 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[1]->type);
1368 $this->assertFalse($conversations[1]->isfavourite);
1369 $this->assertCount(1, $conversations[1]->members);
1370 $this->assertEquals(3, $conversations[1]->membercount);
1371 $this->assertCount(1, $conversations[1]->messages);
74fc14e5
JD
1372 $message = $DB->get_record('messages', ['id' => $conversations[1]->messages[0]->id]);
1373 $expectedmessagetext = message_format_message_text($message);
1374 $this->assertEquals($expectedmessagetext, $conversations[1]->messages[0]->text);
eb5865da
JD
1375 $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1376
1377 $this->assertEquals($ic2->id, $conversations[2]->id);
1378 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[2]->type);
1379 $this->assertFalse($conversations[2]->isfavourite);
1380 $this->assertCount(1, $conversations[2]->members);
1381 $this->assertEquals($user3->id, $conversations[2]->members[$user3->id]->id);
1382 $this->assertEquals(2, $conversations[2]->membercount);
1383 $this->assertCount(1, $conversations[2]->messages);
74fc14e5
JD
1384 $message = $DB->get_record('messages', ['id' => $conversations[2]->messages[0]->id]);
1385 $expectedmessagetext = message_format_message_text($message);
1386 $this->assertEquals($expectedmessagetext, $conversations[2]->messages[0]->text);
eb5865da
JD
1387 $this->assertEquals($user1->id, $conversations[2]->messages[0]->useridfrom);
1388
1389 $this->assertEquals($ic1->id, $conversations[3]->id);
1390 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[3]->type);
1391 $this->assertFalse($conversations[3]->isfavourite);
1392 $this->assertCount(1, $conversations[3]->members);
1393 $this->assertEquals(2, $conversations[3]->membercount);
1394 $this->assertCount(1, $conversations[3]->messages);
74fc14e5
JD
1395 $message = $DB->get_record('messages', ['id' => $conversations[3]->messages[0]->id]);
1396 $expectedmessagetext = message_format_message_text($message);
1397 $this->assertEquals($expectedmessagetext, $conversations[3]->messages[0]->text);
eb5865da
JD
1398 $this->assertEquals($user2->id, $conversations[3]->messages[0]->useridfrom);
1399
1400 // Of the groups without messages, we expect to see the most recently created first.
1401 $this->assertEquals($gc5->id, $conversations[4]->id);
1402 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[4]->type);
1403 $this->assertFalse($conversations[4]->isfavourite);
1404 $this->assertCount(0, $conversations[4]->members); // No members returned, because no recent messages exist.
1405 $this->assertEquals(3, $conversations[4]->membercount);
1406 $this->assertEmpty($conversations[4]->messages);
1407
1408 $this->assertEquals($gc4->id, $conversations[5]->id);
1409 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[5]->type);
1410 $this->assertFalse($conversations[5]->isfavourite);
1411 $this->assertCount(0, $conversations[5]->members);
1412 $this->assertEquals(3, $conversations[5]->membercount);
1413 $this->assertEmpty($conversations[5]->messages);
1414
1415 // Verify format of the return structure.
1416 foreach ($conversations as $conv) {
1417 $this->assertObjectHasAttribute('id', $conv);
1418 $this->assertObjectHasAttribute('name', $conv);
1419 $this->assertObjectHasAttribute('subname', $conv);
003cdcce 1420 $this->assertObjectHasAttribute('imageurl', $conv);
eb5865da
JD
1421 $this->assertObjectHasAttribute('type', $conv);
1422 $this->assertObjectHasAttribute('isfavourite', $conv);
1423 $this->assertObjectHasAttribute('membercount', $conv);
1424 $this->assertObjectHasAttribute('isread', $conv);
1425 $this->assertObjectHasAttribute('unreadcount', $conv);
1426 $this->assertObjectHasAttribute('members', $conv);
1427 foreach ($conv->members as $member) {
1428 $this->assertObjectHasAttribute('id', $member);
1429 $this->assertObjectHasAttribute('fullname', $member);
1430 $this->assertObjectHasAttribute('profileimageurl', $member);
1431 $this->assertObjectHasAttribute('profileimageurlsmall', $member);
1432 $this->assertObjectHasAttribute('isonline', $member);
1433 $this->assertObjectHasAttribute('showonlinestatus', $member);
1434 $this->assertObjectHasAttribute('isblocked', $member);
1435 $this->assertObjectHasAttribute('iscontact', $member);
d15c1e77 1436 $this->assertObjectHasAttribute('isdeleted', $member);
cef1d977
MN
1437 $this->assertObjectHasAttribute('canmessage', $member);
1438 $this->assertObjectHasAttribute('requirescontact', $member);
1439 $this->assertObjectHasAttribute('contactrequests', $member);
eb5865da
JD
1440 }
1441 $this->assertObjectHasAttribute('messages', $conv);
1442 foreach ($conv->messages as $message) {
1443 $this->assertObjectHasAttribute('id', $message);
1444 $this->assertObjectHasAttribute('useridfrom', $message);
1445 $this->assertObjectHasAttribute('text', $message);
1446 $this->assertObjectHasAttribute('timecreated', $message);
1447 }
1448 }
1449 }
1f64514d 1450
74fc14e5
JD
1451 /**
1452 * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately.
1453 */
1454 public function test_get_conversations_message_format() {
1455 global $DB;
1456 // Create some users.
1457 $user1 = self::getDataGenerator()->create_user();
1458 $user2 = self::getDataGenerator()->create_user();
1459
1460 // Create conversation.
1461 $conversation = \core_message\api::create_conversation(
1462 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1463 [$user1->id, $user2->id]
1464 );
1465
1466 // Send some messages back and forth.
1467 $time = 1;
1468 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1);
1469 $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2);
1470
1471 // Verify the format of the html message.
1472 $message = $DB->get_record('messages', ['id' => $mid]);
1473 $expectedmessagetext = message_format_message_text($message);
1474 $conversations = \core_message\api::get_conversations($user1->id);
1475 $messages = $conversations[0]->messages;
1476 $this->assertEquals($expectedmessagetext, $messages[0]->text);
1477 }
1478
00c59245
MN
1479 /**
1480 * Test verifying get_conversations identifies if a conversation is muted or not.
1481 */
1482 public function test_get_conversations_some_muted() {
1483 // Create some users.
1484 $user1 = self::getDataGenerator()->create_user();
1485 $user2 = self::getDataGenerator()->create_user();
1486 $user3 = self::getDataGenerator()->create_user();
1487
1488 $conversation1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1489 [$user1->id, $user2->id]);
1490 testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'Message 1');
1491 testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'Message 2');
1492 \core_message\api::mute_conversation($user1->id, $conversation1->id);
1493
1494 $conversation2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1495 [$user1->id, $user3->id]);
1496 testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Message 1');
1497 testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Message 2');
1498
1499 $conversation3 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1500 [$user1->id, $user2->id]);
1501 \core_message\api::mute_conversation($user1->id, $conversation3->id);
1502
1503 $conversation4 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1504 [$user1->id, $user3->id]);
1505
1506 $conversations = \core_message\api::get_conversations($user1->id);
1507
1508 usort($conversations, function($first, $second){
1509 return $first->id > $second->id;
1510 });
1511
888a467a
AA
1512 // Consider first conversations is self-conversation.
1513 $selfconversation = array_shift($conversations);
00c59245
MN
1514 $conv1 = array_shift($conversations);
1515 $conv2 = array_shift($conversations);
1516 $conv3 = array_shift($conversations);
1517 $conv4 = array_shift($conversations);
1518
1519 $this->assertTrue($conv1->ismuted);
1520 $this->assertFalse($conv2->ismuted);
1521 $this->assertTrue($conv3->ismuted);
1522 $this->assertFalse($conv4->ismuted);
1523 }
1524
eb5865da
JD
1525 /**
1526 * Tests retrieving conversations with a limit and offset to ensure pagination works correctly.
1527 */
1528 public function test_get_conversations_limit_offset() {
1529 // Get a bunch of conversations, some group, some individual and in different states.
1530 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1531 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1f64514d 1532
eb5865da
JD
1533 // Get all conversations for user1, limited to 1 result.
1534 $conversations = core_message\api::get_conversations($user1->id, 0, 1);
1f64514d 1535
eb5865da
JD
1536 // Verify the first conversation.
1537 $this->assertCount(1, $conversations);
1538 $conversation = array_shift($conversations);
1539 $this->assertEquals($conversation->id, $gc3->id);
1f64514d 1540
eb5865da
JD
1541 // Verify the next conversation.
1542 $conversations = \core_message\api::get_conversations($user1->id, 1, 1);
1543 $this->assertCount(1, $conversations);
1544 $this->assertEquals($gc2->id, $conversations[0]->id);
1f64514d 1545
eb5865da
JD
1546 // Verify the next conversation.
1547 $conversations = \core_message\api::get_conversations($user1->id, 2, 1);
1548 $this->assertCount(1, $conversations);
1549 $this->assertEquals($ic2->id, $conversations[0]->id);
1f64514d 1550
eb5865da
JD
1551 // Skip one and get both empty conversations.
1552 $conversations = \core_message\api::get_conversations($user1->id, 4, 2);
1553 $this->assertCount(2, $conversations);
1554 $this->assertEquals($gc5->id, $conversations[0]->id);
1555 $this->assertEmpty($conversations[0]->messages);
1556 $this->assertEquals($gc4->id, $conversations[1]->id);
1557 $this->assertEmpty($conversations[1]->messages);
1f64514d 1558
eb5865da
JD
1559 // Ask for an offset that doesn't exist and verify no conversations are returned.
1560 $conversations = \core_message\api::get_conversations($user1->id, 10, 1);
1561 $this->assertCount(0, $conversations);
1f64514d
MN
1562 }
1563
4d146f1a 1564 /**
eb5865da 1565 * Test verifying the type filtering behaviour of the
4d146f1a 1566 */
eb5865da
JD
1567 public function test_get_conversations_type_filter() {
1568 // Get a bunch of conversations, some group, some individual and in different states.
1569 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1570 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1571
1572 // Verify we can ask for only individual conversations.
1573 $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1574 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1575 $this->assertCount(2, $conversations);
4d146f1a 1576
eb5865da
JD
1577 // Verify we can ask for only group conversations.
1578 $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1579 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP);
1580 $this->assertCount(4, $conversations);
4d146f1a 1581
eb5865da
JD
1582 // Verify an exception is thrown if an unrecognized type is specified.
1583 $this->expectException(\moodle_exception::class);
1584 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, 0);
1585 }
4d146f1a 1586
425f5adc 1587 /**
734b198f 1588 * Tests retrieving conversations when a 'self' conversation exists.
425f5adc 1589 */
734b198f 1590 public function test_get_conversations_self_conversations() {
425f5adc
JD
1591 global $DB;
1592
734b198f 1593 // Create a conversation between one user and themself.
425f5adc 1594 $user1 = self::getDataGenerator()->create_user();
734b198f
SA
1595 $user2 = self::getDataGenerator()->create_user();
1596 $user3 = self::getDataGenerator()->create_user();
1597 $user4 = self::getDataGenerator()->create_user();
1598
1599 // Create some individual conversations.
1600 $ic1 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1601 [$user1->id, $user2->id]);
1602 $ic2 = \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1603 [$user1->id, $user3->id]);
1604 testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message from user1 to user2');
1605
888a467a
AA
1606 // Get some self-conversations.
1607 $sc1 = \core_message\api::get_self_conversation($user1->id);
1608 $sc4 = \core_message\api::get_self_conversation($user4->id);
734b198f 1609 testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Test message to self 1!');
425f5adc
JD
1610
1611 // Verify we are in a 'self' conversation state.
734b198f
SA
1612 $members = $DB->get_records('message_conversation_members', ['conversationid' => $sc1->id]);
1613 $this->assertCount(1, $members);
425f5adc
JD
1614 $member = array_pop($members);
1615 $this->assertEquals($user1->id, $member->userid);
1616
734b198f
SA
1617 // Verify the self-conversations are returned by the method.
1618 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF);
1619 $this->assertCount(1, $conversations);
1620 $conversation = array_pop($conversations);
1621 $this->assertEquals($conversation->id, $sc1->id);
1622
1623 $conversations = \core_message\api::get_conversations($user4->id);
1624 // The self-conversation.
1625 $this->assertCount(1, $conversations);
1626
1627 // Get only private conversations for user1 (empty conversations, like $ic2, are not returned).
1628 $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1629 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1630 $this->assertCount(1, $conversations);
1631
1632 // Merge self with private conversations for user1.
1633 $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1634 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
1635 $this->assertCount(2, $conversations);
1636
1637 // Get only private conversations for user2.
1638 $conversations = \core_message\api::get_conversations($user2->id, 0, 20,
1639 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1640 $this->assertCount(1, $conversations);
1641
888a467a 1642 // Merge self with private conversations for user2.
734b198f
SA
1643 $conversations = \core_message\api::get_conversations($user2->id, 0, 20,
1644 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
888a467a 1645 $this->assertCount(2, $conversations);
425f5adc
JD
1646 }
1647
eb5865da
JD
1648 /**
1649 * Tests retrieving conversations when a conversation contains a deleted user.
1650 */
1651 public function test_get_conversations_with_deleted_user() {
1652 // Get a bunch of conversations, some group, some individual and in different states.
1653 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1654 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
4d146f1a 1655
eb5865da 1656 // Delete the second user and retrieve the conversations.
0847aa12
JD
1657 // We should have 6 still, as conversations with soft-deleted users are still returned.
1658 // Group conversations are also present, albeit with less members.
eb5865da 1659 delete_user($user2);
52beee65
MN
1660 // This is to confirm an exception is not thrown when a user AND the user context is deleted.
1661 // We no longer delete the user context, but historically we did.
1662 context_helper::delete_instance(CONTEXT_USER, $user2->id);
eb5865da 1663 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1664 // Consider there's a self-conversation (the last one).
1665 $this->assertCount(7, $conversations);
eb5865da
JD
1666 $this->assertEquals($gc3->id, $conversations[0]->id);
1667 $this->assertcount(1, $conversations[0]->members);
1668 $this->assertEquals($gc2->id, $conversations[1]->id);
1669 $this->assertcount(1, $conversations[1]->members);
1670 $this->assertEquals($ic2->id, $conversations[2]->id);
0847aa12
JD
1671 $this->assertEquals($ic1->id, $conversations[3]->id);
1672 $this->assertEquals($gc5->id, $conversations[4]->id);
1673 $this->assertEquals($gc4->id, $conversations[5]->id);
eb5865da
JD
1674
1675 // Delete a user from a group conversation where that user had sent the most recent message.
1676 // This user will still be present in the members array, as will the message in the messages array.
1677 delete_user($user4);
1678 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1679
1680 // Consider there's a self-conversation (the last one).
1681 $this->assertCount(7, $conversations);
eb5865da
JD
1682 $this->assertEquals($gc2->id, $conversations[1]->id);
1683 $this->assertcount(1, $conversations[1]->members);
1684 $this->assertEquals($user4->id, $conversations[1]->members[$user4->id]->id);
1685 $this->assertcount(1, $conversations[1]->messages);
1686 $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1687
1688 // Delete the third user and retrieve the conversations.
0847aa12
JD
1689 // We should have 6 still, as conversations with soft-deleted users are still returned.
1690 // Group conversations are also present, albeit with less members.
eb5865da
JD
1691 delete_user($user3);
1692 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1693 // Consider there's a self-conversation (the last one).
1694 $this->assertCount(7, $conversations);
eb5865da
JD
1695 $this->assertEquals($gc3->id, $conversations[0]->id);
1696 $this->assertcount(1, $conversations[0]->members);
1697 $this->assertEquals($gc2->id, $conversations[1]->id);
1698 $this->assertcount(1, $conversations[1]->members);
0847aa12
JD
1699 $this->assertEquals($ic2->id, $conversations[2]->id);
1700 $this->assertEquals($ic1->id, $conversations[3]->id);
1701 $this->assertEquals($gc5->id, $conversations[4]->id);
1702 $this->assertEquals($gc4->id, $conversations[5]->id);
eb5865da 1703 }
4d146f1a 1704
aa748351
JD
1705 /**
1706 * Test confirming the behaviour of get_conversations() when users delete all messages.
1707 */
1708 public function test_get_conversations_deleted_messages() {
1709 // Get a bunch of conversations, some group, some individual and in different states.
1710 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1711 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1712
1713 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1714 // Consider first conversations is self-conversation.
1715 $this->assertCount(7, $conversations);
aa748351
JD
1716
1717 // Delete all messages from a group conversation the user is in - it should be returned.
1718 $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $gc2->id));
1719 $convmessages = \core_message\api::get_conversation_messages($user1->id, $gc2->id);
1720 $messages = $convmessages['messages'];
1721 foreach ($messages as $message) {
1722 \core_message\api::delete_message($user1->id, $message->id);
1723 }
1724 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1725 // Consider first conversations is self-conversation.
1726 $this->assertCount(7, $conversations);
aa748351
JD
1727 $this->assertContains($gc2->id, array_column($conversations, 'id'));
1728
1729 // Delete all messages from an individual conversation the user is in - it should not be returned.
1730 $this->assertTrue(\core_message\api::is_user_in_conversation($user1->id, $ic1->id));
1731 $convmessages = \core_message\api::get_conversation_messages($user1->id, $ic1->id);
1732 $messages = $convmessages['messages'];
1733 foreach ($messages as $message) {
1734 \core_message\api::delete_message($user1->id, $message->id);
1735 }
1736 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1737 // Consider first conversations is self-conversation.
1738 $this->assertCount(6, $conversations);
aa748351
JD
1739 $this->assertNotContains($ic1->id, array_column($conversations, 'id'));
1740 }
1741
e926b4d0
AN
1742 /**
1743 * Test verifying the behaviour of get_conversations() when fetching favourite conversations with only a single
1744 * favourite.
1745 */
1746 public function test_get_conversations_favourite_conversations_single() {
1747 // Get a bunch of conversations, some group, some individual and in different states.
1748 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1749 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1750
1751 // Mark a single conversation as favourites.
1752 \core_message\api::set_favourite_conversation($ic2->id, $user1->id);
1753
1754 // Get the conversation, first with no restrictions, confirming the favourite status of the conversations.
1755 $conversations = \core_message\api::get_conversations($user1->id);
888a467a
AA
1756 // Consider there is a self-conversation.
1757 $selfconversation = \core_message\api::get_self_conversation($user1->id);
1758 $this->assertCount(7, $conversations);
e926b4d0 1759 foreach ($conversations as $conv) {
888a467a 1760 if (in_array($conv->id, [$ic2->id, $selfconversation->id])) {
e926b4d0
AN
1761 $this->assertTrue($conv->isfavourite);
1762 } else {
1763 $this->assertFalse($conv->isfavourite);
1764 }
1765 }
1766
888a467a 1767 // Now, get ONLY favourite conversations (including self-conversation).
e926b4d0 1768 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
888a467a 1769 $this->assertCount(2, $conversations);
e926b4d0 1770 foreach ($conversations as $conv) {
e4987f0f
AA
1771 if ($conv->type != \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF) {
1772 $this->assertTrue($conv->isfavourite);
1773 $this->assertEquals(\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conv->type);
1774 $this->assertEquals($ic2->id, $conv->id);
1775 }
e926b4d0
AN
1776 }
1777
1778 // Now, try ONLY favourites of type 'group'.
1779 $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1780 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1781 $this->assertEmpty($conversations);
1782
1783 // And NO favourite conversations.
1784 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
1785 $this->assertCount(5, $conversations);
1786 foreach ($conversations as $conv) {
1787 $this->assertFalse($conv->isfavourite);
1788 $this->assertNotEquals($ic2, $conv->id);
1789 }
1790 }
1791
eb5865da
JD
1792 /**
1793 * Test verifying the behaviour of get_conversations() when fetching favourite conversations.
1794 */
1795 public function test_get_conversations_favourite_conversations() {
1796 // Get a bunch of conversations, some group, some individual and in different states.
1797 list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1798 $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
4d146f1a 1799
888a467a
AA
1800 // Try to get ONLY favourite conversations, when only self-conversation exist.
1801 $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true));
1802
1803 // Unstar self-conversation.
1804 $selfconversation = \core_message\api::get_self_conversation($user1->id);
1805 \core_message\api::unset_favourite_conversation($selfconversation->id, $user1->id);
1806
eb5865da
JD
1807 // Try to get ONLY favourite conversations, when no favourites exist.
1808 $this->assertEquals([], \core_message\api::get_conversations($user1->id, 0, 20, null, true));
4d146f1a 1809
eb5865da 1810 // Try to get NO favourite conversations, when no favourites exist.
888a467a 1811 $this->assertCount(7, \core_message\api::get_conversations($user1->id, 0, 20, null, false));
4d146f1a 1812
eb5865da
JD
1813 // Mark a few conversations as favourites.
1814 \core_message\api::set_favourite_conversation($ic1->id, $user1->id);
1815 \core_message\api::set_favourite_conversation($gc2->id, $user1->id);
1816 \core_message\api::set_favourite_conversation($gc5->id, $user1->id);
e926b4d0 1817 $favouriteids = [$ic1->id, $gc2->id, $gc5->id];
4d146f1a 1818
eb5865da
JD
1819 // Get the conversations, first with no restrictions, confirming the favourite status of the conversations.
1820 $conversations = \core_message\api::get_conversations($user1->id);
888a467a 1821 $this->assertCount(7, $conversations);
eb5865da 1822 foreach ($conversations as $conv) {
e926b4d0 1823 if (in_array($conv->id, $favouriteids)) {
eb5865da 1824 $this->assertTrue($conv->isfavourite);
e926b4d0
AN
1825 } else {
1826 $this->assertFalse($conv->isfavourite);
eb5865da
JD
1827 }
1828 }
4d146f1a 1829
eb5865da
JD
1830 // Now, get ONLY favourite conversations.
1831 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, true);
1832 $this->assertCount(3, $conversations);
1833 foreach ($conversations as $conv) {
1834 $this->assertTrue($conv->isfavourite);
e926b4d0 1835 $this->assertNotFalse(array_search($conv->id, $favouriteids));
eb5865da 1836 }
4d146f1a 1837
eb5865da
JD
1838 // Now, try ONLY favourites of type 'group'.
1839 $conversations = \core_message\api::get_conversations($user1->id, 0, 20,
1840 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1841 $this->assertCount(2, $conversations);
1842 foreach ($conversations as $conv) {
1843 $this->assertTrue($conv->isfavourite);
e926b4d0 1844 $this->assertNotFalse(array_search($conv->id, [$gc2->id, $gc5->id]));
eb5865da 1845 }
4d146f1a 1846
eb5865da
JD
1847 // And NO favourite conversations.
1848 $conversations = \core_message\api::get_conversations($user1->id, 0, 20, null, false);
888a467a 1849 $this->assertCount(4, $conversations);
eb5865da
JD
1850 foreach ($conversations as $conv) {
1851 $this->assertFalse($conv->isfavourite);
e926b4d0 1852 $this->assertFalse(array_search($conv->id, $favouriteids));
eb5865da 1853 }
4d146f1a
RW
1854 }
1855
cef1d977
MN
1856 /**
1857 * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this
1858 * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want
1859 * to confirm this happens.
1860 */
1861 public function test_get_conversations_user_in_group_and_individual_chat() {
1862 $this->resetAfterTest();
1863
1864 $user1 = self::getDataGenerator()->create_user();
1865 $user2 = self::getDataGenerator()->create_user();
1866 $user3 = self::getDataGenerator()->create_user();
1867
1868 $conversation = \core_message\api::create_conversation(
1869 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1870 [
1871 $user1->id,
1872 $user2->id
1873 ],
1874 'Individual conversation'
1875 );
1876
1877 testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1878
1879 $conversation = \core_message\api::create_conversation(
1880 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
1881 [
1882 $user1->id,
1883 $user2->id,
1884 ],
1885 'Group conversation'
1886 );
1887
1888 testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1889
1890 \core_message\api::create_contact_request($user1->id, $user2->id);
1891 \core_message\api::create_contact_request($user1->id, $user3->id);
1892
1893 $conversations = \core_message\api::get_conversations($user2->id);
1894
1895 $groupconversation = array_shift($conversations);
1896 $individualconversation = array_shift($conversations);
1897
1898 $this->assertEquals('Group conversation', $groupconversation->name);
1899 $this->assertEquals('Individual conversation', $individualconversation->name);
1900
1901 $this->assertCount(1, $groupconversation->members);
1902 $this->assertCount(1, $individualconversation->members);
1903
1904 $groupmember = reset($groupconversation->members);
1905 $this->assertNull($groupmember->requirescontact);
1906 $this->assertNull($groupmember->canmessage);
1907 $this->assertEmpty($groupmember->contactrequests);
1908
1909 $individualmember = reset($individualconversation->members);
1910 $this->assertNotNull($individualmember->requirescontact);
1911 $this->assertNotNull($individualmember->canmessage);
1912 $this->assertNotEmpty($individualmember->contactrequests);
1913 }
1914
f512355b 1915 /**
eb5865da 1916 * Test verifying that group linked conversations are returned and contain a subname matching the course name.
f512355b 1917 */
eb5865da 1918 public function test_get_conversations_group_linked() {
18550c0a 1919 global $CFG, $DB;
003cdcce 1920
f512355b
MN
1921 // Create some users.
1922 $user1 = self::getDataGenerator()->create_user();
1923 $user2 = self::getDataGenerator()->create_user();
1924 $user3 = self::getDataGenerator()->create_user();
1925
eb5865da 1926 $course1 = $this->getDataGenerator()->create_course();
f512355b 1927
9cef5491 1928 // Create a group with a linked conversation and a valid image.
eb5865da
JD
1929 $this->setAdminUser();
1930 $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1931 $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1932 $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
003cdcce
JD
1933 $group1 = $this->getDataGenerator()->create_group([
1934 'courseid' => $course1->id,
1935 'enablemessaging' => 1,
1936 'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
1937 ]);
f512355b 1938
eb5865da
JD
1939 // Add users to group1.
1940 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1941 $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
f512355b 1942
9cef5491 1943 // Verify the group with the image works as expected.
f512355b 1944 $conversations = \core_message\api::get_conversations($user1->id);
003cdcce 1945 $this->assertEquals(2, $conversations[0]->membercount);
eb5865da 1946 $this->assertEquals($course1->shortname, $conversations[0]->subname);
003cdcce
JD
1947 $groupimageurl = get_group_picture_url($group1, $group1->courseid, true);
1948 $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
9cef5491
JD
1949
1950 // Create a group with a linked conversation and without any image.
1951 $group2 = $this->getDataGenerator()->create_group([
1952 'courseid' => $course1->id,
1953 'enablemessaging' => 1,
1954 ]);
1955
1956 // Add users to group2.
1957 $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1958 $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id));
1959
1960 // Verify the group without any image works as expected too.
1961 $conversations = \core_message\api::get_conversations($user3->id);
888a467a 1962 // Consider first conversations is self-conversation.
9cef5491
JD
1963 $this->assertEquals(2, $conversations[0]->membercount);
1964 $this->assertEquals($course1->shortname, $conversations[0]->subname);
442f1425 1965 $this->assertEquals('https://www.example.com/moodle/theme/image.php/_s/boost/core/1/g/g1', $conversations[0]->imageurl);
18550c0a
JD
1966
1967 // Now, disable the conversation linked to the group and verify it's no longer returned.
1968 $DB->set_field('message_conversations', 'enabled', 0, ['id' => $conversations[0]->id]);
1969 $conversations = \core_message\api::get_conversations($user3->id);
888a467a 1970 $this->assertCount(1, $conversations);
f512355b
MN
1971 }
1972
e12d9f49
RW
1973 /**
1974 * The data provider for get_conversations_mixed.
1975 *
1976 * This provides sets of data to for testing.
1977 * @return array
1978 */
1979 public function get_conversations_mixed_provider() {
1980 return array(
4d146f1a
RW
1981 'Test that conversations with messages contacts is correctly ordered.' => array(
1982 'users' => array(
1983 'user1',
1984 'user2',
1985 'user3',
1986 ),
1987 'contacts' => array(
1988 ),
1989 'messages' => array(
1990 array(
1991 'from' => 'user1',
1992 'to' => 'user2',
1993 'state' => 'unread',
1994 'subject' => 'S1',
1995 ),
1996 array(
1997 'from' => 'user2',
1998 'to' => 'user1',
1999 'state' => 'unread',
2000 'subject' => 'S2',
2001 ),
2002 array(
2003 'from' => 'user1',
2004 'to' => 'user2',
2005 'state' => 'unread',
2006 'timecreated' => 0,
2007 'subject' => 'S3',
2008 ),
2009 array(
2010 'from' => 'user1',
2011 'to' => 'user3',
2012 'state' => 'read',
2013 'timemodifier' => 1,
2014 'subject' => 'S4',
2015 ),
2016 array(
2017 'from' => 'user3',
2018 'to' => 'user1',
2019 'state' => 'read',
2020 'timemodifier' => 1,
2021 'subject' => 'S5',
2022 ),
2023 array(
2024 'from' => 'user1',
2025 'to' => 'user3',
2026 'state' => 'read',
2027 'timecreated' => 0,
2028 'subject' => 'S6',
2029 ),
2030 ),
2031 'expectations' => array(
2032 'user1' => array(
2033 // User1 has conversed most recently with user3. The most recent message is M5.
2034 array(
2035 'messageposition' => 0,
2036 'with' => 'user3',
74fc14e5 2037 'subject' => '<p>S5</p>',
e12d9f49 2038 'unreadcount' => 0,
4d146f1a
RW
2039 ),
2040 // User1 has also conversed with user2. The most recent message is S2.
2041 array(
2042 'messageposition' => 1,
2043 'with' => 'user2',
74fc14e5 2044 'subject' => '<p>S2</p>',
e12d9f49 2045 'unreadcount' => 1,
4d146f1a
RW
2046 ),
2047 ),
2048 'user2' => array(
2049 // User2 has only conversed with user1. Their most recent shared message was S2.
2050 array(
2051 'messageposition' => 0,
2052 'with' => 'user1',
74fc14e5 2053 'subject' => '<p>S2</p>',
e12d9f49 2054 'unreadcount' => 2,
4d146f1a
RW
2055 ),
2056 ),
2057 'user3' => array(
2058 // User3 has only conversed with user1. Their most recent shared message was S5.
2059 array(
2060 'messageposition' => 0,
2061 'with' => 'user1',
74fc14e5 2062 'subject' => '<p>S5</p>',
e12d9f49 2063 'unreadcount' => 0,
4d146f1a
RW
2064 ),
2065 ),
2066 ),
2067 ),
4d146f1a
RW
2068 'Test conversations with a single user, where some messages are read and some are not.' => array(
2069 'users' => array(
2070 'user1',
2071 'user2',
2072 ),
2073 'contacts' => array(
2074 ),
2075 'messages' => array(
2076 array(
2077 'from' => 'user1',
2078 'to' => 'user2',
2079 'state' => 'read',
2080 'subject' => 'S1',
2081 ),
2082 array(
2083 'from' => 'user2',
2084 'to' => 'user1',
2085 'state' => 'read',
2086 'subject' => 'S2',
2087 ),
2088 array(
2089 'from' => 'user1',
2090 'to' => 'user2',
2091 'state' => 'unread',
2092 'timemodifier' => 1,
2093 'subject' => 'S3',
2094 ),
2095 array(
2096 'from' => 'user1',
2097 'to' => 'user2',
2098 'state' => 'unread',
2099 'timemodifier' => 1,
2100 'subject' => 'S4',
2101 ),
2102 ),
2103 'expectations' => array(
2104 // The most recent message between user1 and user2 was S4.
2105 'user1' => array(
2106 array(
2107 'messageposition' => 0,
2108 'with' => 'user2',
74fc14e5 2109 'subject' => '<p>S4</p>',
e12d9f49 2110 'unreadcount' => 0,
4d146f1a
RW
2111 ),
2112 ),
2113 'user2' => array(
2114 // The most recent message between user1 and user2 was S4.
2115 array(
2116 'messageposition' => 0,
2117 'with' => 'user1',
74fc14e5 2118 'subject' => '<p>S4</p>',
e12d9f49 2119 'unreadcount' => 2,
4d146f1a
RW
2120 ),
2121 ),
2122 ),
2123 ),
2124 'Test conversations with a single user, where some messages are read and some are not, and messages ' .
2125 'are out of order' => array(
2126 // This can happen through a combination of factors including multi-master DB replication with messages
2127 // read somehow (e.g. API).
2128 'users' => array(
2129 'user1',
2130 'user2',
2131 ),
2132 'contacts' => array(
2133 ),
2134 'messages' => array(
2135 array(
2136 'from' => 'user1',
2137 'to' => 'user2',
2138 'state' => 'read',
2139 'subject' => 'S1',
2140 'timemodifier' => 1,
2141 ),
2142 array(
2143 'from' => 'user2',
2144 'to' => 'user1',
2145 'state' => 'read',
2146 'subject' => 'S2',
2147 'timemodifier' => 2,
2148 ),
2149 array(
2150 'from' => 'user1',
2151 'to' => 'user2',
2152 'state' => 'unread',
2153 'subject' => 'S3',
2154 ),
2155 array(
2156 'from' => 'user1',
2157 'to' => 'user2',
2158 'state' => 'unread',
2159 'subject' => 'S4',
2160 ),
2161 ),
2162 'expectations' => array(
2163 // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
2164 'user1' => array(
2165 array(
2166 'messageposition' => 0,
2167 'with' => 'user2',
74fc14e5 2168 'subject' => '<p>S2</p>',
e12d9f49 2169 'unreadcount' => 0,
4d146f1a
RW
2170 ),
2171 ),
2172 'user2' => array(
2173 array(
2174 'messageposition' => 0,
2175 'with' => 'user1',
74fc14e5 2176 'subject' => '<p>S2</p>',
e12d9f49
RW
2177 'unreadcount' => 2
2178 ),
2179 ),
2180 ),
2181 ),
2182 'Test unread message count is correct for both users' => array(
2183 'users' => array(
2184 'user1',
2185 'user2',
2186 ),
2187 'contacts' => array(
2188 ),
2189 'messages' => array(
2190 array(
2191 'from' => 'user1',
2192 'to' => 'user2',
2193 'state' => 'read',
2194 'subject' => 'S1',
2195 'timemodifier' => 1,
2196 ),
2197 array(
2198 'from' => 'user2',
2199 'to' => 'user1',
2200 'state' => 'read',
2201 'subject' => 'S2',
2202 'timemodifier' => 2,
2203 ),
2204 array(
2205 'from' => 'user1',
2206 'to' => 'user2',
2207 'state' => 'read',
2208 'subject' => 'S3',
2209 'timemodifier' => 3,
2210 ),
2211 array(
2212 'from' => 'user1',
2213 'to' => 'user2',
2214 'state' => 'read',
2215 'subject' => 'S4',
2216 'timemodifier' => 4,
2217 ),
2218 array(
2219 'from' => 'user1',
2220 'to' => 'user2',
2221 'state' => 'unread',
2222 'subject' => 'S5',
2223 'timemodifier' => 5,
2224 ),
2225 array(
2226 'from' => 'user2',
2227 'to' => 'user1',
2228 'state' => 'unread',
2229 'subject' => 'S6',
2230 'timemodifier' => 6,
2231 ),
2232 array(
2233 'from' => 'user1',
2234 'to' => 'user2',
2235 'state' => 'unread',
2236 'subject' => 'S7',
2237 'timemodifier' => 7,
2238 ),
2239 array(
2240 'from' => 'user1',
2241 'to' => 'user2',
2242 'state' => 'unread',
2243 'subject' => 'S8',
2244 'timemodifier' => 8,
2245 ),
2246 ),
2247 'expectations' => array(
2248 // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
2249 'user1' => array(
2250 array(
2251 'messageposition' => 0,
2252 'with' => 'user2',
74fc14e5 2253 'subject' => '<p>S8</p>',
e12d9f49
RW
2254 'unreadcount' => 1,
2255 ),
2256 ),
2257 'user2' => array(
2258 array(
2259 'messageposition' => 0,
2260 'with' => 'user1',
74fc14e5 2261 'subject' => '<p>S8</p>',
e12d9f49 2262 'unreadcount' => 3,
4d146f1a
RW
2263 ),
2264 ),
2265 ),
2266 ),
2267 );
2268 }
2269
510ede56
JD
2270 /**
2271 * Test that creation can't create the same conversation twice for 1:1 conversations.
2272 */
2273 public function test_create_conversation_duplicate_conversations() {
2274 global $DB;
2275 $user1 = $this::getDataGenerator()->create_user();
2276
2277 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2278 \core_message\api::create_conversation(\core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2279
2280 $convhash = \core_message\helper::get_conversation_hash([$user1->id]);
2281 $countconversations = $DB->count_records('message_conversations', ['convhash' => $convhash]);
2282 $this->assertEquals(1, $countconversations);
2283 $this->assertNotEmpty($conversation = \core_message\api::get_self_conversation($user1->id));
2284 }
2285
4d146f1a
RW
2286 /**
2287 * Test get_conversations with a mixture of messages.
2288 *
2289 * @dataProvider get_conversations_mixed_provider
2290 * @param array $usersdata The list of users to create for this test.
2291 * @param array $messagesdata The list of messages to create.
2292 * @param array $expectations The list of expected outcomes.
2293 */
2294 public function test_get_conversations_mixed($usersdata, $contacts, $messagesdata, $expectations) {
2295 global $DB;
2296
2297 // Create all of the users.
2298 $users = array();
2299 foreach ($usersdata as $username) {
2300 $users[$username] = $this->getDataGenerator()->create_user(array('username' => $username));
2301 }
2302
2303 foreach ($contacts as $username => $contact) {
2304 foreach ($contact as $contactname => $blocked) {
2305 $record = new stdClass();
2306 $record->userid = $users[$username]->id;
2307 $record->contactid = $users[$contactname]->id;
2308 $record->blocked = $blocked;
2309 $record->id = $DB->insert_record('message_contacts', $record);
2310 }
2311 }
2312
2313 $defaulttimecreated = time();
2314 foreach ($messagesdata as $messagedata) {
2315 $from = $users[$messagedata['from']];
2316 $to = $users[$messagedata['to']];
2317 $subject = $messagedata['subject'];
2318
2319 if (isset($messagedata['state']) && $messagedata['state'] == 'unread') {
4d146f1a
RW
2320 $messageid = $this->send_fake_message($from, $to, $subject);
2321 } else {
2322 // If there is no state, or the state is not 'unread', assume the message is read.
4d146f1a
RW
2323 $messageid = message_post_message($from, $to, $subject, FORMAT_PLAIN);
2324 }
2325
2326 $updatemessage = new stdClass();
2327 $updatemessage->id = $messageid;
2328 if (isset($messagedata['timecreated'])) {
2329 $updatemessage->timecreated = $messagedata['timecreated'];
2330 } else if (isset($messagedata['timemodifier'])) {
2331 $updatemessage->timecreated = $defaulttimecreated + $messagedata['timemodifier'];
2332 } else {
2333 $updatemessage->timecreated = $defaulttimecreated;
2334 }
e12d9f49 2335
883ce421 2336 $DB->update_record('messages', $updatemessage);
4d146f1a
RW
2337 }
2338
2339 foreach ($expectations as $username => $data) {
2340 // Get the recent conversations for the specified user.
2341 $user = $users[$username];
2342 $conversations = array_values(\core_message\api::get_conversations($user->id));
2343 foreach ($data as $expectation) {
2344 $otheruser = $users[$expectation['with']];
2345 $conversation = $conversations[$expectation['messageposition']];
eb5865da
JD
2346 $this->assertEquals($otheruser->id, $conversation->members[$otheruser->id]->id);
2347 $this->assertEquals($expectation['subject'], $conversation->messages[0]->text);
e12d9f49 2348 $this->assertEquals($expectation['unreadcount'], $conversation->unreadcount);
4d146f1a
RW
2349 }
2350 }
2351 }
2352
1f64514d
MN
2353 /**
2354 * Tests retrieving contacts.
2355 */
2356 public function test_get_contacts() {
2357 // Create some users.
2358 $user1 = self::getDataGenerator()->create_user();
2359
2360 // Set as the user.
2361 $this->setUser($user1);
2362
2363 $user2 = new stdClass();
2364 $user2->firstname = 'User';
2365 $user2->lastname = 'A';
2366 $user2 = self::getDataGenerator()->create_user($user2);
2367
2368 $user3 = new stdClass();
2369 $user3->firstname = 'User';
2370 $user3->lastname = 'B';
2371 $user3 = self::getDataGenerator()->create_user($user3);
2372
2373 $user4 = new stdClass();
2374 $user4->firstname = 'User';
2375 $user4->lastname = 'C';
2376 $user4 = self::getDataGenerator()->create_user($user4);
2377
2378 $user5 = new stdClass();
2379 $user5->firstname = 'User';
2380 $user5->lastname = 'D';
2381 $user5 = self::getDataGenerator()->create_user($user5);
2382
2383 // Add some users as contacts.
f219eac7
MN
2384 \core_message\api::add_contact($user1->id, $user2->id);
2385 \core_message\api::add_contact($user1->id, $user3->id);
2386 \core_message\api::add_contact($user1->id, $user4->id);
1f64514d
MN
2387
2388 // Retrieve the contacts.
2389 $contacts = \core_message\api::get_contacts($user1->id);
2390
2391 // Confirm the data is correct.
2392 $this->assertEquals(3, count($contacts));
f219eac7 2393 usort($contacts, ['static', 'sort_contacts']);
1f64514d
MN
2394
2395 $contact1 = $contacts[0];
2396 $contact2 = $contacts[1];
2397 $contact3 = $contacts[2];
2398
2399 $this->assertEquals($user2->id, $contact1->userid);
2400 $this->assertEmpty($contact1->useridfrom);
2401 $this->assertFalse($contact1->ismessaging);
2402 $this->assertNull($contact1->lastmessage);
2403 $this->assertNull($contact1->messageid);
cb805753 2404 $this->assertNull($contact1->isonline);
1f64514d
MN
2405 $this->assertFalse($contact1->isread);
2406 $this->assertFalse($contact1->isblocked);
2407 $this->assertNull($contact1->unreadcount);
2408
2409 $this->assertEquals($user3->id, $contact2->userid);
2410 $this->assertEmpty($contact2->useridfrom);
2411 $this->assertFalse($contact2->ismessaging);
2412 $this->assertNull($contact2->lastmessage);
2413 $this->assertNull($contact2->messageid);
cb805753 2414 $this->assertNull($contact2->isonline);
1f64514d
MN
2415 $this->assertFalse($contact2->isread);
2416 $this->assertFalse($contact2->isblocked);
2417 $this->assertNull($contact2->unreadcount);
2418
2419 $this->assertEquals($user4->id, $contact3->userid);
2420 $this->assertEmpty($contact3->useridfrom);
2421 $this->assertFalse($contact3->ismessaging);
2422 $this->assertNull($contact3->lastmessage);
2423 $this->assertNull($contact3->messageid);
cb805753 2424 $this->assertNull($contact3->isonline);
1f64514d
MN
2425 $this->assertFalse($contact3->isread);
2426 $this->assertFalse($contact3->isblocked);
2427 $this->assertNull($contact3->unreadcount);
2428 }
2429
715c45aa
MN
2430 /**
2431 * Tests retrieving user contacts.
2432 */
2433 public function test_get_user_contacts() {
2434 // Create some users.
2435 $user1 = self::getDataGenerator()->create_user();
2436
2437 // Set as the user.
2438 $this->setUser($user1);
2439
2440 $user2 = new stdClass();
2441 $user2->firstname = 'User';
2442 $user2->lastname = 'A';
2443 $user2 = self::getDataGenerator()->create_user($user2);
2444
2445 $user3 = new stdClass();
2446 $user3->firstname = 'User';
2447 $user3->lastname = 'B';
2448 $user3 = self::getDataGenerator()->create_user($user3);
2449
2450 $user4 = new stdClass();
2451 $user4->firstname = 'User';
2452 $user4->lastname = 'C';
2453 $user4 = self::getDataGenerator()->create_user($user4);
2454
2455 $user5 = new stdClass();
2456 $user5->firstname = 'User';
2457 $user5->lastname = 'D';
2458 $user5 = self::getDataGenerator()->create_user($user5);
2459
2460 // Add some users as contacts.
2461 \core_message\api::add_contact($user1->id, $user2->id);
2462 \core_message\api::add_contact($user1->id, $user3->id);
2463 \core_message\api::add_contact($user1->id, $user4->id);
2464
2465 // Retrieve the contacts.
2466 $contacts = \core_message\api::get_user_contacts($user1->id);
2467
2468 // Confirm the data is correct.
2469 $this->assertEquals(3, count($contacts));
2470
2471 ksort($contacts);
2472
2473 $contact1 = array_shift($contacts);
2474 $contact2 = array_shift($contacts);
2475 $contact3 = array_shift($contacts);
2476
2477 $this->assertEquals($user2->id, $contact1->id);
2478 $this->assertEquals(fullname($user2), $contact1->fullname);
2479 $this->assertTrue($contact1->iscontact);
2480
2481 $this->assertEquals($user3->id, $contact2->id);
2482 $this->assertEquals(fullname($user3), $contact2->fullname);
2483 $this->assertTrue($contact2->iscontact);
2484
2485 $this->assertEquals($user4->id, $contact3->id);
2486 $this->assertEquals(fullname($user4), $contact3->fullname);
2487 $this->assertTrue($contact3->iscontact);
2488 }
2489
1f64514d
MN
2490 /**
2491 * Tests retrieving messages.
2492 */
2493 public function test_get_messages() {
2494 // Create some users.
2495 $user1 = self::getDataGenerator()->create_user();
2496 $user2 = self::getDataGenerator()->create_user();
2497
2498 // The person doing the search.
2499 $this->setUser($user1);
2500
2501 // Send some messages back and forth.
2502 $time = 1;
2503 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2504 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2505 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2506 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2507
2508 // Retrieve the messages.
2509 $messages = \core_message\api::get_messages($user1->id, $user2->id);
2510
2511 // Confirm the message data is correct.
2512 $this->assertEquals(4, count($messages));
2513
2514 $message1 = $messages[0];
2515 $message2 = $messages[1];
2516 $message3 = $messages[2];
2517 $message4 = $messages[3];
2518
2519 $this->assertEquals($user1->id, $message1->useridfrom);
2520 $this->assertEquals($user2->id, $message1->useridto);
2521 $this->assertTrue($message1->displayblocktime);
2522 $this->assertContains('Yo!', $message1->text);
2523
2524 $this->assertEquals($user2->id, $message2->useridfrom);
2525 $this->assertEquals($user1->id, $message2->useridto);
2526 $this->assertFalse($message2->displayblocktime);
2527 $this->assertContains('Sup mang?', $message2->text);
2528
2529 $this->assertEquals($user1->id, $message3->useridfrom);
2530 $this->assertEquals($user2->id, $message3->useridto);
2531 $this->assertFalse($message3->displayblocktime);
2532 $this->assertContains('Writing PHPUnit tests!', $message3->text);
2533
2534 $this->assertEquals($user2->id, $message4->useridfrom);
2535 $this->assertEquals($user1->id, $message4->useridto);
2536 $this->assertFalse($message4->displayblocktime);
2537 $this->assertContains('Word.', $message4->text);
2538 }
2539
fb04293b
SA
2540 /**
2541 * Tests retrieving conversation messages.
2542 */
2543 public function test_get_conversation_messages() {
2544 // Create some users.
2545 $user1 = self::getDataGenerator()->create_user();
2546 $user2 = self::getDataGenerator()->create_user();
2547
2548 // Create conversation.
2549 $conversation = \core_message\api::create_conversation(
2550 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2551 [$user1->id, $user2->id]
2552 );
2553
2554 // The person doing the search.
2555 $this->setUser($user1);
2556
2557 // Send some messages back and forth.
2558 $time = 1;
2559 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2560 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2561 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2562 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2563
2564 // Retrieve the messages.
2565 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2566
2567 // Confirm the conversation id is correct.
2568 $this->assertEquals($conversation->id, $convmessages['id']);
2569
2570 // Confirm the message data is correct.
2571 $messages = $convmessages['messages'];
2572 $this->assertEquals(4, count($messages));
2573 $message1 = $messages[0];
2574 $message2 = $messages[1];
2575 $message3 = $messages[2];
2576 $message4 = $messages[3];
2577
2578 $this->assertEquals($user1->id, $message1->useridfrom);
2579 $this->assertContains('Yo!', $message1->text);
2580
2581 $this->assertEquals($user2->id, $message2->useridfrom);
2582 $this->assertContains('Sup mang?', $message2->text);
2583
2584 $this->assertEquals($user1->id, $message3->useridfrom);
2585 $this->assertContains('Writing PHPUnit tests!', $message3->text);
2586
2587 $this->assertEquals($user1->id, $message4->useridfrom);
2588 $this->assertContains('Word.', $message4->text);
2589
2590 // Confirm the members data is correct.
2591 $members = $convmessages['members'];
2592 $this->assertEquals(2, count($members));
2593 }
2594
2595 /**
2596 * Tests retrieving group conversation messages.
2597 */
2598 public function test_get_group_conversation_messages() {
2599 // Create some users.
2600 $user1 = self::getDataGenerator()->create_user();
2601 $user2 = self::getDataGenerator()->create_user();
2602 $user3 = self::getDataGenerator()->create_user();
2603 $user4 = self::getDataGenerator()->create_user();
2604
2605 // Create group conversation.
2606 $conversation = \core_message\api::create_conversation(
2607 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2608 [$user1->id, $user2->id, $user3->id, $user4->id]
2609 );
2610
2611 // The person doing the search.
2612 $this->setUser($user1);
2613
2614 // Send some messages back and forth.
2615 $time = 1;
2616 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2617 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2618 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2619 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2620 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Yeah!', $time + 5);
2621
2622 // Retrieve the messages.
2623 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2624
2625 // Confirm the conversation id is correct.
2626 $this->assertEquals($conversation->id, $convmessages['id']);
2627
2628 // Confirm the message data is correct.
2629 $messages = $convmessages['messages'];
2630 $this->assertEquals(5, count($messages));
2631
2632 $message1 = $messages[0];
2633 $message2 = $messages[1];
2634 $message3 = $messages[2];
2635 $message4 = $messages[3];
2636 $message5 = $messages[4];
2637
2638 $this->assertEquals($user1->id, $message1->useridfrom);
2639 $this->assertContains('Yo!', $message1->text);
2640
2641 $this->assertEquals($user2->id, $message2->useridfrom);
2642 $this->assertContains('Sup mang?', $message2->text);
2643
2644 $this->assertEquals($user3->id, $message3->useridfrom);
2645 $this->assertContains('Writing PHPUnit tests!', $message3->text);
2646
2647 $this->assertEquals($user1->id, $message4->useridfrom);
2648 $this->assertContains('Word.', $message4->text);
2649
2650 $this->assertEquals($user2->id, $message5->useridfrom);
2651 $this->assertContains('Yeah!', $message5->text);
2652
2653 // Confirm the members data is correct.
2654 $members = $convmessages['members'];
2655 $this->assertEquals(3, count($members));
2656 }
2657
b95e4c78
JD
2658 /**
2659 * Test verifying the sorting param for get_conversation_messages is respected().
2660 */
2661 public function test_get_conversation_messages_sorting() {
2662 // Create some users.
2663 $user1 = self::getDataGenerator()->create_user();
2664 $user2 = self::getDataGenerator()->create_user();
2665 $user3 = self::getDataGenerator()->create_user();
2666
2667 // Create conversations - 1 group and 1 individual.
2668 $conversation = \core_message\api::create_conversation(
2669 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2670 [$user1->id, $user2->id]
2671 );
2672 $conversation2 = \core_message\api::create_conversation(
2673 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2674 [$user1->id, $user2->id, $user3->id]
2675 );
2676
2677 // Send some messages back and forth.
2678 $time = 1;
2679 $m1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2680 $m2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2681 $m3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2682 $m4id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2683
2684 $gm1id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Yo!', $time + 1);
2685 $gm2id = testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Sup mang?', $time + 2);
2686 $gm3id = testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'Writing PHPUnit tests!', $time + 3);
2687 $gm4id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Word.', $time + 4);
2688
2689 // The person doing the search.
2690 $this->setUser($user1);
2691
2692 // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2693 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id);
2694 $messages = $convmessages['messages'];
2695 $this->assertEquals($m1id, $messages[0]->id);
2696 $this->assertEquals($m2id, $messages[1]->id);
2697 $this->assertEquals($m3id, $messages[2]->id);
2698 $this->assertEquals($m4id, $messages[3]->id);
2699
2700 // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2701 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated DESC');
2702 $messages = $convmessages['messages'];
2703 $this->assertEquals($m1id, $messages[3]->id);
2704 $this->assertEquals($m2id, $messages[2]->id);
2705 $this->assertEquals($m3id, $messages[1]->id);
2706 $this->assertEquals($m4id, $messages[0]->id);
2707
2708 // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2709 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id);
2710 $messages = $convmessages['messages'];
2711 $this->assertEquals($gm1id, $messages[0]->id);
2712 $this->assertEquals($gm2id, $messages[1]->id);
2713 $this->assertEquals($gm3id, $messages[2]->id);
2714 $this->assertEquals($gm4id, $messages[3]->id);
2715
2716 // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2717 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation2->id, 0, 0, 'timecreated DESC');
2718 $messages = $convmessages['messages'];
2719 $this->assertEquals($gm1id, $messages[3]->id);
2720 $this->assertEquals($gm2id, $messages[2]->id);
2721 $this->assertEquals($gm3id, $messages[1]->id);
2722 $this->assertEquals($gm4id, $messages[0]->id);
2723 }
2724
fb04293b
SA
2725 /**
2726 * Test retrieving conversation messages by providing a minimum timecreated value.
2727 */
2728 public function test_get_conversation_messages_time_from_only() {
2729 // Create some users.
2730 $user1 = self::getDataGenerator()->create_user();
2731 $user2 = self::getDataGenerator()->create_user();
2732 $user3 = self::getDataGenerator()->create_user();
2733 $user4 = self::getDataGenerator()->create_user();
2734
2735 // Create group conversation.
2736 $conversation = \core_message\api::create_conversation(
2737 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2738 [$user1->id, $user2->id, $user3->id, $user4->id]
2739 );
2740
2741 // The person doing the search.
2742 $this->setUser($user1);
2743
2744 // Send some messages back and forth.
2745 $time = 1;
2746 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2747 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2748 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2749 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2750
2751 // Retrieve the messages from $time, which should be all of them.
2752 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC', $time);
2753
2754 // Confirm the conversation id is correct.
2755 $this->assertEquals($conversation->id, $convmessages['id']);
2756
2757 // Confirm the message data is correct.
2758 $messages = $convmessages['messages'];
2759 $this->assertEquals(4, count($messages));
2760
2761 $message1 = $messages[0];
2762 $message2 = $messages[1];
2763 $message3 = $messages[2];
2764 $message4 = $messages[3];
2765
2766 $this->assertContains('Message 1', $message1->text);
2767 $this->assertContains('Message 2', $message2->text);
2768 $this->assertContains('Message 3', $message3->text);
2769 $this->assertContains('Message 4', $message4->text);
2770
2771 // Confirm the members data is correct.
2772 $members = $convmessages['members'];
2773 $this->assertEquals(3, count($members));
2774
2775 // Retrieve the messages from $time + 3, which should only be the 2 last messages.
2776 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2777 'timecreated ASC', $time + 3);
2778
2779 // Confirm the conversation id is correct.
2780 $this->assertEquals($conversation->id, $convmessages['id']);
2781
2782 // Confirm the message data is correct.
2783 $messages = $convmessages['messages'];
2784 $this->assertEquals(2, count($messages));
2785
2786 $message1 = $messages[0];
2787 $message2 = $messages[1];
2788
2789 $this->assertContains('Message 3', $message1->text);
2790 $this->assertContains('Message 4', $message2->text);
2791
2792 // Confirm the members data is correct.
2793 $members = $convmessages['members'];
2794 $this->assertEquals(2, count($members));
2795 }
2796
2797 /**
2798 * Test retrieving conversation messages by providing a maximum timecreated value.
2799 */
2800 public function test_get_conversation_messages_time_to_only() {
2801 // Create some users.
2802 $user1 = self::getDataGenerator()->create_user();
2803 $user2 = self::getDataGenerator()->create_user();
2804 $user3 = self::getDataGenerator()->create_user();
2805 $user4 = self::getDataGenerator()->create_user();
2806
2807 // Create group conversation.
2808 $conversation = \core_message\api::create_conversation(
2809 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2810 [$user1->id, $user2->id, $user3->id, $user4->id]
2811 );
2812
2813 // The person doing the search.
2814 $this->setUser($user1);
2815
2816 // Send some messages back and forth.
2817 $time = 1;
2818 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2819 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2820 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2821 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2822
2823 // Retrieve the messages up until $time + 4, which should be all of them.
2824 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2825 0, $time + 4);
2826
2827 // Confirm the conversation id is correct.
2828 $this->assertEquals($conversation->id, $convmessages['id']);
2829
2830 // Confirm the message data is correct.
2831 $messages = $convmessages['messages'];
2832 $this->assertEquals(4, count($messages));
2833
2834 $message1 = $messages[0];
2835 $message2 = $messages[1];
2836 $message3 = $messages[2];
2837 $message4 = $messages[3];
2838
2839 $this->assertContains('Message 1', $message1->text);
2840 $this->assertContains('Message 2', $message2->text);
2841 $this->assertContains('Message 3', $message3->text);
2842 $this->assertContains('Message 4', $message4->text);
2843
2844 // Confirm the members data is correct.
2845 $members = $convmessages['members'];
2846 $this->assertEquals(3, count($members));
2847
2848 // Retrieve the messages up until $time + 2, which should be the first two.
2849 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2850 0, $time + 2);
2851
2852 // Confirm the conversation id is correct.
2853 $this->assertEquals($conversation->id, $convmessages['id']);
2854
2855 // Confirm the message data is correct.
2856 $messages = $convmessages['messages'];
2857 $this->assertEquals(2, count($messages));
2858
2859 $message1 = $messages[0];
2860 $message2 = $messages[1];
2861
2862 $this->assertContains('Message 1', $message1->text);
2863 $this->assertContains('Message 2', $message2->text);
2864
2865 // Confirm the members data is correct.
2866 $members = $convmessages['members'];
2867 $this->assertEquals(2, count($members));
2868 }
2869
2870 /**
2871 * Test retrieving conversation messages by providing a minimum and maximum timecreated value.
2872 */
2873 public function test_get_conversation_messages_time_from_and_to() {
2874 // Create some users.
2875 $user1 = self::getDataGenerator()->create_user();
2876 $user2 = self::getDataGenerator()->create_user();
2877 $user3 = self::getDataGenerator()->create_user();
2878 $user4 = self::getDataGenerator()->create_user();
2879
2880 // Create group conversation.
2881 $conversation = \core_message\api::create_conversation(
2882 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2883 [$user1->id, $user2->id, $user3->id, $user4->id]
2884 );
2885
2886 // The person doing the search.
2887 $this->setUser($user1);
2888
2889 // Send some messages back and forth.
2890 $time = 1;
2891 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2892 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2893 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2894 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2895
2896 // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
2897 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2898 'timecreated ASC', $time + 2, $time + 3);
2899
2900 // Confirm the conversation id is correct.
2901 $this->assertEquals($conversation->id, $convmessages['id']);
2902
2903 // Confirm the message data is correct.
2904 $messages = $convmessages['messages'];
2905 $this->assertEquals(2, count($messages));
2906
2907 $message1 = $messages[0];
2908 $message2 = $messages[1];
2909
2910 $this->assertContains('Message 2', $message1->text);
2911 $this->assertContains('Message 3', $message2->text);
2912
2913 // Confirm the members data is correct.
2914 $members = $convmessages['members'];
2915 $this->assertEquals(2, count($members));
2916 }
2917
2918
2919 /**
2920 * Test retrieving conversation messages by providing a limitfrom value.
2921 */
2922 public function test_get_conversation_messages_limitfrom_only() {
2923 // Create some users.
2924 $user1 = self::getDataGenerator()->create_user();
2925 $user2 = self::getDataGenerator()->create_user();
2926 $user3 = self::getDataGenerator()->create_user();
2927 $user4 = self::getDataGenerator()->create_user();
2928
2929 // Create group conversation.
2930 $conversation = \core_message\api::create_conversation(
2931 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2932 [$user1->id, $user2->id, $user3->id, $user4->id]
2933 );
2934
2935 // The person doing the search.
2936 $this->setUser($user1);
2937
2938 // Send some messages back and forth.
2939 $time = 1;
2940 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2941 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2942 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2943 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2944
2945 // Retrieve the messages from $time, which should be all of them.
2946 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2);
2947
2948 // Confirm the conversation id is correct.
2949 $messages = $convmessages['messages'];
2950 $this->assertEquals($conversation->id, $convmessages['id']);
2951
2952 // Confirm the message data is correct.
2953 $this->assertEquals(2, count($messages));
2954
2955 $message1 = $messages[0];
2956 $message2 = $messages[1];
2957
2958 $this->assertContains('Message 3', $message1->text);
2959 $this->assertContains('Message 4', $message2->text);
2960
2961 // Confirm the members data is correct.
2962 $members = $convmessages['members'];
2963 $this->assertEquals(2, count($members));
2964 }
2965
2966 /**
2967 * Test retrieving conversation messages by providing a limitnum value.
2968 */
2969 public function test_get_conversation_messages_limitnum() {
2970 // Create some users.
2971 $user1 = self::getDataGenerator()->create_user();
2972 $user2 = self::getDataGenerator()->create_user();
2973 $user3 = self::getDataGenerator()->create_user();
2974 $user4 = self::getDataGenerator()->create_user();
2975
2976 // Create group conversation.
2977 $conversation = \core_message\api::create_conversation(
2978 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
2979 [$user1->id, $user2->id, $user3->id, $user4->id]
2980 );
2981
2982 // The person doing the search.
2983 $this->setUser($user1);
2984
2985 // Send some messages back and forth.
2986 $time = 1;
2987 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2988 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2989 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2990 testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2991
2992 // Retrieve the messages from $time, which should be all of them.
2993 $convmessages = \core_message\api::get_conversation_messages($user1->id, $conversation->id, 2, 1);
2994
2995 // Confirm the conversation id is correct.
2996 $messages = $convmessages['messages'];
2997 $this->assertEquals($conversation->id, $convmessages['id']);
2998
2999 // Confirm the message data is correct.
3000 $messages = $convmessages['messages'];
3001 $this->assertEquals(1, count($messages));
3002
3003 $message1 = $messages[0];
3004
3005 $this->assertContains('Message 3', $message1->text);
3006
3007 // Confirm the members data is correct.
3008 $members = $convmessages['members'];
3009 $this->assertEquals(1, count($members));
3010 }
3011
1f64514d
MN
3012 /**
3013 * Tests retrieving most recent message.
3014 */
3015 public function test_get_most_recent_message() {
3016 // Create some users.
3017 $user1 = self::getDataGenerator()->create_user();
3018 $user2 = self::getDataGenerator()->create_user();
3019
3020 // The person doing the search.
3021 $this->setUser($user1);
3022
3023 // Send some messages back and forth.
3024 $time = 1;
3025 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3026 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3027 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3028 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3029
3030 // Retrieve the most recent messages.
3031 $message = \core_message\api::get_most_recent_message($user1->id, $user2->id);
3032
3033 // Check the results are correct.
3034 $this->assertEquals($user2->id, $message->useridfrom);
3035 $this->assertEquals($user1->id, $message->useridto);
3036 $this->assertContains('Word.', $message->text);
3037 }
3038
fb04293b
SA
3039 /**
3040 * Tests retrieving most recent conversation message.
3041 */
3042 public function test_get_most_recent_conversation_message() {
3043 // Create some users.
3044 $user1 = self::getDataGenerator()->create_user();
3045 $user2 = self::getDataGenerator()->create_user();
3046 $user3 = self::getDataGenerator()->create_user();
3047
3048 // Create group conversation.
3049 $conversation = \core_message\api::create_conversation(
3050 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
3051 [$user1->id, $user2->id, $user3->id]
3052 );
3053
3054 // The person getting the most recent conversation message.
3055 $this->setUser($user1);
3056
3057 // Send some messages back and forth.
3058 $time = 1;
3059 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
3060 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
3061 testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
3062 testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Word.', $time + 4);
3063
3064 // Retrieve the most recent messages.
3065 $message = \core_message\api::get_most_recent_conversation_message($conversation->id, $user1->id);
3066
3067 // Check the results are correct.
3068 $this->assertEquals($user2->id, $message->useridfrom);
3069 $this->assertContains('Word.', $message->text);
3070 }
3071
1f64514d
MN
3072 /**
3073 * Tests retrieving a user's profile.
3074 */
3075 public function test_get_profile() {
3076 // Create some users.
3077 $user1 = self::getDataGenerator()->create_user();
3078
3079 $user2 = new stdClass();
3080 $user2->country = 'AU';
3081 $user2->city = 'Perth';
3082 $user2 = self::getDataGenerator()->create_user($user2);
3083
3084 // The person doing the search.
3085 $this->setUser($user1);
3086
3087 // Get the profile.
3088 $profile = \core_message\api::get_profile($user1->id, $user2->id);
3089
3090 $this->assertEquals($user2->id, $profile->userid);
3091 $this->assertEmpty($profile->email);
3092 $this->assertEmpty($profile->country);
3093 $this->assertEmpty($profile->city);
3094 $this->assertEquals(fullname($user2), $profile->fullname);
cb805753 3095 $this->assertNull($profile->isonline);
1f64514d
MN
3096 $this->assertFalse($profile->isblocked);
3097 $this->assertFalse($profile->iscontact);
3098 }
3099
3100 /**
3101 * Tests retrieving a user's profile.
3102 */
3103 public function test_get_profile_as_admin() {
3104 // The person doing the search.
3105 $this->setAdminUser();
3106
3107 // Create some users.
3108 $user1 = self::getDataGenerator()->create_user();
3109
3110 $user2 = new stdClass();
3111 $user2->country = 'AU';
3112 $user2->city = 'Perth';
3113 $user2 = self::getDataGenerator()->create_user($user2);
3114
3115 // Get the profile.
3116 $profile = \core_message\api::get_profile($user1->id, $user2->id);
3117
3118 $this->assertEquals($user2->id, $profile->userid);
3119 $this->assertEquals($user2->email, $profile->email);
3120 $this->assertEquals($user2->country, $profile->country);
3121 $this->assertEquals($user2->city, $profile->city);
3122 $this->assertEquals(fullname($user2), $profile->fullname);
3123 $this->assertFalse($profile->isonline);
3124 $this->assertFalse($profile->isblocked);
3125 $this->assertFalse($profile->iscontact);
3126 }
3127
abf7a261
MN
3128 /**
3129 * Tests checking if a user can mark all messages as read.
3130 */
3131 public function test_can_mark_all_messages_as_read() {
3132 // Set as the admin.
3133 $this->setAdminUser();
3134
3135 // Create some users.
3136 $user1 = self::getDataGenerator()->create_user();
3137 $user2 = self::getDataGenerator()->create_user();
3138 $user3 = self::getDataGenerator()->create_user();
3139
3140 // Send some messages back and forth.
3141 $time = 1;
3142 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3143 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3144 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3145 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3146
3147 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3148
3149 // The admin can do anything.
3150 $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
3151
3152 // Set as the user 1.
3153 $this->setUser($user1);
3154
3155 // The user can mark the messages as he is in the conversation.
3156 $this->assertTrue(\core_message\api::can_mark_all_messages_as_read($user1->id, $conversationid));
3157
3158 // User 1 can not mark the messages read for user 2.
3159 $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user2->id, $conversationid));
3160
3161 // This user is not a part of the conversation.
3162 $this->assertFalse(\core_message\api::can_mark_all_messages_as_read($user3->id, $conversationid));
3163 }
3164
1f64514d
MN
3165 /**
3166 * Tests checking if a user can delete a conversation.
3167 */
3168 public function test_can_delete_conversation() {
3169 // Set as the admin.
3170 $this->setAdminUser();
3171
3172 // Create some users.
3173 $user1 = self::getDataGenerator()->create_user();
3174 $user2 = self::getDataGenerator()->create_user();
3175
15663b0b
MN
3176 // Send some messages back and forth.
3177 $time = 1;
3178 $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3179 $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3180 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3181 $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
3182
3183 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
3184
1f64514d 3185 // The admin can do anything.
15663b0b 3186 $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
1f64514d
MN
3187
3188 // Set as the user 1.
3189 $this->setUser($user1);
3190
3191 // They can delete their own messages.
15663b0b 3192 $this->assertTrue(\core_message\api::can_delete_conversation($user1->id, $conversationid));
1f64514d
MN
3193
3194 // They can't delete someone elses.
15663b0b 3195 $this->assertFalse(\core_message\api::can_delete_conversation($user2->id, $conversationid));
1f64514d
MN
3196 }
3197
3198 /**
3199 * Tests deleting a conversation.
3200 */
3201 public function test_delete_conversation() {
3202 global $DB;
3203
3204 // Create some users.
3205 $user1 = self::getDataGenerator()->create_user();
3206 $user2 = self::getDataGenerator()->create_user();
3207
3208 // The person doing the search.
3209 $this->setUser($user1);
3210
3211 // Send some messages back and forth.
3212 $time = 1;
883ce421
MN
3213 $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3214 $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3215 $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3216 $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1f64514d
MN
3217
3218 // Delete the conversation as user 1.
3219 \core_message\api::delete_conversation($user1->id, $user2->id);
263ad984
MN
3220 $this->assertDebuggingCalled();
3221
3222 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3223 $this->assertCount(4, $muas);
3224 // Sort by id.
3225 ksort($muas);
3226
3227 $mua1 = array_shift($muas);
3228 $mua2 = array_shift($muas);
3229 $mua3 = array_shift($muas);
3230 $mua4 = array_shift($muas);
3231
3232 $this->assertEquals($user1->id, $mua1->userid);
3233 $this->assertEquals($m1id, $mua1->messageid);
3234 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
3235
3236 $this->assertEquals($user1->id, $mua2->userid);
3237 $this->assertEquals($m2id, $mua2->messageid);
3238 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
3239
3240 $this->assertEquals($user1->id, $mua3->userid);
3241 $this->assertEquals($m3id, $mua3->messageid);
3242 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
3243
3244 $this->assertEquals($user1->id, $mua4->userid);
3245 $this->assertEquals($m4id, $mua4->messageid);
3246 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
3247 }
3248
3249 /**
3250 * Tests deleting a conversation by conversation id.
3251 */
3252 public function test_delete_conversation_by_id() {
3253 global $DB;
3254
3255 // Create some users.
3256 $user1 = self::getDataGenerator()->create_user();
3257 $user2 = self::getDataGenerator()->create_user();
3258
3259 // The person doing the search.
3260 $this->setUser($user1);
3261
888a467a
AA
3262 // Get self-conversation.
3263 $sc1 = \core_message\api::get_self_conversation($user1->id);
3264 $sc2 = \core_message\api::get_self_conversation($user2->id);
734b198f 3265
263ad984
MN
3266 // Send some messages back and forth.
3267 $time = 1;
3268 $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
3269 $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
3270 $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
3271 $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
734b198f
SA
3272 $m5id = testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi to myself!', $time + 5);
3273 $m6id = testhelper::send_fake_message_to_conversation($user2, $sc2->id, 'I am talking with myself', $time + 6);
263ad984 3274
263ad984 3275 $conversationid = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]);
734b198f
SA
3276
3277 // Delete the individual conversation between user1 and user2 (only for user1).
263ad984 3278 \core_message\api::delete_conversation_by_id($user1->id, $conversationid);
1f64514d 3279
883ce421
MN
3280 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3281 $this->assertCount(4, $muas);
3282 // Sort by id.
3283 ksort($muas);
1f64514d 3284
883ce421
MN
3285 $mua1 = array_shift($muas);
3286 $mua2 = array_shift($muas);
3287 $mua3 = array_shift($muas);
3288 $mua4 = array_shift($muas);
1f64514d 3289
883ce421
MN
3290 $this->assertEquals($user1->id, $mua1->userid);
3291 $this->assertEquals($m1id, $mua1->messageid);
3292 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua1->action);
1f64514d 3293
883ce421
MN
3294 $this->assertEquals($user1->id, $mua2->userid);
3295 $this->assertEquals($m2id, $mua2->messageid);
3296 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua2->action);
1f64514d 3297
883ce421
MN
3298 $this->assertEquals($user1->id, $mua3->userid);
3299 $this->assertEquals($m3id, $mua3->messageid);
3300 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua3->action);
1f64514d 3301
883ce421
MN
3302 $this->assertEquals($user1->id, $mua4->userid);
3303 $this->assertEquals($m4id, $mua4->messageid);
3304 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua4->action);
734b198f
SA
3305
3306 // Delete the self-conversation as user 1.
3307 \core_message\api::delete_conversation_by_id($user1->id, $sc1->id);
3308
3309 $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
3310 $this->assertCount(5, $muas);
3311
3312 // Sort by id.
3313 ksort($muas);
3314
3315 $mua1 = array_shift($muas);
3316 $mua2 = array_shift($muas);
3317 $mua3 = array_shift($muas);
3318 $mua4 = array_shift($muas);
3319 $mua5 = array_shift($muas);
3320
3321 // Check only messages in self-conversion for user1 are deleted (self-conversation for user2 shouldn't be removed).
3322 $this->assertEquals($user1->id, $mua5->userid);
3323 $this->assertEquals($m5id, $mua5->messageid);
3324 $this->assertEquals(\core_message\api::MESSAGE_ACTION_DELETED, $mua5->action);
1f64514d
MN
3325 }
3326
3327 /**
3328 * Tests counting unread conversations.
3329 */
3330 public function test_count_unread_conversations() {
3331 $this->resetAfterTest(true);
3332
3333 // Create some users.
3334 $user1 = self::getDataGenerator()->create_user();
3335 $user2 = self::getDataGenerator()->create_user();
3336 $user3 = self::getDataGenerator()->create_user();
3337 $user4 = self::getDataGenerator()->create_user();
3338
3339 // The person wanting the conversation count.
3340 $this->setUser($user1);
3341
3342 // Send some messages back and forth, have some different conversations with different users.
3343 $this->send_fake_message($user1, $user2, 'Yo!');
3344 $this->send_fake_message($user2, $user1, 'Sup mang?');
3345 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
3346 $this->send_fake_message($user2, $user1, 'Word.');
3347
3348 $this->send_fake_message($user1, $user3, 'Booyah');
3349 $this->send_fake_message($user3, $user1, 'Whaaat?');
3350 $this->send_fake_message($user1, $user3, 'Nothing.');
3351 $this->send_fake_message($user3, $user1, 'Cool.');
3352
3353 $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3354 $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3355 $this->send_fake_message($user1, $user4, 'Dope.');
3356
3357 // Check the amount for the current user.
3358 $this->assertEquals(3, core_message\api::count_unread_conversations());
3359
3360 // Check the amount for the second user.
3361 $this->assertEquals(1, core_message\api::count_unread_conversations($user2));
3362 }
3363
7c8ba89d
MN
3364 /**
3365 * Tests counting unread conversations where one conversation is disabled.
3366 */
3367 public function test_count_unread_conversations_disabled() {
3368 $this->resetAfterTest(true);
3369
3370 // Create some users.
3371 $user1 = self::getDataGenerator()->create_user();
3372 $user2 = self::getDataGenerator()->create_user();
3373 $user3 = self::getDataGenerator()->create_user();
3374 $user4 = self::getDataGenerator()->create_user();
3375
3376 // The person wanting the conversation count.
3377 $this->setUser($user1);
3378
3379 // Send some messages back and forth, have some different conversations with different users.
3380 $this->send_fake_message($user1, $user2, 'Yo!');
3381 $this->send_fake_message($user2, $user1, 'Sup mang?');
3382 $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
3383 $this->send_fake_message($user2, $user1, 'Word.');
3384
3385 $this->send_fake_message($user1, $user3, 'Booyah');
3386 $this->send_fake_message($user3, $user1, 'Whaaat?');
3387 $this->send_fake_message($user1, $user3, 'Nothing.');
3388 $this->send_fake_message($user3, $user1, 'Cool.');
3389
3390 $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
3391 $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
3392 $this->send_fake_message($user1, $user4, 'Dope.');
3393
3394 // Let's disable the last conversation.
3395 $conversationid = core_message\api::get_conversation_between_users([$user1->id, $user4->id]);
3396 core_message\api::disable_conversation($conversationid);
3397
3398 // Check that the disabled conversation was not included.
3399 $this->assertEquals(2, core_message\api::count_unread_conversations());
3400 }
3401
1f64514d
MN
3402 /**
3403 * Tests deleting a conversation.
3404 */
3405 public function test_get_all_message_preferences() {
3406 $user = self::getDataGenerator()->create_user();
3407 $this->setUser($user);
3408
3409 // Set a couple of preferences to test.
3410 set_user_preference('message_provider_mod_assign_assign_notification_loggedin', 'popup', $user);
3411 set_user_preference('message_provider_mod_assign_assign_notification_loggedoff', 'email', $user);
3412
3413 $processors = get_message_processors();
3414 $providers = message_get_providers_for_user($user->id);
3415 $prefs = \core_message\api::get_all_message_preferences($processors, $providers, $user);
3416
3417 $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedin['popup']);
3418 $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedoff['email']);
3419 }
3420
3421 /**
3422 * Tests the user can post a message.
3423 */
3424 public function test_can_post_message() {
3425 // Create some users.
3426 $user1 = self::getDataGenerator()->create_user();
3427 $user2 = self::getDataGenerator()->create_user();
3428
f7dfa9ba 3429 // Set as the first user.
1f64514d
MN
3430 $this->setUser($user1);
3431
f7dfa9ba
SA
3432 // With the default privacy setting, users can't message them.
3433 $this->assertFalse(\core_message\api::can_post_message($user2));
3434
3435 // Enrol users to the same course.
3436 $course = $this->getDataGenerator()->create_course();
3437 $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3438 $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3439 // After enrolling users to the course, they should be able to message them with the default privacy setting.
1f64514d
MN
3440 $this->assertTrue(\core_message\api::can_post_message($user2));
3441 }
3442
3443 /**
3444 * Tests the user can't post a message without proper capability.
3445 */
7983fb83 3446 public function test_can_post_message_without_sendmessage_cap() {
1f64514d
MN
3447 global $DB;
3448
3449 // Create some users.
3450 $user1 = self::getDataGenerator()->create_user();
3451 $user2 = self::getDataGenerator()->create_user();
3452
3453 // Set as the user 1.
3454 $this->setUser($user1);
3455
3456 // Remove the capability to send a message.
3457 $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3458 unassign_capability('moodle/site:sendmessage', $roleids['user'],
3459 context_system::instance());
3460
3461 // Check that we can not post a message without the capability.
3462 $this->assertFalse(\core_message\api::can_post_message($user2));
3463 }
3464
f7dfa9ba
SA
3465 /**
3466 * Tests the user can post a message when they are contact.
3467 */
3468 public function test_can_post_message_when_contact() {
3469 // Create some users.
3470 $user1 = self::getDataGenerator()->create_user();
3471 $user2 = self::getDataGenerator()->create_user();
3472
3473 // Set as the first user.
3474 $this->setUser($user1);
3475
3476 // Check that we can not send user2 a message.
3477 $this->assertFalse(\core_message\api::can_post_message($user2));
3478
3479 // Add users as contacts.
3480 \core_message\api::add_contact($user1->id, $user2->id);
3481
3482 // Check that the return result is now true.
3483 $this->assertTrue(\core_message\api::can_post_message($user2));
3484 }
3485
1f64514d
MN
3486 /**
3487 * Tests the user can't post a message if they are not a contact and the user
3488 * has requested messages only from contacts.
3489 */
3490 public function test_can_post_message_when_not_contact() {
3491 // Create some users.
3492 $user1 = self::getDataGenerator()->create_user();
3493 $user2 = self::getDataGenerator()->create_user();
3494
3495 // Set as the first user.
3496 $this->setUser($user1);
3497
3498 // Set the second user's preference to not receive messages from non-contacts.
f7dfa9ba 3499 set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
1f64514d
MN
3500
3501 // Check that we can not send user 2 a message.
3502 $this->assertFalse(\core_message\api::can_post_message($user2));
3503 }
3504
3505 /**
3506 * Tests the user can't post a message if they are blocked.
3507 */
3508 public function test_can_post_message_when_blocked() {
3509 // Create some users.
3510 $user1 = self::getDataGenerator()->create_user();
3511 $user2 = self::getDataGenerator()->create_user();
3512
3513 // Set the user.
3514 $this->setUser($user1);