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