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