Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace core_message;
18
 
19
use core_message\tests\helper as testhelper;
20
 
21
defined('MOODLE_INTERNAL') || die();
22
 
23
global $CFG;
24
 
25
require_once($CFG->dirroot . '/message/tests/messagelib_test.php');
26
 
27
/**
28
 * Test message API.
29
 *
30
 * @package core_message
31
 * @category test
32
 * @copyright 2016 Mark Nelson <markn@moodle.com>
33
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class api_test extends messagelib_test {
36
 
37
    public function test_mark_all_read_for_user_touser() {
38
        $sender = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
39
        $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
40
 
41
        $this->send_fake_message($sender, $recipient, 'Notification', 1);
42
        $this->send_fake_message($sender, $recipient, 'Notification', 1);
43
        $this->send_fake_message($sender, $recipient, 'Notification', 1);
44
        $this->send_fake_message($sender, $recipient);
45
        $this->send_fake_message($sender, $recipient);
46
        $this->send_fake_message($sender, $recipient);
47
 
48
        $this->assertEquals(1, api::count_unread_conversations($recipient));
49
 
50
        api::mark_all_notifications_as_read($recipient->id);
51
        api::mark_all_messages_as_read($recipient->id);
52
 
53
        // We've marked all of recipients conversation messages as read.
54
        $this->assertEquals(0, api::count_unread_conversations($recipient));
55
    }
56
 
57
    public function test_mark_all_read_for_user_touser_with_fromuser() {
58
        $sender1 = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'User1'));
59
        $sender2 = $this->getDataGenerator()->create_user(array('firstname' => 'Test3', 'lastname' => 'User3'));
60
        $recipient = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'User2'));
61
 
62
        $this->send_fake_message($sender1, $recipient, 'Notification', 1);
63
        $this->send_fake_message($sender1, $recipient, 'Notification', 1);
64
        $this->send_fake_message($sender1, $recipient, 'Notification', 1);
65
        $this->send_fake_message($sender1, $recipient);
66
        $this->send_fake_message($sender1, $recipient);
67
        $this->send_fake_message($sender1, $recipient);
68
        $this->send_fake_message($sender2, $recipient, 'Notification', 1);
69
        $this->send_fake_message($sender2, $recipient, 'Notification', 1);
70
        $this->send_fake_message($sender2, $recipient, 'Notification', 1);
71
        $this->send_fake_message($sender2, $recipient);
72
        $this->send_fake_message($sender2, $recipient);
73
        $this->send_fake_message($sender2, $recipient);
74
 
75
        $this->assertEquals(2, api::count_unread_conversations($recipient));
76
 
77
        api::mark_all_notifications_as_read($recipient->id, $sender1->id);
78
        $conversationid = api::get_conversation_between_users([$recipient->id, $sender1->id]);
79
        api::mark_all_messages_as_read($recipient->id, $conversationid);
80
 
81
        // We've marked only the conversation with sender1 messages as read.
82
        $this->assertEquals(1, api::count_unread_conversations($recipient));
83
    }
84
 
85
    /**
86
     * Test count_blocked_users.
87
     */
88
    public function test_count_blocked_users() {
89
        global $USER;
90
 
91
        // Set this user as the admin.
92
        $this->setAdminUser();
93
 
94
        // Create user to add to the admin's block list.
95
        $user1 = $this->getDataGenerator()->create_user();
96
        $user2 = $this->getDataGenerator()->create_user();
97
 
98
        $this->assertEquals(0, api::count_blocked_users());
99
 
100
        // Add 1 blocked user to admin's blocked user list.
101
        api::block_user($USER->id, $user1->id);
102
 
103
        $this->assertEquals(0, api::count_blocked_users($user1));
104
        $this->assertEquals(1, api::count_blocked_users());
105
    }
106
 
107
    /**
108
     * Tests searching for users when site-wide messaging is disabled.
109
     *
110
     * This test verifies that any contacts are returned, as well as any non-contacts whose profile we can view.
111
     * If checks this by placing some users in the same course, where default caps would permit a user to view another user's
112
     * profile.
113
     */
114
    public function test_message_search_users_messagingallusers_disabled() {
115
        global $DB;
116
        $this->resetAfterTest();
117
 
118
        // Create some users.
119
        $users = [];
120
        foreach (range(1, 8) as $i) {
121
            $user = new \stdClass();
122
            $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
123
            $user->lastname = $i;
124
            $user = $this->getDataGenerator()->create_user($user);
125
            $users[$i] = $user;
126
        }
127
 
128
        // Enrol a few users in the same course, but leave them as non-contacts.
129
        $course1 = $this->getDataGenerator()->create_course();
130
        $course2 = $this->getDataGenerator()->create_course();
131
 
132
        $this->setAdminUser();
133
        $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
134
        $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
135
        $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
136
 
137
        // Add some other users as contacts.
138
        api::add_contact($users[1]->id, $users[2]->id);
139
        api::add_contact($users[3]->id, $users[1]->id);
140
        api::add_contact($users[1]->id, $users[4]->id);
141
 
142
        // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
143
        $this->getDataGenerator()->enrol_user($users[8]->id, $course2->id, 'editingteacher');
144
        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
145
        set_config('coursecontact', $teacherrole->id);
146
 
147
        // Create individual conversations between some users, one contact and one non-contact.
148
        $ic1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
149
            [$users[1]->id, $users[2]->id]);
150
        $ic2 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
151
            [$users[6]->id, $users[1]->id]);
152
 
153
        // Create a group conversation between 4 users, including a contact and a non-contact.
154
        $gc1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
155
            [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id], 'Project chat');
156
 
157
        // Set as the user performing the search.
158
        $this->setUser($users[1]);
159
 
160
        // Perform a search with $CFG->messagingallusers disabled.
161
        set_config('messagingallusers', 0);
162
        $result = api::message_search_users($users[1]->id, 'search');
163
 
164
        // Confirm that we returns contacts and non-contacts.
165
        $this->assertArrayHasKey(0, $result);
166
        $this->assertArrayHasKey(1, $result);
167
        $contacts = $result[0];
168
        $noncontacts = $result[1];
169
 
170
        // Check that we retrieved the correct contacts.
171
        $this->assertCount(2, $contacts);
172
        $this->assertEquals($users[2]->id, $contacts[0]->id);
173
        $this->assertEquals($users[3]->id, $contacts[1]->id);
174
 
175
        // Verify the correct conversations were returned for the contacts.
176
        $this->assertCount(2, $contacts[0]->conversations);
177
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
178
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
179
 
180
        $this->assertCount(0, $contacts[1]->conversations);
181
 
182
        // Check that we retrieved the correct non-contacts.
183
        // When site wide messaging is disabled, we expect to see only those users who we share a course with and whose profiles
184
        // are visible in that course. This excludes users like course contacts.
185
        $this->assertCount(3, $noncontacts);
186
        // Self-conversation first.
187
        $this->assertEquals($users[1]->id, $noncontacts[0]->id);
188
        $this->assertEquals($users[6]->id, $noncontacts[1]->id);
189
        $this->assertEquals($users[7]->id, $noncontacts[2]->id);
190
 
191
        // Verify the correct conversations were returned for the non-contacts.
192
        $this->assertCount(1, $noncontacts[1]->conversations);
193
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
194
            $noncontacts[1]->conversations[$ic2->id]->type);
195
 
196
        $this->assertCount(1, $noncontacts[2]->conversations);
197
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
198
    }
199
 
200
    /**
201
     * Tests searching for users when site-wide messaging is enabled.
202
     *
203
     * This test verifies that any contacts are returned, as well as any non-contacts,
204
     * provided the searching user can view their profile.
205
     */
206
    public function test_message_search_users_messagingallusers_enabled() {
207
        global $DB;
208
        $this->resetAfterTest();
209
 
210
        // Create some users.
211
        $users = [];
212
        foreach (range(1, 9) as $i) {
213
            $user = new \stdClass();
214
            $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
215
            $user->lastname = $i;
216
            $user = $this->getDataGenerator()->create_user($user);
217
            $users[$i] = $user;
218
        }
219
 
220
        $course1 = $this->getDataGenerator()->create_course();
221
        $coursecontext = \context_course::instance($course1->id);
222
 
223
        // Enrol a few users in the same course, but leave them as non-contacts.
224
        $this->setAdminUser();
225
        $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id, 'student');
226
        $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id, 'student');
227
        $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id, 'student');
228
 
229
        // Add some other users as contacts.
230
        api::add_contact($users[1]->id, $users[2]->id);
231
        api::add_contact($users[3]->id, $users[1]->id);
232
        api::add_contact($users[1]->id, $users[4]->id);
233
 
234
        // Enrol a user as a teacher in the course, and make the teacher role a course contact role.
235
        $this->getDataGenerator()->enrol_user($users[9]->id, $course1->id, 'editingteacher');
236
        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
237
        set_config('coursecontact', $teacherrole->id);
238
 
239
        // Get self-conversation.
240
        $selfconversation = api::get_self_conversation($users[1]->id);
241
 
242
        // Create individual conversations between some users, one contact and one non-contact.
243
        $ic1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
244
            [$users[1]->id, $users[2]->id]);
245
        $ic2 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
246
            [$users[6]->id, $users[1]->id]);
247
 
248
        // Create a group conversation between 5 users, including a contact and a non-contact, and a user NOT in a shared course.
249
        $gc1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
250
            [$users[1]->id, $users[2]->id, $users[4]->id, $users[7]->id, $users[8]->id], 'Project chat');
251
 
252
        // Set as the user performing the search.
253
        $this->setUser($users[1]);
254
 
255
        // Perform a search with $CFG->messagingallusers enabled.
256
        set_config('messagingallusers', 1);
257
        $result = api::message_search_users($users[1]->id, 'search');
258
 
259
        // Confirm that we returns contacts and non-contacts.
260
        $this->assertArrayHasKey(0, $result);
261
        $this->assertArrayHasKey(1, $result);
262
        $contacts = $result[0];
263
        $noncontacts = $result[1];
264
 
265
        // Check that we retrieved the correct contacts.
266
        $this->assertCount(2, $contacts);
267
        $this->assertEquals($users[2]->id, $contacts[0]->id);
268
        $this->assertEquals($users[3]->id, $contacts[1]->id);
269
 
270
        // Verify the correct conversations were returned for the contacts.
271
        $this->assertCount(2, $contacts[0]->conversations);
272
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $contacts[0]->conversations[$gc1->id]->type);
273
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $contacts[0]->conversations[$ic1->id]->type);
274
 
275
        $this->assertCount(0, $contacts[1]->conversations);
276
 
277
        // Check that we retrieved the correct non-contacts.
278
        // If site wide messaging is enabled, we expect to only be able to search for users whose profiles we can view.
279
        // In this case, as a student, that's the course contact for course2 and those noncontacts sharing a course with user1.
280
        // Consider first conversations is self-conversation.
281
        $this->assertCount(4, $noncontacts);
282
        $this->assertEquals($users[1]->id, $noncontacts[0]->id);
283
        $this->assertEquals($users[6]->id, $noncontacts[1]->id);
284
        $this->assertEquals($users[7]->id, $noncontacts[2]->id);
285
        $this->assertEquals($users[9]->id, $noncontacts[3]->id);
286
 
287
        $this->assertCount(1, $noncontacts[1]->conversations);
288
        $this->assertCount(1, $noncontacts[2]->conversations);
289
        $this->assertCount(0, $noncontacts[3]->conversations);
290
 
291
        // Verify the correct conversations were returned for the non-contacts.
292
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_SELF,
293
            $noncontacts[0]->conversations[$selfconversation->id]->type);
294
 
295
        $this->assertCount(1, $noncontacts[1]->conversations);
296
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
297
            $noncontacts[1]->conversations[$ic2->id]->type);
298
 
299
        $this->assertCount(1, $noncontacts[2]->conversations);
300
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $noncontacts[2]->conversations[$gc1->id]->type);
301
 
302
        $this->assertCount(0, $noncontacts[3]->conversations);
303
    }
304
 
305
    /**
306
     * Verify searching for users find themselves when they have self-conversations.
307
     */
308
    public function test_message_search_users_self_conversations() {
309
        $this->resetAfterTest();
310
 
311
        // Create some users.
312
        $user1 = new \stdClass();
313
        $user1->firstname = 'User';
314
        $user1->lastname = 'One';
315
        $user1 = $this->getDataGenerator()->create_user($user1);
316
        $user2 = new \stdClass();
317
        $user2->firstname = 'User';
318
        $user2->lastname = 'Two';
319
        $user2 = $this->getDataGenerator()->create_user($user2);
320
 
321
        // Get self-conversation for user1.
322
        $sc1 = api::get_self_conversation($user1->id);
323
        testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi myself!');
324
 
325
        // Perform a search as user1.
326
        $this->setUser($user1);
327
        $result = api::message_search_users($user1->id, 'One');
328
 
329
        // Check user1 is found as non-contacts.
330
        $this->assertCount(0, $result[0]);
331
        $this->assertCount(1, $result[1]);
332
    }
333
 
334
    /**
335
     * Verify searching for users works even if no matching users from either contacts, or non-contacts can be found.
336
     */
337
    public function test_message_search_users_with_empty_result() {
338
        $this->resetAfterTest();
339
 
340
        // Create some users, but make sure neither will match the search term.
341
        $user1 = new \stdClass();
342
        $user1->firstname = 'User';
343
        $user1->lastname = 'One';
344
        $user1 = $this->getDataGenerator()->create_user($user1);
345
        $user2 = new \stdClass();
346
        $user2->firstname = 'User';
347
        $user2->lastname = 'Two';
348
        $user2 = $this->getDataGenerator()->create_user($user2);
349
 
350
        // Perform a search as user1.
351
        $this->setUser($user1);
352
        $result = api::message_search_users($user1->id, 'search');
353
 
354
        // Check results are empty.
355
        $this->assertCount(0, $result[0]);
356
        $this->assertCount(0, $result[1]);
357
    }
358
 
359
    /**
360
     * Test verifying that limits and offsets work for both the contacts and non-contacts return data.
361
     */
362
    public function test_message_search_users_limit_offset() {
363
        $this->resetAfterTest();
364
 
365
        // Create 20 users.
366
        $users = [];
367
        foreach (range(1, 20) as $i) {
368
            $user = new \stdClass();
369
            $user->firstname = "User search";
370
            $user->lastname = $i;
371
            $user = $this->getDataGenerator()->create_user($user);
372
            $users[$i] = $user;
373
        }
374
 
375
        // Enrol the first 9 users in the same course, but leave them as non-contacts.
376
        $this->setAdminUser();
377
        $course1 = $this->getDataGenerator()->create_course();
378
        foreach (range(1, 8) as $i) {
379
            $this->getDataGenerator()->enrol_user($users[$i]->id, $course1->id);
380
        }
381
 
382
        // Add 5 users, starting at the 11th user, as contacts for user1.
383
        foreach (range(11, 15) as $i) {
384
            api::add_contact($users[1]->id, $users[$i]->id);
385
        }
386
 
387
        // Set as the user performing the search.
388
        $this->setUser($users[1]);
389
 
390
        // Search using a limit of 3.
391
        // This tests the case where we have more results than the limit for both contacts and non-contacts.
392
        $result = api::message_search_users($users[1]->id, 'search', 0, 3);
393
        $contacts = $result[0];
394
        $noncontacts = $result[1];
395
 
396
        // Check that we retrieved the correct contacts.
397
        $this->assertCount(3, $contacts);
398
        $this->assertEquals($users[11]->id, $contacts[0]->id);
399
        $this->assertEquals($users[12]->id, $contacts[1]->id);
400
        $this->assertEquals($users[13]->id, $contacts[2]->id);
401
 
402
        // Check that we retrieved the correct non-contacts.
403
        // Consider first conversations is self-conversation.
404
        $this->assertCount(3, $noncontacts);
405
        $this->assertEquals($users[1]->id, $noncontacts[0]->id);
406
        $this->assertEquals($users[2]->id, $noncontacts[1]->id);
407
        $this->assertEquals($users[3]->id, $noncontacts[2]->id);
408
 
409
        // Now, offset to get the next batch of results.
410
        // We expect to see 2 contacts, and 3 non-contacts.
411
        $result = api::message_search_users($users[1]->id, 'search', 3, 3);
412
        $contacts = $result[0];
413
        $noncontacts = $result[1];
414
        $this->assertCount(2, $contacts);
415
        $this->assertEquals($users[14]->id, $contacts[0]->id);
416
        $this->assertEquals($users[15]->id, $contacts[1]->id);
417
 
418
        $this->assertCount(3, $noncontacts);
419
        $this->assertEquals($users[4]->id, $noncontacts[0]->id);
420
        $this->assertEquals($users[5]->id, $noncontacts[1]->id);
421
        $this->assertEquals($users[6]->id, $noncontacts[2]->id);
422
 
423
        // Now, offset to get the next batch of results.
424
        // We expect to see 0 contacts, and 2 non-contacts.
425
        $result = api::message_search_users($users[1]->id, 'search', 6, 3);
426
        $contacts = $result[0];
427
        $noncontacts = $result[1];
428
        $this->assertCount(0, $contacts);
429
 
430
        $this->assertCount(2, $noncontacts);
431
        $this->assertEquals($users[7]->id, $noncontacts[0]->id);
432
        $this->assertEquals($users[8]->id, $noncontacts[1]->id);
433
    }
434
 
435
    /**
436
     * Tests searching users as a user having the 'moodle/user:viewdetails' capability.
437
     */
438
    public function test_message_search_users_with_cap() {
439
        $this->resetAfterTest();
440
        global $DB;
441
 
442
        // Create some users.
443
        $users = [];
444
        foreach (range(1, 8) as $i) {
445
            $user = new \stdClass();
446
            $user->firstname = ($i == 4) ? 'User' : 'User search'; // Ensure the fourth user won't match the search term.
447
            $user->lastname = $i;
448
            $user = $this->getDataGenerator()->create_user($user);
449
            $users[$i] = $user;
450
        }
451
 
452
        // Enrol a few users in the same course, but leave them as non-contacts.
453
        $course1 = $this->getDataGenerator()->create_course();
454
        $this->setAdminUser();
455
        $this->getDataGenerator()->enrol_user($users[1]->id, $course1->id);
456
        $this->getDataGenerator()->enrol_user($users[6]->id, $course1->id);
457
        $this->getDataGenerator()->enrol_user($users[7]->id, $course1->id);
458
 
459
        // Add some other users as contacts.
460
        api::add_contact($users[1]->id, $users[2]->id);
461
        api::add_contact($users[3]->id, $users[1]->id);
462
        api::add_contact($users[1]->id, $users[4]->id);
463
 
464
        // Set as the user performing the search.
465
        $this->setUser($users[1]);
466
 
467
        // Grant the authenticated user role the capability 'user:viewdetails' at site context.
468
        $authenticatedrole = $DB->get_record('role', ['shortname' => 'user'], '*', MUST_EXIST);
469
        assign_capability('moodle/user:viewdetails', CAP_ALLOW, $authenticatedrole->id, \context_system::instance());
470
 
471
        // Perform a search with $CFG->messagingallusers disabled.
472
        set_config('messagingallusers', 0);
473
        $result = api::message_search_users($users[1]->id, 'search');
474
        $contacts = $result[0];
475
        $noncontacts = $result[1];
476
 
477
        // Check that we retrieved the correct contacts.
478
        $this->assertCount(2, $contacts);
479
        $this->assertEquals($users[2]->id, $contacts[0]->id);
480
        $this->assertEquals($users[3]->id, $contacts[1]->id);
481
 
482
        // Check that we retrieved the correct non-contacts.
483
        // Site-wide messaging is disabled, so we expect to be able to search for any users whose profiles we can view.
484
        // Consider first conversations is self-conversation.
485
        $this->assertCount(3, $noncontacts);
486
        $this->assertEquals($users[1]->id, $noncontacts[0]->id);
487
        $this->assertEquals($users[6]->id, $noncontacts[1]->id);
488
        $this->assertEquals($users[7]->id, $noncontacts[2]->id);
489
    }
490
 
491
    /**
492
     * Tests searching users with messaging disabled.
493
     */
494
    public function test_message_search_users_messaging_disabled() {
495
        $this->resetAfterTest();
496
 
497
        // Create a user.
498
        $user = $this->getDataGenerator()->create_user();
499
 
500
        // Disable messaging.
501
        set_config('messaging', 0);
502
 
503
        // Ensure an exception is thrown.
504
        $this->expectException('moodle_exception');
505
        api::message_search_users($user->id, 'User');
506
    }
507
 
508
    /**
509
     * Tests getting conversations between 2 users.
510
     */
511
    public function test_get_conversations_between_users() {
512
        // Create some users.
513
        $user1 = new \stdClass();
514
        $user1->firstname = 'User';
515
        $user1->lastname = 'One';
516
        $user1 = self::getDataGenerator()->create_user($user1);
517
 
518
        $user2 = new \stdClass();
519
        $user2->firstname = 'User';
520
        $user2->lastname = 'Two';
521
        $user2 = self::getDataGenerator()->create_user($user2);
522
 
523
        $user3 = new \stdClass();
524
        $user3->firstname = 'User search';
525
        $user3->lastname = 'Three';
526
        $user3 = self::getDataGenerator()->create_user($user3);
527
 
528
        $user4 = new \stdClass();
529
        $user4->firstname = 'User';
530
        $user4->lastname = 'Four';
531
        $user4 = self::getDataGenerator()->create_user($user4);
532
 
533
        $user5 = new \stdClass();
534
        $user5->firstname = 'User';
535
        $user5->lastname = 'Five';
536
        $user5 = self::getDataGenerator()->create_user($user5);
537
 
538
        $user6 = new \stdClass();
539
        $user6->firstname = 'User search';
540
        $user6->lastname = 'Six';
541
        $user6 = self::getDataGenerator()->create_user($user6);
542
 
543
        // Add some users as contacts.
544
        api::add_contact($user1->id, $user2->id);
545
        api::add_contact($user6->id, $user1->id);
546
 
547
        // Create private conversations with some users.
548
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
549
            array($user1->id, $user2->id));
550
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
551
            array($user3->id, $user1->id));
552
 
553
        // Create a group conversation with users.
554
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
555
            array($user1->id, $user2->id, $user3->id, $user4->id),
556
            'Project chat');
557
 
558
        // Check that we retrieved the correct conversations.
559
        $this->assertCount(2, api::get_conversations_between_users($user1->id, $user2->id));
560
        $this->assertCount(2, api::get_conversations_between_users($user2->id, $user1->id));
561
        $this->assertCount(2, api::get_conversations_between_users($user1->id, $user3->id));
562
        $this->assertCount(2, api::get_conversations_between_users($user3->id, $user1->id));
563
        $this->assertCount(1, api::get_conversations_between_users($user1->id, $user4->id));
564
        $this->assertCount(1, api::get_conversations_between_users($user4->id, $user1->id));
565
        $this->assertCount(0, api::get_conversations_between_users($user1->id, $user5->id));
566
        $this->assertCount(0, api::get_conversations_between_users($user5->id, $user1->id));
567
        $this->assertCount(0, api::get_conversations_between_users($user1->id, $user6->id));
568
        $this->assertCount(0, api::get_conversations_between_users($user6->id, $user1->id));
569
    }
570
 
571
    /**
572
     * Tests getting self-conversations.
573
     */
574
    public function test_get_self_conversation() {
575
        // Create some users.
576
        $user1 = new \stdClass();
577
        $user1->firstname = 'User';
578
        $user1->lastname = 'One';
579
        $user1 = self::getDataGenerator()->create_user($user1);
580
 
581
        $user2 = new \stdClass();
582
        $user2->firstname = 'User';
583
        $user2->lastname = 'Two';
584
        $user2 = self::getDataGenerator()->create_user($user2);
585
 
586
        $user3 = new \stdClass();
587
        $user3->firstname = 'User search';
588
        $user3->lastname = 'Three';
589
        $user3 = self::getDataGenerator()->create_user($user3);
590
 
591
        // Add some users as contacts.
592
        api::add_contact($user1->id, $user2->id);
593
        api::add_contact($user3->id, $user1->id);
594
 
595
        // Create private conversations with some users.
596
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
597
            array($user1->id, $user2->id));
598
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
599
            array($user3->id, $user1->id));
600
 
601
        // Create a group conversation with users.
602
        $gc = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
603
            array($user1->id, $user2->id, $user3->id),
604
            'Project chat');
605
 
606
        // Get self-conversations.
607
        $rsc1 = api::get_self_conversation($user1->id);
608
        $rsc2 = api::get_self_conversation($user2->id);
609
        $rsc3 = api::get_self_conversation($user3->id);
610
 
611
        // Send message to self-conversation.
612
        testhelper::send_fake_message_to_conversation($user1, $rsc1->id, 'Message to myself!');
613
 
614
        // Check that we retrieved the correct conversations.
615
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_SELF, $rsc1->type);
616
        $members = api::get_conversation_members($user1->id, $rsc1->id);
617
        $this->assertCount(1, $members);
618
        $member = reset($members);
619
        $this->assertEquals($user1->id, $member->id);
620
 
621
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_SELF, $rsc2->type);
622
        $members = api::get_conversation_members($user2->id, $rsc2->id);
623
        $this->assertCount(1, $members);
624
        $member = reset($members);
625
        $this->assertEquals($user2->id, $member->id);
626
 
627
        api::delete_all_conversation_data($rsc3->id);
628
        $selfconversation = api::get_self_conversation($user3->id);
629
        $members = api::get_conversation_members($user1->id, $selfconversation->id);
630
        $this->assertCount(1, $members);
631
    }
632
 
633
    /**
634
     * Tests searching messages.
635
     */
636
    public function test_search_messages() {
637
        $this->resetAfterTest();
638
 
639
        // Create some users.
640
        $user1 = self::getDataGenerator()->create_user();
641
        $user2 = self::getDataGenerator()->create_user();
642
        $user3 = self::getDataGenerator()->create_user();
643
 
644
        // The person doing the search.
645
        $this->setUser($user1);
646
 
647
        // Get self-conversation.
648
        $sc = api::get_self_conversation($user1->id);
649
 
650
        // Create group conversation.
651
        $gc = api::create_conversation(
652
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
653
            [$user1->id, $user2->id, $user3->id]
654
        );
655
 
656
        // Send some messages back and forth.
657
        $time = 1;
658
        testhelper::send_fake_message_to_conversation($user1, $sc->id, 'Test message to self!', $time);
659
        testhelper::send_fake_message_to_conversation($user1, $gc->id, 'My hero!', $time + 1);
660
        $this->send_fake_message($user3, $user1, 'Don\'t block me.', 0, $time + 2);
661
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 3);
662
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 4);
663
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 5);
664
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 6);
665
 
666
        $convid = api::get_conversation_between_users([$user1->id, $user2->id]);
667
        $conv2id = api::get_conversation_between_users([$user1->id, $user3->id]);
668
 
669
        // Block user 3.
670
        api::block_user($user1->id, $user3->id);
671
 
672
        // Perform a search.
673
        $messages = api::search_messages($user1->id, 'o');
674
 
675
        // Confirm the data is correct.
676
        $this->assertEquals(5, count($messages));
677
        $message1 = $messages[0];
678
        $message2 = $messages[1];
679
        $message3 = $messages[2];
680
        $message4 = $messages[3];
681
        $message5 = $messages[4];
682
 
683
        $this->assertEquals($user2->id, $message1->userid);
684
        $this->assertEquals($user2->id, $message1->useridfrom);
685
        $this->assertEquals(fullname($user2), $message1->fullname);
686
        $this->assertTrue($message1->ismessaging);
687
        $this->assertEquals('Word.', $message1->lastmessage);
688
        $this->assertNotEmpty($message1->messageid);
689
        $this->assertNull($message1->isonline);
690
        $this->assertFalse($message1->isread);
691
        $this->assertFalse($message1->isblocked);
692
        $this->assertNull($message1->unreadcount);
693
        $this->assertEquals($convid, $message1->conversationid);
694
 
695
        $this->assertEquals($user2->id, $message2->userid);
696
        $this->assertEquals($user1->id, $message2->useridfrom);
697
        $this->assertEquals(fullname($user2), $message2->fullname);
698
        $this->assertTrue($message2->ismessaging);
699
        $this->assertEquals('Yo!', $message2->lastmessage);
700
        $this->assertNotEmpty($message2->messageid);
701
        $this->assertNull($message2->isonline);
702
        $this->assertTrue($message2->isread);
703
        $this->assertFalse($message2->isblocked);
704
        $this->assertNull($message2->unreadcount);
705
        $this->assertEquals($convid, $message2->conversationid);
706
 
707
        $this->assertEquals($user3->id, $message3->userid);
708
        $this->assertEquals($user3->id, $message3->useridfrom);
709
        $this->assertEquals(fullname($user3), $message3->fullname);
710
        $this->assertTrue($message3->ismessaging);
711
        $this->assertEquals('Don\'t block me.', $message3->lastmessage);
712
        $this->assertNotEmpty($message3->messageid);
713
        $this->assertNull($message3->isonline);
714
        $this->assertFalse($message3->isread);
715
        $this->assertTrue($message3->isblocked);
716
        $this->assertNull($message3->unreadcount);
717
        $this->assertEquals($conv2id, $message3->conversationid);
718
 
719
        // This is a group conversation. For now, search_messages returns only one of the other users on the conversation. It can't
720
        // be guaranteed who will be returned in the first place, so we need to use the in_array to check all the possibilities.
721
        $this->assertTrue(in_array($message4->userid, [$user2->id, $user3->id]));
722
        $this->assertEquals($user1->id, $message4->useridfrom);
723
        $this->assertTrue($message4->ismessaging);
724
        $this->assertEquals('My hero!', $message4->lastmessage);
725
        $this->assertNotEmpty($message4->messageid);
726
        $this->assertNull($message4->isonline);
727
        $this->assertTrue($message4->isread);
728
        $this->assertNull($message4->unreadcount);
729
        $this->assertEquals($gc->id, $message4->conversationid);
730
 
731
        $this->assertEquals($user1->id, $message5->userid);
732
        $this->assertEquals($user1->id, $message5->useridfrom);
733
        $this->assertEquals(fullname($user1), $message5->fullname);
734
        $this->assertTrue($message5->ismessaging);
735
        $this->assertEquals('Test message to self!', $message5->lastmessage);
736
        $this->assertNotEmpty($message5->messageid);
737
        $this->assertFalse($message5->isonline);
738
        $this->assertTrue($message5->isread);
739
        $this->assertFalse($message5->isblocked);
740
        $this->assertNull($message5->unreadcount);
741
        $this->assertEquals($sc->id, $message5->conversationid);
742
    }
743
 
744
    /**
745
     * Test verifying that favourited conversations can be retrieved.
746
     */
747
    public function test_get_favourite_conversations() {
748
        // Create some users.
749
        $user1 = self::getDataGenerator()->create_user();
750
        $user2 = self::getDataGenerator()->create_user();
751
        $user3 = self::getDataGenerator()->create_user();
752
        $user4 = self::getDataGenerator()->create_user();
753
 
754
        // The person doing the search.
755
        $this->setUser($user1);
756
 
757
        // Only self-conversation created.
758
        $this->assertCount(1, api::get_conversations($user1->id));
759
 
760
        // Create some conversations for user1.
761
        $time = 1;
762
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
763
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
764
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
765
        $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
766
 
767
        $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
768
        $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
769
        $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
770
        $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
771
 
772
        $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
773
        $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
774
        $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
775
 
776
        // Favourite the first 2 conversations for user1.
777
        $convoids = [];
778
        $convoids[] = api::get_conversation_between_users([$user1->id, $user2->id]);
779
        $convoids[] = api::get_conversation_between_users([$user1->id, $user3->id]);
780
        $user1context = \context_user::instance($user1->id);
781
        $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
782
        foreach ($convoids as $convoid) {
783
            $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
784
        }
785
 
786
        // We should have 4 conversations.
787
        // Consider first conversations is self-conversation.
788
        $this->assertCount(4, api::get_conversations($user1->id));
789
 
790
        // And 3 favourited conversations (self-conversation included).
791
        $conversations = api::get_conversations($user1->id, 0, 20, null, true);
792
        $this->assertCount(3, $conversations);
793
        $conversations = api::get_conversations(
794
            $user1->id,
795
            0,
796
            20,
797
            api::MESSAGE_CONVERSATION_TYPE_SELF,
798
            true
799
        );
800
        $this->assertCount(1, $conversations);
801
    }
802
 
803
    /**
804
     * Tests retrieving favourite conversations with a limit and offset to ensure pagination works correctly.
805
     */
806
    public function test_get_favourite_conversations_limit_offset() {
807
        // Create some users.
808
        $user1 = self::getDataGenerator()->create_user();
809
        $user2 = self::getDataGenerator()->create_user();
810
        $user3 = self::getDataGenerator()->create_user();
811
        $user4 = self::getDataGenerator()->create_user();
812
 
813
        // The person doing the search.
814
        $this->setUser($user1);
815
 
816
        // Only self-conversation created.
817
        $this->assertCount(1, api::get_conversations($user1->id));
818
 
819
        // Create some conversations for user1.
820
        $time = 1;
821
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
822
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
823
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
824
        $messageid1 = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
825
 
826
        $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
827
        $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
828
        $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
829
        $messageid2 = $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
830
 
831
        $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?', 0, $time + 9);
832
        $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.', 0, $time + 10);
833
        $messageid3 = $this->send_fake_message($user1, $user4, 'Dope.', 0, $time + 11);
834
 
835
        // Favourite the all conversations for user1.
836
        $convoids = [];
837
        $convoids[] = api::get_conversation_between_users([$user1->id, $user2->id]);
838
        $convoids[] = api::get_conversation_between_users([$user1->id, $user3->id]);
839
        $convoids[] = api::get_conversation_between_users([$user1->id, $user4->id]);
840
        $user1context = \context_user::instance($user1->id);
841
        $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
842
        foreach ($convoids as $convoid) {
843
            $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
844
        }
845
 
846
        // Consider first conversations is self-conversation.
847
        // Get all records, using offset 0 and large limit.
848
        $this->assertCount(4, api::get_conversations($user1->id, 0, 20, null, true));
849
 
850
        // Now, get 10 conversations starting at the second record. We should see 2 conversations.
851
        $this->assertCount(3, api::get_conversations($user1->id, 1, 10, null, true));
852
 
853
        // Now, try to get favourited conversations using an invalid offset.
854
        $this->assertCount(0, api::get_conversations($user1->id, 5, 10, null, true));
855
    }
856
 
857
    /**
858
     * Tests retrieving favourite conversations when a conversation contains a deleted user.
859
     */
860
    public function test_get_favourite_conversations_with_deleted_user() {
861
        // Create some users.
862
        $user1 = self::getDataGenerator()->create_user();
863
        $user2 = self::getDataGenerator()->create_user();
864
        $user3 = self::getDataGenerator()->create_user();
865
 
866
        // Send some messages back and forth, have some different conversations with different users.
867
        $time = 1;
868
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
869
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
870
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
871
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
872
 
873
        $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
874
        $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
875
        $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
876
        $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
877
 
878
        // Favourite the all conversations for user1.
879
        $convoids = [];
880
        $convoids[] = api::get_conversation_between_users([$user1->id, $user2->id]);
881
        $convoids[] = api::get_conversation_between_users([$user1->id, $user3->id]);
882
        $user1context = \context_user::instance($user1->id);
883
        $service = \core_favourites\service_factory::get_service_for_user_context($user1context);
884
        foreach ($convoids as $convoid) {
885
            $service->create_favourite('core_message', 'message_conversations', $convoid, $user1context);
886
        }
887
 
888
        // Delete the second user.
889
        delete_user($user2);
890
 
891
        // Retrieve the conversations.
892
        $conversations = api::get_conversations($user1->id, 0, 20, null, true);
893
 
894
        // We should have both conversations, despite the other user being soft-deleted.
895
        // Consider first conversations is self-conversation.
896
        $this->assertCount(3, $conversations);
897
 
898
        // Confirm the conversation is from the non-deleted user.
899
        $conversation = reset($conversations);
900
        $this->assertEquals($convoids[1], $conversation->id);
901
    }
902
 
903
    /**
904
     * Test confirming that conversations can be marked as favourites.
905
     */
906
    public function test_set_favourite_conversation() {
907
        // Create some users.
908
        $user1 = self::getDataGenerator()->create_user();
909
        $user2 = self::getDataGenerator()->create_user();
910
        $user3 = self::getDataGenerator()->create_user();
911
 
912
        // Send some messages back and forth, have some different conversations with different users.
913
        $time = 1;
914
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
915
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
916
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
917
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
918
 
919
        $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
920
        $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
921
        $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
922
        $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
923
 
924
        // Favourite the first conversation as user 1.
925
        $conversationid1 = api::get_conversation_between_users([$user1->id, $user2->id]);
926
        $favourite = api::set_favourite_conversation($conversationid1, $user1->id);
927
 
928
        // Verify we have two favourite conversations a user 1.
929
        // Consider first conversations is self-conversation.
930
        $this->assertCount(2, api::get_conversations($user1->id, 0, 20, null, true));
931
 
932
        // Verify we have only one favourite as user2, despite being a member in that conversation.
933
        // Consider first conversations is self-conversation.
934
        $this->assertCount(1, api::get_conversations($user2->id, 0, 20, null, true));
935
 
936
        // Try to favourite the same conversation again should just return the existing favourite.
937
        $repeatresult = api::set_favourite_conversation($conversationid1, $user1->id);
938
        $this->assertEquals($favourite->id, $repeatresult->id);
939
    }
940
 
941
    /**
942
     * Test verifying that trying to mark a non-existent conversation as a favourite, results in an exception.
943
     */
944
    public function test_set_favourite_conversation_nonexistent_conversation() {
945
        // Create some users.
946
        $user1 = self::getDataGenerator()->create_user();
947
        // Try to favourite a non-existent conversation.
948
        $this->expectException(\moodle_exception::class);
949
        api::set_favourite_conversation(0, $user1->id);
950
    }
951
 
952
    /**
953
     * Test verifying that a conversation cannot be marked as favourite unless the user is a member of that conversation.
954
     */
955
    public function test_set_favourite_conversation_non_member() {
956
        // Create some users.
957
        $user1 = self::getDataGenerator()->create_user();
958
        $user2 = self::getDataGenerator()->create_user();
959
        $user3 = self::getDataGenerator()->create_user();
960
 
961
        // Send some messages back and forth, have some different conversations with different users.
962
        $time = 1;
963
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
964
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
965
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
966
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
967
 
968
        $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
969
        $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
970
        $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
971
        $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
972
 
973
        // Try to favourite the first conversation as user 3, who is not a member.
974
        $conversationid1 = api::get_conversation_between_users([$user1->id, $user2->id]);
975
        $this->expectException(\moodle_exception::class);
976
        api::set_favourite_conversation($conversationid1, $user3->id);
977
    }
978
 
979
    /**
980
     * Test confirming that those conversations marked as favourites can be unfavourited.
981
     */
982
    public function test_unset_favourite_conversation() {
983
        // Create some users.
984
        $user1 = self::getDataGenerator()->create_user();
985
        $user2 = self::getDataGenerator()->create_user();
986
        $user3 = self::getDataGenerator()->create_user();
987
 
988
        // Send some messages back and forth, have some different conversations with different users.
989
        $time = 1;
990
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
991
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
992
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
993
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
994
 
995
        $this->send_fake_message($user1, $user3, 'Booyah', 0, $time + 5);
996
        $this->send_fake_message($user3, $user1, 'Whaaat?', 0, $time + 6);
997
        $this->send_fake_message($user1, $user3, 'Nothing.', 0, $time + 7);
998
        $this->send_fake_message($user3, $user1, 'Cool.', 0, $time + 8);
999
 
1000
        // Favourite the first conversation as user 1 and the second as user 3.
1001
        $conversationid1 = api::get_conversation_between_users([$user1->id, $user2->id]);
1002
        $conversationid2 = api::get_conversation_between_users([$user1->id, $user3->id]);
1003
        api::set_favourite_conversation($conversationid1, $user1->id);
1004
        api::set_favourite_conversation($conversationid2, $user3->id);
1005
 
1006
        // Verify we have two favourite conversations for both user 1 and user 3, counting self conversations.
1007
        $this->assertCount(2, api::get_conversations($user1->id, 0, 20, null, true));
1008
        $this->assertCount(2, api::get_conversations($user3->id, 0, 20, null, true));
1009
 
1010
        // Now unfavourite the conversation as user 1.
1011
        api::unset_favourite_conversation($conversationid1, $user1->id);
1012
 
1013
        // Verify we have two favourite conversations user 3 only, and one for user1, counting self conversations.
1014
        $this->assertCount(2, api::get_conversations($user3->id, 0, 20, null, true));
1015
        $this->assertCount(1, api::get_conversations($user1->id, 0, 20, null, true));
1016
 
1017
        // Try to favourite the same conversation again as user 1.
1018
        $this->expectException(\moodle_exception::class);
1019
        api::unset_favourite_conversation($conversationid1, $user1->id);
1020
    }
1021
 
1022
    /**
1023
     * Test verifying that a valid conversation cannot be unset as a favourite if it's not marked as a favourite.
1024
     */
1025
    public function test_unset_favourite_conversation_not_favourite() {
1026
        // Create some users.
1027
        $user1 = self::getDataGenerator()->create_user();
1028
        $user2 = self::getDataGenerator()->create_user();
1029
 
1030
        // Send some messages back and forth, have some different conversations with different users.
1031
        $time = 1;
1032
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
1033
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
1034
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
1035
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
1036
 
1037
        // Now try to unfavourite the conversation as user 1.
1038
        $conversationid1 = api::get_conversation_between_users([$user1->id, $user2->id]);
1039
        $this->expectException(\moodle_exception::class);
1040
        api::unset_favourite_conversation($conversationid1, $user1->id);
1041
    }
1042
 
1043
    /**
1044
     * Test verifying that a non-existent conversation cannot be unset as a favourite.
1045
     */
1046
    public function test_unset_favourite_conversation_non_existent_conversation() {
1047
        // Create some users.
1048
        $user1 = self::getDataGenerator()->create_user();
1049
 
1050
        // Now try to unfavourite the conversation as user 1.
1051
        $this->expectException(\moodle_exception::class);
1052
        api::unset_favourite_conversation(0, $user1->id);
1053
    }
1054
 
1055
    /**
1056
     * Helper to seed the database with initial state.
1057
     */
1058
    protected function create_conversation_test_data() {
1059
        // Create some users.
1060
        $user1 = self::getDataGenerator()->create_user();
1061
        $user2 = self::getDataGenerator()->create_user();
1062
        $user3 = self::getDataGenerator()->create_user();
1063
        $user4 = self::getDataGenerator()->create_user();
1064
 
1065
        $time = 1;
1066
 
1067
        // Create some conversations. We want:
1068
        // 1) At least one of each type (group, individual) of which user1 IS a member and DID send the most recent message.
1069
        // 2) At least one of each type (group, individual) of which user1 IS a member and DID NOT send the most recent message.
1070
        // 3) At least one of each type (group, individual) of which user1 IS NOT a member.
1071
        // 4) At least two group conversation having 0 messages, of which user1 IS a member (To confirm conversationid ordering).
1072
        // 5) At least one group conversation having 0 messages, of which user1 IS NOT a member.
1073
 
1074
        // Individual conversation, user1 is a member, last message from other user.
1075
        $ic1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1076
            [$user1->id, $user2->id]);
1077
        testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message 1', $time);
1078
        testhelper::send_fake_message_to_conversation($user2, $ic1->id, 'Message 2', $time + 1);
1079
 
1080
        // Individual conversation, user1 is a member, last message from user1.
1081
        $ic2 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1082
            [$user1->id, $user3->id]);
1083
        testhelper::send_fake_message_to_conversation($user3, $ic2->id, 'Message 3', $time + 2);
1084
        testhelper::send_fake_message_to_conversation($user1, $ic2->id, 'Message 4', $time + 3);
1085
 
1086
        // Individual conversation, user1 is not a member.
1087
        $ic3 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1088
            [$user2->id, $user3->id]);
1089
        testhelper::send_fake_message_to_conversation($user2, $ic3->id, 'Message 5', $time + 4);
1090
        testhelper::send_fake_message_to_conversation($user3, $ic3->id, 'Message 6', $time + 5);
1091
 
1092
        // Group conversation, user1 is not a member.
1093
        $gc1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1094
            [$user2->id, $user3->id, $user4->id], 'Project discussions');
1095
        testhelper::send_fake_message_to_conversation($user2, $gc1->id, 'Message 7', $time + 6);
1096
        testhelper::send_fake_message_to_conversation($user4, $gc1->id, 'Message 8', $time + 7);
1097
 
1098
        // Group conversation, user1 is a member, last message from another user.
1099
        $gc2 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1100
            [$user1->id, $user3->id, $user4->id], 'Group chat');
1101
        testhelper::send_fake_message_to_conversation($user1, $gc2->id, 'Message 9', $time + 8);
1102
        testhelper::send_fake_message_to_conversation($user3, $gc2->id, 'Message 10', $time + 9);
1103
        testhelper::send_fake_message_to_conversation($user4, $gc2->id, 'Message 11', $time + 10);
1104
 
1105
        // Group conversation, user1 is a member, last message from user1.
1106
        $gc3 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1107
            [$user1->id, $user2->id, $user3->id, $user4->id], 'Group chat again!');
1108
        testhelper::send_fake_message_to_conversation($user4, $gc3->id, 'Message 12', $time + 11);
1109
        testhelper::send_fake_message_to_conversation($user3, $gc3->id, 'Message 13', $time + 12);
1110
        testhelper::send_fake_message_to_conversation($user1, $gc3->id, 'Message 14', $time + 13);
1111
 
1112
        // Empty group conversations (x2), user1 is a member.
1113
        $gc4 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1114
            [$user1->id, $user2->id, $user3->id], 'Empty group');
1115
        $gc5 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1116
            [$user1->id, $user2->id, $user4->id], 'Another empty group');
1117
 
1118
        // Empty group conversation, user1 is NOT a member.
1119
        $gc6 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1120
            [$user2->id, $user3->id, $user4->id], 'Empty group 3');
1121
 
1122
        return [$user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, $gc1, $gc2, $gc3, $gc4, $gc5, $gc6];
1123
    }
1124
 
1125
    /**
1126
     * Test verifying get_conversations when no limits, offsets, type filters or favourite restrictions are used.
1127
     */
1128
    public function test_get_conversations_no_restrictions() {
1129
        global $DB;
1130
 
1131
        $user1 = self::getDataGenerator()->create_user();
1132
        // Self-conversation should exists.
1133
        $this->assertCount(1, api::get_conversations($user1->id));
1134
 
1135
        // Get a bunch of conversations, some group, some individual and in different states.
1136
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1137
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1138
 
1139
        // Get all conversations for user1.
1140
        $conversations = api::get_conversations($user1->id);
1141
 
1142
        // Verify there are 2 individual conversation, 2 group conversations, 2 empty group conversations,
1143
        // and a self-conversation.
1144
        // The conversations with the most recent messages should be listed first, followed by the empty
1145
        // conversations, with the most recently created first.
1146
        $this->assertCount(7, $conversations);
1147
        $typecounts  = array_count_values(array_column($conversations, 'type'));
1148
        $this->assertEquals(2, $typecounts[1]);
1149
        $this->assertEquals(4, $typecounts[2]);
1150
        $this->assertEquals(1, $typecounts[3]);
1151
 
1152
        // Those conversations having messages should be listed after self-conversation, ordered by most recent message time.
1153
        $this->assertEquals($gc3->id, $conversations[0]->id);
1154
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[0]->type);
1155
        $this->assertFalse($conversations[1]->isfavourite);
1156
        $this->assertCount(1, $conversations[0]->members);
1157
        $this->assertEquals(4, $conversations[0]->membercount);
1158
        $this->assertCount(1, $conversations[0]->messages);
1159
        $message = $DB->get_record('messages', ['id' => $conversations[0]->messages[0]->id]);
1160
        $expectedmessagetext = message_format_message_text($message);
1161
        $this->assertEquals($expectedmessagetext, $conversations[0]->messages[0]->text);
1162
        $this->assertEquals($user1->id, $conversations[0]->messages[0]->useridfrom);
1163
 
1164
        $this->assertEquals($gc2->id, $conversations[1]->id);
1165
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[1]->type);
1166
        $this->assertFalse($conversations[1]->isfavourite);
1167
        $this->assertCount(1, $conversations[1]->members);
1168
        $this->assertEquals(3, $conversations[1]->membercount);
1169
        $this->assertCount(1, $conversations[1]->messages);
1170
        $message = $DB->get_record('messages', ['id' => $conversations[1]->messages[0]->id]);
1171
        $expectedmessagetext = message_format_message_text($message);
1172
        $this->assertEquals($expectedmessagetext, $conversations[1]->messages[0]->text);
1173
        $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1174
 
1175
        $this->assertEquals($ic2->id, $conversations[2]->id);
1176
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[2]->type);
1177
        $this->assertFalse($conversations[2]->isfavourite);
1178
        $this->assertCount(1, $conversations[2]->members);
1179
        $this->assertEquals($user3->id, $conversations[2]->members[$user3->id]->id);
1180
        $this->assertEquals(2, $conversations[2]->membercount);
1181
        $this->assertCount(1, $conversations[2]->messages);
1182
        $message = $DB->get_record('messages', ['id' => $conversations[2]->messages[0]->id]);
1183
        $expectedmessagetext = message_format_message_text($message);
1184
        $this->assertEquals($expectedmessagetext, $conversations[2]->messages[0]->text);
1185
        $this->assertEquals($user1->id, $conversations[2]->messages[0]->useridfrom);
1186
 
1187
        $this->assertEquals($ic1->id, $conversations[3]->id);
1188
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversations[3]->type);
1189
        $this->assertFalse($conversations[3]->isfavourite);
1190
        $this->assertCount(1, $conversations[3]->members);
1191
        $this->assertEquals(2, $conversations[3]->membercount);
1192
        $this->assertCount(1, $conversations[3]->messages);
1193
        $message = $DB->get_record('messages', ['id' => $conversations[3]->messages[0]->id]);
1194
        $expectedmessagetext = message_format_message_text($message);
1195
        $this->assertEquals($expectedmessagetext, $conversations[3]->messages[0]->text);
1196
        $this->assertEquals($user2->id, $conversations[3]->messages[0]->useridfrom);
1197
 
1198
        // Of the groups without messages, we expect to see the most recently created first.
1199
        $this->assertEquals($gc5->id, $conversations[4]->id);
1200
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[4]->type);
1201
        $this->assertFalse($conversations[4]->isfavourite);
1202
        $this->assertCount(0, $conversations[4]->members); // No members returned, because no recent messages exist.
1203
        $this->assertEquals(3, $conversations[4]->membercount);
1204
        $this->assertEmpty($conversations[4]->messages);
1205
 
1206
        $this->assertEquals($gc4->id, $conversations[5]->id);
1207
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversations[5]->type);
1208
        $this->assertFalse($conversations[5]->isfavourite);
1209
        $this->assertCount(0, $conversations[5]->members);
1210
        $this->assertEquals(3, $conversations[5]->membercount);
1211
        $this->assertEmpty($conversations[5]->messages);
1212
 
1213
        // Verify format of the return structure.
1214
        foreach ($conversations as $conv) {
1215
            $this->assertObjectHasProperty('id', $conv);
1216
            $this->assertObjectHasProperty('name', $conv);
1217
            $this->assertObjectHasProperty('subname', $conv);
1218
            $this->assertObjectHasProperty('imageurl', $conv);
1219
            $this->assertObjectHasProperty('type', $conv);
1220
            $this->assertObjectHasProperty('isfavourite', $conv);
1221
            $this->assertObjectHasProperty('membercount', $conv);
1222
            $this->assertObjectHasProperty('isread', $conv);
1223
            $this->assertObjectHasProperty('unreadcount', $conv);
1224
            $this->assertObjectHasProperty('members', $conv);
1225
            foreach ($conv->members as $member) {
1226
                $this->assertObjectHasProperty('id', $member);
1227
                $this->assertObjectHasProperty('fullname', $member);
1228
                $this->assertObjectHasProperty('profileimageurl', $member);
1229
                $this->assertObjectHasProperty('profileimageurlsmall', $member);
1230
                $this->assertObjectHasProperty('isonline', $member);
1231
                $this->assertObjectHasProperty('showonlinestatus', $member);
1232
                $this->assertObjectHasProperty('isblocked', $member);
1233
                $this->assertObjectHasProperty('iscontact', $member);
1234
                $this->assertObjectHasProperty('isdeleted', $member);
1235
                $this->assertObjectHasProperty('canmessage', $member);
1236
                $this->assertObjectHasProperty('requirescontact', $member);
1237
                $this->assertObjectHasProperty('contactrequests', $member);
1238
            }
1239
            $this->assertObjectHasProperty('messages', $conv);
1240
            foreach ($conv->messages as $message) {
1241
                $this->assertObjectHasProperty('id', $message);
1242
                $this->assertObjectHasProperty('useridfrom', $message);
1243
                $this->assertObjectHasProperty('text', $message);
1244
                $this->assertObjectHasProperty('timecreated', $message);
1245
            }
1246
        }
1247
    }
1248
 
1249
    /**
1250
     * Test verifying that html format messages are supported, and that message_format_message_text() is being called appropriately.
1251
     */
1252
    public function test_get_conversations_message_format() {
1253
        global $DB;
1254
        // Create some users.
1255
        $user1 = self::getDataGenerator()->create_user();
1256
        $user2 = self::getDataGenerator()->create_user();
1257
 
1258
        // Create conversation.
1259
        $conversation = api::create_conversation(
1260
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1261
            [$user1->id, $user2->id]
1262
        );
1263
 
1264
        // Send some messages back and forth.
1265
        $time = 1;
1266
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 1);
1267
        $mid = testhelper::send_fake_message_to_conversation($user1, $conversation->id, '<a href="#">A link</a>', $time + 2);
1268
 
1269
        // Verify the format of the html message.
1270
        $message = $DB->get_record('messages', ['id' => $mid]);
1271
        $expectedmessagetext = message_format_message_text($message);
1272
        $conversations = api::get_conversations($user1->id);
1273
        $messages = $conversations[0]->messages;
1274
        $this->assertEquals($expectedmessagetext, $messages[0]->text);
1275
    }
1276
 
1277
    /**
1278
     * Test verifying get_conversations identifies if a conversation is muted or not.
1279
     */
1280
    public function test_get_conversations_some_muted() {
1281
        // Create some users.
1282
        $user1 = self::getDataGenerator()->create_user();
1283
        $user2 = self::getDataGenerator()->create_user();
1284
        $user3 = self::getDataGenerator()->create_user();
1285
 
1286
        $conversation1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1287
            [$user1->id, $user2->id]);
1288
        testhelper::send_fake_message_to_conversation($user1, $conversation1->id, 'Message 1');
1289
        testhelper::send_fake_message_to_conversation($user2, $conversation1->id, 'Message 2');
1290
        api::mute_conversation($user1->id, $conversation1->id);
1291
 
1292
        $conversation2 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1293
            [$user1->id, $user3->id]);
1294
        testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Message 1');
1295
        testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Message 2');
1296
 
1297
        $conversation3 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1298
            [$user1->id, $user2->id]);
1299
        api::mute_conversation($user1->id, $conversation3->id);
1300
 
1301
        $conversation4 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP,
1302
            [$user1->id, $user3->id]);
1303
 
1304
        $conversations = api::get_conversations($user1->id);
1305
 
1306
        usort($conversations, function($first, $second){
1307
            return $first->id <=> $second->id;
1308
        });
1309
 
1310
        // Consider first conversations is self-conversation.
1311
        $selfconversation = array_shift($conversations);
1312
        $conv1 = array_shift($conversations);
1313
        $conv2 = array_shift($conversations);
1314
        $conv3 = array_shift($conversations);
1315
        $conv4 = array_shift($conversations);
1316
 
1317
        $this->assertTrue($conv1->ismuted);
1318
        $this->assertFalse($conv2->ismuted);
1319
        $this->assertTrue($conv3->ismuted);
1320
        $this->assertFalse($conv4->ismuted);
1321
    }
1322
 
1323
    /**
1324
     * Tests retrieving conversations with a limit and offset to ensure pagination works correctly.
1325
     */
1326
    public function test_get_conversations_limit_offset() {
1327
        // Get a bunch of conversations, some group, some individual and in different states.
1328
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1329
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1330
 
1331
        // Get all conversations for user1, limited to 1 result.
1332
        $conversations = api::get_conversations($user1->id, 0, 1);
1333
 
1334
        // Verify the first conversation.
1335
        $this->assertCount(1, $conversations);
1336
        $conversation = array_shift($conversations);
1337
        $this->assertEquals($conversation->id, $gc3->id);
1338
 
1339
        // Verify the next conversation.
1340
        $conversations = api::get_conversations($user1->id, 1, 1);
1341
        $this->assertCount(1, $conversations);
1342
        $this->assertEquals($gc2->id, $conversations[0]->id);
1343
 
1344
        // Verify the next conversation.
1345
        $conversations = api::get_conversations($user1->id, 2, 1);
1346
        $this->assertCount(1, $conversations);
1347
        $this->assertEquals($ic2->id, $conversations[0]->id);
1348
 
1349
        // Skip one and get both empty conversations.
1350
        $conversations = api::get_conversations($user1->id, 4, 2);
1351
        $this->assertCount(2, $conversations);
1352
        $this->assertEquals($gc5->id, $conversations[0]->id);
1353
        $this->assertEmpty($conversations[0]->messages);
1354
        $this->assertEquals($gc4->id, $conversations[1]->id);
1355
        $this->assertEmpty($conversations[1]->messages);
1356
 
1357
        // Ask for an offset that doesn't exist and verify no conversations are returned.
1358
        $conversations = api::get_conversations($user1->id, 10, 1);
1359
        $this->assertCount(0, $conversations);
1360
    }
1361
 
1362
    /**
1363
     * Test verifying the type filtering behaviour of the
1364
     */
1365
    public function test_get_conversations_type_filter() {
1366
        // Get a bunch of conversations, some group, some individual and in different states.
1367
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1368
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1369
 
1370
        // Verify we can ask for only individual conversations.
1371
        $conversations = api::get_conversations($user1->id, 0, 20,
1372
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1373
        $this->assertCount(2, $conversations);
1374
 
1375
        // Verify we can ask for only group conversations.
1376
        $conversations = api::get_conversations($user1->id, 0, 20,
1377
            api::MESSAGE_CONVERSATION_TYPE_GROUP);
1378
        $this->assertCount(4, $conversations);
1379
 
1380
        // Verify an exception is thrown if an unrecognized type is specified.
1381
        $this->expectException(\moodle_exception::class);
1382
        $conversations = api::get_conversations($user1->id, 0, 20, 0);
1383
    }
1384
 
1385
    /**
1386
     * Tests retrieving conversations when a 'self' conversation exists.
1387
     */
1388
    public function test_get_conversations_self_conversations() {
1389
        global $DB;
1390
 
1391
        // Create a conversation between one user and themself.
1392
        $user1 = self::getDataGenerator()->create_user();
1393
        $user2 = self::getDataGenerator()->create_user();
1394
        $user3 = self::getDataGenerator()->create_user();
1395
        $user4 = self::getDataGenerator()->create_user();
1396
 
1397
        // Create some individual conversations.
1398
        $ic1 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1399
            [$user1->id, $user2->id]);
1400
        $ic2 = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1401
            [$user1->id, $user3->id]);
1402
        testhelper::send_fake_message_to_conversation($user1, $ic1->id, 'Message from user1 to user2');
1403
 
1404
        // Get some self-conversations.
1405
        $sc1 = api::get_self_conversation($user1->id);
1406
        $sc4 = api::get_self_conversation($user4->id);
1407
        testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Test message to self 1!');
1408
 
1409
        // Verify we are in a 'self' conversation state.
1410
        $members = $DB->get_records('message_conversation_members', ['conversationid' => $sc1->id]);
1411
        $this->assertCount(1, $members);
1412
        $member = array_pop($members);
1413
        $this->assertEquals($user1->id, $member->userid);
1414
 
1415
        // Verify the self-conversations are returned by the method.
1416
        $conversations = api::get_conversations($user1->id, 0, 20, api::MESSAGE_CONVERSATION_TYPE_SELF);
1417
        $this->assertCount(1, $conversations);
1418
        $conversation = array_pop($conversations);
1419
        $this->assertEquals($conversation->id, $sc1->id);
1420
 
1421
        $conversations = api::get_conversations($user4->id);
1422
        // The self-conversation.
1423
        $this->assertCount(1, $conversations);
1424
 
1425
        // Get only private conversations for user1 (empty conversations, like $ic2, are not returned).
1426
        $conversations = api::get_conversations($user1->id, 0, 20,
1427
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1428
        $this->assertCount(1, $conversations);
1429
 
1430
        // Merge self with private conversations for user1.
1431
        $conversations = api::get_conversations($user1->id, 0, 20,
1432
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
1433
        $this->assertCount(2, $conversations);
1434
 
1435
        // Get only private conversations for user2.
1436
        $conversations = api::get_conversations($user2->id, 0, 20,
1437
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL);
1438
        $this->assertCount(1, $conversations);
1439
 
1440
        // Merge self with private conversations for user2.
1441
        $conversations = api::get_conversations($user2->id, 0, 20,
1442
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, null, true);
1443
        $this->assertCount(2, $conversations);
1444
    }
1445
 
1446
    /**
1447
     * Tests retrieving conversations when a conversation contains a deleted user.
1448
     */
1449
    public function test_get_conversations_with_deleted_user() {
1450
        // Get a bunch of conversations, some group, some individual and in different states.
1451
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1452
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1453
 
1454
        // Delete the second user and retrieve the conversations.
1455
        // We should have 6 still, as conversations with soft-deleted users are still returned.
1456
        // Group conversations are also present, albeit with less members.
1457
        delete_user($user2);
1458
        // This is to confirm an exception is not thrown when a user AND the user context is deleted.
1459
        // We no longer delete the user context, but historically we did.
1460
        \context_helper::delete_instance(CONTEXT_USER, $user2->id);
1461
        $conversations = api::get_conversations($user1->id);
1462
        // Consider there's a self-conversation (the last one).
1463
        $this->assertCount(7, $conversations);
1464
        $this->assertEquals($gc3->id, $conversations[0]->id);
1465
        $this->assertcount(1, $conversations[0]->members);
1466
        $this->assertEquals($gc2->id, $conversations[1]->id);
1467
        $this->assertcount(1, $conversations[1]->members);
1468
        $this->assertEquals($ic2->id, $conversations[2]->id);
1469
        $this->assertEquals($ic1->id, $conversations[3]->id);
1470
        $this->assertEquals($gc5->id, $conversations[4]->id);
1471
        $this->assertEquals($gc4->id, $conversations[5]->id);
1472
 
1473
        // Delete a user from a group conversation where that user had sent the most recent message.
1474
        // This user will still be present in the members array, as will the message in the messages array.
1475
        delete_user($user4);
1476
        $conversations = api::get_conversations($user1->id);
1477
 
1478
        // Consider there's a self-conversation (the last one).
1479
        $this->assertCount(7, $conversations);
1480
        $this->assertEquals($gc2->id, $conversations[1]->id);
1481
        $this->assertcount(1, $conversations[1]->members);
1482
        $this->assertEquals($user4->id, $conversations[1]->members[$user4->id]->id);
1483
        $this->assertcount(1, $conversations[1]->messages);
1484
        $this->assertEquals($user4->id, $conversations[1]->messages[0]->useridfrom);
1485
 
1486
        // Delete the third user and retrieve the conversations.
1487
        // We should have 6 still, as conversations with soft-deleted users are still returned.
1488
        // Group conversations are also present, albeit with less members.
1489
        delete_user($user3);
1490
        $conversations = api::get_conversations($user1->id);
1491
        // Consider there's a self-conversation (the last one).
1492
        $this->assertCount(7, $conversations);
1493
        $this->assertEquals($gc3->id, $conversations[0]->id);
1494
        $this->assertcount(1, $conversations[0]->members);
1495
        $this->assertEquals($gc2->id, $conversations[1]->id);
1496
        $this->assertcount(1, $conversations[1]->members);
1497
        $this->assertEquals($ic2->id, $conversations[2]->id);
1498
        $this->assertEquals($ic1->id, $conversations[3]->id);
1499
        $this->assertEquals($gc5->id, $conversations[4]->id);
1500
        $this->assertEquals($gc4->id, $conversations[5]->id);
1501
    }
1502
 
1503
    /**
1504
     * Test confirming the behaviour of get_conversations() when users delete all messages.
1505
     */
1506
    public function test_get_conversations_deleted_messages() {
1507
        // Get a bunch of conversations, some group, some individual and in different states.
1508
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1509
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1510
 
1511
        $conversations = api::get_conversations($user1->id);
1512
        // Consider first conversations is self-conversation.
1513
        $this->assertCount(7, $conversations);
1514
 
1515
        // Delete all messages from a group conversation the user is in - it should be returned.
1516
        $this->assertTrue(api::is_user_in_conversation($user1->id, $gc2->id));
1517
        $convmessages = api::get_conversation_messages($user1->id, $gc2->id);
1518
        $messages = $convmessages['messages'];
1519
        foreach ($messages as $message) {
1520
            api::delete_message($user1->id, $message->id);
1521
        }
1522
        $conversations = api::get_conversations($user1->id);
1523
        // Consider first conversations is self-conversation.
1524
        $this->assertCount(7, $conversations);
1525
        $this->assertContainsEquals($gc2->id, array_column($conversations, 'id'));
1526
 
1527
        // Delete all messages from an individual conversation the user is in - it should not be returned.
1528
        $this->assertTrue(api::is_user_in_conversation($user1->id, $ic1->id));
1529
        $convmessages = api::get_conversation_messages($user1->id, $ic1->id);
1530
        $messages = $convmessages['messages'];
1531
        foreach ($messages as $message) {
1532
            api::delete_message($user1->id, $message->id);
1533
        }
1534
        $conversations = api::get_conversations($user1->id);
1535
        // Consider first conversations is self-conversation.
1536
        $this->assertCount(6, $conversations);
1537
        $this->assertNotContainsEquals($ic1->id, array_column($conversations, 'id'));
1538
    }
1539
 
1540
    /**
1541
     * Test verifying the behaviour of get_conversations() when fetching favourite conversations with only a single
1542
     * favourite.
1543
     */
1544
    public function test_get_conversations_favourite_conversations_single() {
1545
        // Get a bunch of conversations, some group, some individual and in different states.
1546
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1547
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1548
 
1549
        // Mark a single conversation as favourites.
1550
        api::set_favourite_conversation($ic2->id, $user1->id);
1551
 
1552
        // Get the conversation, first with no restrictions, confirming the favourite status of the conversations.
1553
        $conversations = api::get_conversations($user1->id);
1554
        // Consider there is a self-conversation.
1555
        $selfconversation = api::get_self_conversation($user1->id);
1556
        $this->assertCount(7, $conversations);
1557
        foreach ($conversations as $conv) {
1558
            if (in_array($conv->id, [$ic2->id, $selfconversation->id])) {
1559
                $this->assertTrue($conv->isfavourite);
1560
            } else {
1561
                $this->assertFalse($conv->isfavourite);
1562
            }
1563
        }
1564
 
1565
        // Now, get ONLY favourite conversations (including self-conversation).
1566
        $conversations = api::get_conversations($user1->id, 0, 20, null, true);
1567
        $this->assertCount(2, $conversations);
1568
        foreach ($conversations as $conv) {
1569
            if ($conv->type != api::MESSAGE_CONVERSATION_TYPE_SELF) {
1570
                $this->assertTrue($conv->isfavourite);
1571
                $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conv->type);
1572
                $this->assertEquals($ic2->id, $conv->id);
1573
            }
1574
        }
1575
 
1576
        // Now, try ONLY favourites of type 'group'.
1577
        $conversations = api::get_conversations($user1->id, 0, 20,
1578
            api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1579
        $this->assertEmpty($conversations);
1580
 
1581
        // And NO favourite conversations.
1582
        $conversations = api::get_conversations($user1->id, 0, 20, null, false);
1583
        $this->assertCount(5, $conversations);
1584
        foreach ($conversations as $conv) {
1585
            $this->assertFalse($conv->isfavourite);
1586
            $this->assertNotEquals($ic2, $conv->id);
1587
        }
1588
    }
1589
 
1590
    /**
1591
     * Test verifying the behaviour of get_conversations() when fetching favourite conversations.
1592
     */
1593
    public function test_get_conversations_favourite_conversations() {
1594
        // Get a bunch of conversations, some group, some individual and in different states.
1595
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
1596
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
1597
 
1598
        // Try to get ONLY favourite conversations, when only self-conversation exist.
1599
        $this->assertCount(1, api::get_conversations($user1->id, 0, 20, null, true));
1600
 
1601
        // Unstar self-conversation.
1602
        $selfconversation = api::get_self_conversation($user1->id);
1603
        api::unset_favourite_conversation($selfconversation->id, $user1->id);
1604
 
1605
        // Try to get ONLY favourite conversations, when no favourites exist.
1606
        $this->assertEquals([], api::get_conversations($user1->id, 0, 20, null, true));
1607
 
1608
        // Try to get NO favourite conversations, when no favourites exist.
1609
        $this->assertCount(7, api::get_conversations($user1->id, 0, 20, null, false));
1610
 
1611
        // Mark a few conversations as favourites.
1612
        api::set_favourite_conversation($ic1->id, $user1->id);
1613
        api::set_favourite_conversation($gc2->id, $user1->id);
1614
        api::set_favourite_conversation($gc5->id, $user1->id);
1615
        $favouriteids = [$ic1->id, $gc2->id, $gc5->id];
1616
 
1617
        // Get the conversations, first with no restrictions, confirming the favourite status of the conversations.
1618
        $conversations = api::get_conversations($user1->id);
1619
        $this->assertCount(7, $conversations);
1620
        foreach ($conversations as $conv) {
1621
            if (in_array($conv->id, $favouriteids)) {
1622
                $this->assertTrue($conv->isfavourite);
1623
            } else {
1624
                $this->assertFalse($conv->isfavourite);
1625
            }
1626
        }
1627
 
1628
        // Now, get ONLY favourite conversations.
1629
        $conversations = api::get_conversations($user1->id, 0, 20, null, true);
1630
        $this->assertCount(3, $conversations);
1631
        foreach ($conversations as $conv) {
1632
            $this->assertTrue($conv->isfavourite);
1633
            $this->assertNotFalse(array_search($conv->id, $favouriteids));
1634
        }
1635
 
1636
        // Now, try ONLY favourites of type 'group'.
1637
        $conversations = api::get_conversations($user1->id, 0, 20,
1638
            api::MESSAGE_CONVERSATION_TYPE_GROUP, true);
1639
        $this->assertCount(2, $conversations);
1640
        foreach ($conversations as $conv) {
1641
            $this->assertTrue($conv->isfavourite);
1642
            $this->assertNotFalse(array_search($conv->id, [$gc2->id, $gc5->id]));
1643
        }
1644
 
1645
        // And NO favourite conversations.
1646
        $conversations = api::get_conversations($user1->id, 0, 20, null, false);
1647
        $this->assertCount(4, $conversations);
1648
        foreach ($conversations as $conv) {
1649
            $this->assertFalse($conv->isfavourite);
1650
            $this->assertFalse(array_search($conv->id, $favouriteids));
1651
        }
1652
    }
1653
 
1654
    /**
1655
     * Test verifying get_conversations when there are users in a group and/or individual conversation. The reason this
1656
     * test is performed is because we do not need as much data for group conversations (saving DB calls), so we want
1657
     * to confirm this happens.
1658
     */
1659
    public function test_get_conversations_user_in_group_and_individual_chat() {
1660
        $this->resetAfterTest();
1661
 
1662
        $user1 = self::getDataGenerator()->create_user();
1663
        $user2 = self::getDataGenerator()->create_user();
1664
        $user3 = self::getDataGenerator()->create_user();
1665
 
1666
        $conversation = api::create_conversation(
1667
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
1668
            [
1669
                $user1->id,
1670
                $user2->id
1671
            ],
1672
            'Individual conversation'
1673
        );
1674
 
1675
        testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1676
 
1677
        $conversation = api::create_conversation(
1678
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
1679
            [
1680
                $user1->id,
1681
                $user2->id,
1682
            ],
1683
            'Group conversation'
1684
        );
1685
 
1686
        testhelper::send_fake_message_to_conversation($user1, $conversation->id);
1687
 
1688
        api::create_contact_request($user1->id, $user2->id);
1689
        api::create_contact_request($user1->id, $user3->id);
1690
 
1691
        $conversations = api::get_conversations($user2->id);
1692
 
1693
        $groupconversation = array_shift($conversations);
1694
        $individualconversation = array_shift($conversations);
1695
 
1696
        $this->assertEquals('Group conversation', $groupconversation->name);
1697
        $this->assertEquals('Individual conversation', $individualconversation->name);
1698
 
1699
        $this->assertCount(1, $groupconversation->members);
1700
        $this->assertCount(1, $individualconversation->members);
1701
 
1702
        $groupmember = reset($groupconversation->members);
1703
        $this->assertNull($groupmember->requirescontact);
1704
        $this->assertNull($groupmember->canmessage);
1705
        $this->assertEmpty($groupmember->contactrequests);
1706
 
1707
        $individualmember = reset($individualconversation->members);
1708
        $this->assertNotNull($individualmember->requirescontact);
1709
        $this->assertNotNull($individualmember->canmessage);
1710
        $this->assertNotEmpty($individualmember->contactrequests);
1711
    }
1712
 
1713
    /**
1714
     * Test verifying that group linked conversations are returned and contain a subname matching the course name.
1715
     */
1716
    public function test_get_conversations_group_linked() {
1717
        global $CFG, $DB;
1718
 
1719
        // Create some users.
1720
        $user1 = self::getDataGenerator()->create_user();
1721
        $user2 = self::getDataGenerator()->create_user();
1722
        $user3 = self::getDataGenerator()->create_user();
1723
 
1724
        $course1 = $this->getDataGenerator()->create_course();
1725
 
1726
        // Create a group with a linked conversation and a valid image.
1727
        $this->setAdminUser();
1728
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1729
        $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1730
        $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
1731
        $group1 = $this->getDataGenerator()->create_group([
1732
            'courseid' => $course1->id,
1733
            'enablemessaging' => 1,
1734
            'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
1735
        ]);
1736
 
1737
        // Add users to group1.
1738
        $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1739
        $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
1740
 
1741
        // Verify the group with the image works as expected.
1742
        $conversations = api::get_conversations($user1->id);
1743
        $this->assertEquals(2, $conversations[0]->membercount);
1744
        $this->assertEquals($course1->shortname, $conversations[0]->subname);
1745
        $groupimageurl = get_group_picture_url($group1, $group1->courseid, true);
1746
        $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
1747
 
1748
        // Create a group with a linked conversation and without any image.
1749
        $group2 = $this->getDataGenerator()->create_group([
1750
            'courseid' => $course1->id,
1751
            'enablemessaging' => 1,
1752
        ]);
1753
 
1754
        // Add users to group2.
1755
        $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1756
        $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id));
1757
 
1758
        // Verify the group without any image works as expected too.
1759
        $conversations = api::get_conversations($user3->id);
1760
        // Consider first conversations is self-conversation.
1761
        $this->assertEquals(2, $conversations[0]->membercount);
1762
        $this->assertEquals($course1->shortname, $conversations[0]->subname);
1763
        $this->assertEquals('https://www.example.com/moodle/theme/image.php/boost/core/1/g/g1', $conversations[0]->imageurl);
1764
 
1765
        // Now, disable the conversation linked to the group and verify it's no longer returned.
1766
        $DB->set_field('message_conversations', 'enabled', 0, ['id' => $conversations[0]->id]);
1767
        $conversations = api::get_conversations($user3->id);
1768
        $this->assertCount(1, $conversations);
1769
    }
1770
 
1771
   /**
1772
    * The data provider for get_conversations_mixed.
1773
    *
1774
    * This provides sets of data to for testing.
1775
    * @return array
1776
    */
1777
   public function get_conversations_mixed_provider() {
1778
       return array(
1779
            'Test that conversations with messages contacts is correctly ordered.' => array(
1780
                'users' => array(
1781
                    'user1',
1782
                    'user2',
1783
                    'user3',
1784
                ),
1785
                'contacts' => array(
1786
                ),
1787
                'messages' => array(
1788
                    array(
1789
                        'from'          => 'user1',
1790
                        'to'            => 'user2',
1791
                        'state'         => 'unread',
1792
                        'subject'       => 'S1',
1793
                    ),
1794
                    array(
1795
                        'from'          => 'user2',
1796
                        'to'            => 'user1',
1797
                        'state'         => 'unread',
1798
                        'subject'       => 'S2',
1799
                    ),
1800
                    array(
1801
                        'from'          => 'user1',
1802
                        'to'            => 'user2',
1803
                        'state'         => 'unread',
1804
                        'timecreated'   => 0,
1805
                        'subject'       => 'S3',
1806
                    ),
1807
                    array(
1808
                        'from'          => 'user1',
1809
                        'to'            => 'user3',
1810
                        'state'         => 'read',
1811
                        'timemodifier'  => 1,
1812
                        'subject'       => 'S4',
1813
                    ),
1814
                    array(
1815
                        'from'          => 'user3',
1816
                        'to'            => 'user1',
1817
                        'state'         => 'read',
1818
                        'timemodifier'  => 1,
1819
                        'subject'       => 'S5',
1820
                    ),
1821
                    array(
1822
                        'from'          => 'user1',
1823
                        'to'            => 'user3',
1824
                        'state'         => 'read',
1825
                        'timecreated'   => 0,
1826
                        'subject'       => 'S6',
1827
                    ),
1828
                ),
1829
                'expectations' => array(
1830
                    'user1' => array(
1831
                        // User1 has conversed most recently with user3. The most recent message is M5.
1832
                        array(
1833
                            'messageposition'   => 0,
1834
                            'with'              => 'user3',
1835
                            'subject'           => '<p>S5</p>',
1836
                            'unreadcount'       => 0,
1837
                        ),
1838
                        // User1 has also conversed with user2. The most recent message is S2.
1839
                        array(
1840
                            'messageposition'   => 1,
1841
                            'with'              => 'user2',
1842
                            'subject'           => '<p>S2</p>',
1843
                            'unreadcount'       => 1,
1844
                        ),
1845
                    ),
1846
                    'user2' => array(
1847
                        // User2 has only conversed with user1. Their most recent shared message was S2.
1848
                        array(
1849
                            'messageposition'   => 0,
1850
                            'with'              => 'user1',
1851
                            'subject'           => '<p>S2</p>',
1852
                            'unreadcount'       => 2,
1853
                        ),
1854
                    ),
1855
                    'user3' => array(
1856
                        // User3 has only conversed with user1. Their most recent shared message was S5.
1857
                        array(
1858
                            'messageposition'   => 0,
1859
                            'with'              => 'user1',
1860
                            'subject'           => '<p>S5</p>',
1861
                            'unreadcount'       => 0,
1862
                        ),
1863
                    ),
1864
                ),
1865
            ),
1866
            'Test conversations with a single user, where some messages are read and some are not.' => array(
1867
                'users' => array(
1868
                    'user1',
1869
                    'user2',
1870
                ),
1871
                'contacts' => array(
1872
                ),
1873
                'messages' => array(
1874
                    array(
1875
                        'from'          => 'user1',
1876
                        'to'            => 'user2',
1877
                        'state'         => 'read',
1878
                        'subject'       => 'S1',
1879
                    ),
1880
                    array(
1881
                        'from'          => 'user2',
1882
                        'to'            => 'user1',
1883
                        'state'         => 'read',
1884
                        'subject'       => 'S2',
1885
                    ),
1886
                    array(
1887
                        'from'          => 'user1',
1888
                        'to'            => 'user2',
1889
                        'state'         => 'unread',
1890
                        'timemodifier'  => 1,
1891
                        'subject'       => 'S3',
1892
                    ),
1893
                    array(
1894
                        'from'          => 'user1',
1895
                        'to'            => 'user2',
1896
                        'state'         => 'unread',
1897
                        'timemodifier'  => 1,
1898
                        'subject'       => 'S4',
1899
                    ),
1900
                ),
1901
                'expectations' => array(
1902
                    // The most recent message between user1 and user2 was S4.
1903
                    'user1' => array(
1904
                        array(
1905
                            'messageposition'   => 0,
1906
                            'with'              => 'user2',
1907
                            'subject'           => '<p>S4</p>',
1908
                            'unreadcount'       => 0,
1909
                        ),
1910
                    ),
1911
                    'user2' => array(
1912
                        // The most recent message between user1 and user2 was S4.
1913
                        array(
1914
                            'messageposition'   => 0,
1915
                            'with'              => 'user1',
1916
                            'subject'           => '<p>S4</p>',
1917
                            'unreadcount'       => 2,
1918
                        ),
1919
                    ),
1920
                ),
1921
            ),
1922
            'Test conversations with a single user, where some messages are read and some are not, and messages ' .
1923
            'are out of order' => array(
1924
            // This can happen through a combination of factors including multi-master DB replication with messages
1925
            // read somehow (e.g. API).
1926
                'users' => array(
1927
                    'user1',
1928
                    'user2',
1929
                ),
1930
                'contacts' => array(
1931
                ),
1932
                'messages' => array(
1933
                    array(
1934
                        'from'          => 'user1',
1935
                        'to'            => 'user2',
1936
                        'state'         => 'read',
1937
                        'subject'       => 'S1',
1938
                        'timemodifier'  => 1,
1939
                    ),
1940
                    array(
1941
                        'from'          => 'user2',
1942
                        'to'            => 'user1',
1943
                        'state'         => 'read',
1944
                        'subject'       => 'S2',
1945
                        'timemodifier'  => 2,
1946
                    ),
1947
                    array(
1948
                        'from'          => 'user1',
1949
                        'to'            => 'user2',
1950
                        'state'         => 'unread',
1951
                        'subject'       => 'S3',
1952
                    ),
1953
                    array(
1954
                        'from'          => 'user1',
1955
                        'to'            => 'user2',
1956
                        'state'         => 'unread',
1957
                        'subject'       => 'S4',
1958
                    ),
1959
                ),
1960
                'expectations' => array(
1961
                    // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
1962
                    'user1' => array(
1963
                        array(
1964
                            'messageposition'   => 0,
1965
                            'with'              => 'user2',
1966
                            'subject'           => '<p>S2</p>',
1967
                            'unreadcount'       => 0,
1968
                        ),
1969
                    ),
1970
                    'user2' => array(
1971
                        array(
1972
                            'messageposition'   => 0,
1973
                            'with'              => 'user1',
1974
                            'subject'           => '<p>S2</p>',
1975
                            'unreadcount'       => 2
1976
                        ),
1977
                    ),
1978
                ),
1979
            ),
1980
            'Test unread message count is correct for both users' => array(
1981
                'users' => array(
1982
                    'user1',
1983
                    'user2',
1984
                ),
1985
                'contacts' => array(
1986
                ),
1987
                'messages' => array(
1988
                    array(
1989
                        'from'          => 'user1',
1990
                        'to'            => 'user2',
1991
                        'state'         => 'read',
1992
                        'subject'       => 'S1',
1993
                        'timemodifier'  => 1,
1994
                    ),
1995
                    array(
1996
                        'from'          => 'user2',
1997
                        'to'            => 'user1',
1998
                        'state'         => 'read',
1999
                        'subject'       => 'S2',
2000
                        'timemodifier'  => 2,
2001
                    ),
2002
                    array(
2003
                        'from'          => 'user1',
2004
                        'to'            => 'user2',
2005
                        'state'         => 'read',
2006
                        'subject'       => 'S3',
2007
                        'timemodifier'  => 3,
2008
                    ),
2009
                    array(
2010
                        'from'          => 'user1',
2011
                        'to'            => 'user2',
2012
                        'state'         => 'read',
2013
                        'subject'       => 'S4',
2014
                        'timemodifier'  => 4,
2015
                    ),
2016
                    array(
2017
                        'from'          => 'user1',
2018
                        'to'            => 'user2',
2019
                        'state'         => 'unread',
2020
                        'subject'       => 'S5',
2021
                        'timemodifier'  => 5,
2022
                    ),
2023
                    array(
2024
                        'from'          => 'user2',
2025
                        'to'            => 'user1',
2026
                        'state'         => 'unread',
2027
                        'subject'       => 'S6',
2028
                        'timemodifier'  => 6,
2029
                    ),
2030
                    array(
2031
                        'from'          => 'user1',
2032
                        'to'            => 'user2',
2033
                        'state'         => 'unread',
2034
                        'subject'       => 'S7',
2035
                        'timemodifier'  => 7,
2036
                    ),
2037
                    array(
2038
                        'from'          => 'user1',
2039
                        'to'            => 'user2',
2040
                        'state'         => 'unread',
2041
                        'subject'       => 'S8',
2042
                        'timemodifier'  => 8,
2043
                    ),
2044
                ),
2045
                'expectations' => array(
2046
                    // The most recent message between user1 and user2 was S2, even though later IDs have not been read.
2047
                    'user1' => array(
2048
                        array(
2049
                            'messageposition'   => 0,
2050
                            'with'              => 'user2',
2051
                            'subject'           => '<p>S8</p>',
2052
                            'unreadcount'       => 1,
2053
                        ),
2054
                    ),
2055
                    'user2' => array(
2056
                        array(
2057
                            'messageposition'   => 0,
2058
                            'with'              => 'user1',
2059
                            'subject'           => '<p>S8</p>',
2060
                            'unreadcount'       => 3,
2061
                        ),
2062
                    ),
2063
                ),
2064
            ),
2065
        );
2066
    }
2067
 
2068
    /**
2069
     * Test that creation can't create the same conversation twice for 1:1 conversations.
2070
     */
2071
    public function test_create_conversation_duplicate_conversations() {
2072
        global $DB;
2073
        $user1 = $this::getDataGenerator()->create_user();
2074
 
2075
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2076
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_SELF, [$user1->id]);
2077
 
2078
        $convhash = helper::get_conversation_hash([$user1->id]);
2079
        $countconversations = $DB->count_records('message_conversations', ['convhash' => $convhash]);
2080
        $this->assertEquals(1, $countconversations);
2081
        $this->assertNotEmpty($conversation = api::get_self_conversation($user1->id));
2082
    }
2083
 
2084
    /**
2085
     * Test get_conversations with a mixture of messages.
2086
     *
2087
     * @dataProvider get_conversations_mixed_provider
2088
     * @param array $usersdata The list of users to create for this test.
2089
     * @param array $messagesdata The list of messages to create.
2090
     * @param array $expectations The list of expected outcomes.
2091
     */
2092
    public function test_get_conversations_mixed($usersdata, $contacts, $messagesdata, $expectations) {
2093
        global $DB;
2094
 
2095
        // Create all of the users.
2096
        $users = array();
2097
        foreach ($usersdata as $username) {
2098
            $users[$username] = $this->getDataGenerator()->create_user(array('username' => $username));
2099
        }
2100
 
2101
        foreach ($contacts as $username => $contact) {
2102
            foreach ($contact as $contactname => $blocked) {
2103
                $record = new \stdClass();
2104
                $record->userid     = $users[$username]->id;
2105
                $record->contactid  = $users[$contactname]->id;
2106
                $record->blocked    = $blocked;
2107
                $record->id = $DB->insert_record('message_contacts', $record);
2108
            }
2109
        }
2110
 
2111
        $defaulttimecreated = time();
2112
        foreach ($messagesdata as $messagedata) {
2113
            $from       = $users[$messagedata['from']];
2114
            $to         = $users[$messagedata['to']];
2115
            $subject    = $messagedata['subject'];
2116
 
2117
            if (isset($messagedata['state']) && $messagedata['state'] == 'unread') {
2118
                $messageid = $this->send_fake_message($from, $to, $subject);
2119
            } else {
2120
                // If there is no state, or the state is not 'unread', assume the message is read.
2121
                $messageid = message_post_message($from, $to, $subject, FORMAT_PLAIN);
2122
            }
2123
 
2124
            $updatemessage = new \stdClass();
2125
            $updatemessage->id = $messageid;
2126
            if (isset($messagedata['timecreated'])) {
2127
                $updatemessage->timecreated = $messagedata['timecreated'];
2128
            } else if (isset($messagedata['timemodifier'])) {
2129
                $updatemessage->timecreated = $defaulttimecreated + $messagedata['timemodifier'];
2130
            } else {
2131
                $updatemessage->timecreated = $defaulttimecreated;
2132
            }
2133
 
2134
            $DB->update_record('messages', $updatemessage);
2135
        }
2136
 
2137
        foreach ($expectations as $username => $data) {
2138
            // Get the recent conversations for the specified user.
2139
            $user = $users[$username];
2140
            $conversations = array_values(api::get_conversations($user->id));
2141
            foreach ($data as $expectation) {
2142
                $otheruser = $users[$expectation['with']];
2143
                $conversation = $conversations[$expectation['messageposition']];
2144
                $this->assertEquals($otheruser->id, $conversation->members[$otheruser->id]->id);
2145
                $this->assertEquals($expectation['subject'], $conversation->messages[0]->text);
2146
                $this->assertEquals($expectation['unreadcount'], $conversation->unreadcount);
2147
            }
2148
        }
2149
    }
2150
 
2151
    /**
2152
     * Tests retrieving user contacts.
2153
     */
2154
    public function test_get_user_contacts() {
2155
        // Create some users.
2156
        $user1 = self::getDataGenerator()->create_user();
2157
 
2158
        // Set as the user.
2159
        $this->setUser($user1);
2160
 
2161
        $user2 = new \stdClass();
2162
        $user2->firstname = 'User';
2163
        $user2->lastname = 'A';
2164
        $user2 = self::getDataGenerator()->create_user($user2);
2165
 
2166
        $user3 = new \stdClass();
2167
        $user3->firstname = 'User';
2168
        $user3->lastname = 'B';
2169
        $user3 = self::getDataGenerator()->create_user($user3);
2170
 
2171
        $user4 = new \stdClass();
2172
        $user4->firstname = 'User';
2173
        $user4->lastname = 'C';
2174
        $user4 = self::getDataGenerator()->create_user($user4);
2175
 
2176
        $user5 = new \stdClass();
2177
        $user5->firstname = 'User';
2178
        $user5->lastname = 'D';
2179
        $user5 = self::getDataGenerator()->create_user($user5);
2180
 
2181
        // Add some users as contacts.
2182
        api::add_contact($user1->id, $user2->id);
2183
        api::add_contact($user1->id, $user3->id);
2184
        api::add_contact($user1->id, $user4->id);
2185
 
2186
        // Retrieve the contacts.
2187
        $contacts = api::get_user_contacts($user1->id);
2188
 
2189
        // Confirm the data is correct.
2190
        $this->assertEquals(3, count($contacts));
2191
 
2192
        ksort($contacts);
2193
 
2194
        $contact1 = array_shift($contacts);
2195
        $contact2 = array_shift($contacts);
2196
        $contact3 = array_shift($contacts);
2197
 
2198
        $this->assertEquals($user2->id, $contact1->id);
2199
        $this->assertEquals(fullname($user2), $contact1->fullname);
2200
        $this->assertTrue($contact1->iscontact);
2201
 
2202
        $this->assertEquals($user3->id, $contact2->id);
2203
        $this->assertEquals(fullname($user3), $contact2->fullname);
2204
        $this->assertTrue($contact2->iscontact);
2205
 
2206
        $this->assertEquals($user4->id, $contact3->id);
2207
        $this->assertEquals(fullname($user4), $contact3->fullname);
2208
        $this->assertTrue($contact3->iscontact);
2209
    }
2210
 
2211
    /**
2212
     * Tests retrieving conversation messages.
2213
     */
2214
    public function test_get_conversation_messages() {
2215
        // Create some users.
2216
        $user1 = self::getDataGenerator()->create_user();
2217
        $user2 = self::getDataGenerator()->create_user();
2218
 
2219
        // Create conversation.
2220
        $conversation = api::create_conversation(
2221
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2222
            [$user1->id, $user2->id]
2223
        );
2224
 
2225
        // The person doing the search.
2226
        $this->setUser($user1);
2227
 
2228
        // Send some messages back and forth.
2229
        $time = 1;
2230
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2231
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2232
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2233
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2234
 
2235
        // Retrieve the messages.
2236
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id);
2237
 
2238
        // Confirm the conversation id is correct.
2239
        $this->assertEquals($conversation->id, $convmessages['id']);
2240
 
2241
        // Confirm the message data is correct.
2242
        $messages = $convmessages['messages'];
2243
        $this->assertEquals(4, count($messages));
2244
        $message1 = $messages[0];
2245
        $message2 = $messages[1];
2246
        $message3 = $messages[2];
2247
        $message4 = $messages[3];
2248
 
2249
        $this->assertEquals($user1->id, $message1->useridfrom);
2250
        $this->assertStringContainsString('Yo!', $message1->text);
2251
 
2252
        $this->assertEquals($user2->id, $message2->useridfrom);
2253
        $this->assertStringContainsString('Sup mang?', $message2->text);
2254
 
2255
        $this->assertEquals($user1->id, $message3->useridfrom);
2256
        $this->assertStringContainsString('Writing PHPUnit tests!', $message3->text);
2257
 
2258
        $this->assertEquals($user1->id, $message4->useridfrom);
2259
        $this->assertStringContainsString('Word.', $message4->text);
2260
 
2261
        // Confirm the members data is correct.
2262
        $members = $convmessages['members'];
2263
        $this->assertEquals(2, count($members));
2264
    }
2265
 
2266
    /**
2267
     * Tests retrieving group conversation messages.
2268
     */
2269
    public function test_get_group_conversation_messages() {
2270
        // Create some users.
2271
        $user1 = self::getDataGenerator()->create_user();
2272
        $user2 = self::getDataGenerator()->create_user();
2273
        $user3 = self::getDataGenerator()->create_user();
2274
        $user4 = self::getDataGenerator()->create_user();
2275
 
2276
        // Create group conversation.
2277
        $conversation = api::create_conversation(
2278
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2279
            [$user1->id, $user2->id, $user3->id, $user4->id]
2280
        );
2281
 
2282
        // The person doing the search.
2283
        $this->setUser($user1);
2284
 
2285
        // Send some messages back and forth.
2286
        $time = 1;
2287
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2288
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2289
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2290
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2291
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Yeah!', $time + 5);
2292
 
2293
        // Retrieve the messages.
2294
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id);
2295
 
2296
        // Confirm the conversation id is correct.
2297
        $this->assertEquals($conversation->id, $convmessages['id']);
2298
 
2299
        // Confirm the message data is correct.
2300
        $messages = $convmessages['messages'];
2301
        $this->assertEquals(5, count($messages));
2302
 
2303
        $message1 = $messages[0];
2304
        $message2 = $messages[1];
2305
        $message3 = $messages[2];
2306
        $message4 = $messages[3];
2307
        $message5 = $messages[4];
2308
 
2309
        $this->assertEquals($user1->id, $message1->useridfrom);
2310
        $this->assertStringContainsString('Yo!', $message1->text);
2311
 
2312
        $this->assertEquals($user2->id, $message2->useridfrom);
2313
        $this->assertStringContainsString('Sup mang?', $message2->text);
2314
 
2315
        $this->assertEquals($user3->id, $message3->useridfrom);
2316
        $this->assertStringContainsString('Writing PHPUnit tests!', $message3->text);
2317
 
2318
        $this->assertEquals($user1->id, $message4->useridfrom);
2319
        $this->assertStringContainsString('Word.', $message4->text);
2320
 
2321
        $this->assertEquals($user2->id, $message5->useridfrom);
2322
        $this->assertStringContainsString('Yeah!', $message5->text);
2323
 
2324
        // Confirm the members data is correct.
2325
        $members = $convmessages['members'];
2326
        $this->assertEquals(3, count($members));
2327
    }
2328
 
2329
    /**
2330
     * Test verifying the sorting param for get_conversation_messages is respected().
2331
     */
2332
    public function test_get_conversation_messages_sorting() {
2333
        // Create some users.
2334
        $user1 = self::getDataGenerator()->create_user();
2335
        $user2 = self::getDataGenerator()->create_user();
2336
        $user3 = self::getDataGenerator()->create_user();
2337
 
2338
        // Create conversations - 1 group and 1 individual.
2339
        $conversation = api::create_conversation(
2340
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
2341
            [$user1->id, $user2->id]
2342
        );
2343
        $conversation2 = api::create_conversation(
2344
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2345
            [$user1->id, $user2->id, $user3->id]
2346
        );
2347
 
2348
        // Send some messages back and forth.
2349
        $time = 1;
2350
        $m1id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2351
        $m2id = testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2352
        $m3id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2353
        $m4id = testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Word.', $time + 4);
2354
 
2355
        $gm1id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Yo!', $time + 1);
2356
        $gm2id = testhelper::send_fake_message_to_conversation($user2, $conversation2->id, 'Sup mang?', $time + 2);
2357
        $gm3id = testhelper::send_fake_message_to_conversation($user3, $conversation2->id, 'Writing PHPUnit tests!', $time + 3);
2358
        $gm4id = testhelper::send_fake_message_to_conversation($user1, $conversation2->id, 'Word.', $time + 4);
2359
 
2360
        // The person doing the search.
2361
        $this->setUser($user1);
2362
 
2363
        // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2364
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id);
2365
        $messages = $convmessages['messages'];
2366
        $this->assertEquals($m1id, $messages[0]->id);
2367
        $this->assertEquals($m2id, $messages[1]->id);
2368
        $this->assertEquals($m3id, $messages[2]->id);
2369
        $this->assertEquals($m4id, $messages[3]->id);
2370
 
2371
        // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2372
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated DESC');
2373
        $messages = $convmessages['messages'];
2374
        $this->assertEquals($m1id, $messages[3]->id);
2375
        $this->assertEquals($m2id, $messages[2]->id);
2376
        $this->assertEquals($m3id, $messages[1]->id);
2377
        $this->assertEquals($m4id, $messages[0]->id);
2378
 
2379
        // Retrieve the messages using default sort ('timecreated ASC') and verify ordering.
2380
        $convmessages = api::get_conversation_messages($user1->id, $conversation2->id);
2381
        $messages = $convmessages['messages'];
2382
        $this->assertEquals($gm1id, $messages[0]->id);
2383
        $this->assertEquals($gm2id, $messages[1]->id);
2384
        $this->assertEquals($gm3id, $messages[2]->id);
2385
        $this->assertEquals($gm4id, $messages[3]->id);
2386
 
2387
        // Retrieve the messages without specifying DESC sort ordering, and verify ordering.
2388
        $convmessages = api::get_conversation_messages($user1->id, $conversation2->id, 0, 0, 'timecreated DESC');
2389
        $messages = $convmessages['messages'];
2390
        $this->assertEquals($gm1id, $messages[3]->id);
2391
        $this->assertEquals($gm2id, $messages[2]->id);
2392
        $this->assertEquals($gm3id, $messages[1]->id);
2393
        $this->assertEquals($gm4id, $messages[0]->id);
2394
    }
2395
 
2396
    /**
2397
     * Test retrieving conversation messages by providing a minimum timecreated value.
2398
     */
2399
    public function test_get_conversation_messages_time_from_only() {
2400
        // Create some users.
2401
        $user1 = self::getDataGenerator()->create_user();
2402
        $user2 = self::getDataGenerator()->create_user();
2403
        $user3 = self::getDataGenerator()->create_user();
2404
        $user4 = self::getDataGenerator()->create_user();
2405
 
2406
        // Create group conversation.
2407
        $conversation = api::create_conversation(
2408
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2409
            [$user1->id, $user2->id, $user3->id, $user4->id]
2410
        );
2411
 
2412
        // The person doing the search.
2413
        $this->setUser($user1);
2414
 
2415
        // Send some messages back and forth.
2416
        $time = 1;
2417
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2418
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2419
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2420
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2421
 
2422
        // Retrieve the messages from $time, which should be all of them.
2423
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC', $time);
2424
 
2425
        // Confirm the conversation id is correct.
2426
        $this->assertEquals($conversation->id, $convmessages['id']);
2427
 
2428
        // Confirm the message data is correct.
2429
        $messages = $convmessages['messages'];
2430
        $this->assertEquals(4, count($messages));
2431
 
2432
        $message1 = $messages[0];
2433
        $message2 = $messages[1];
2434
        $message3 = $messages[2];
2435
        $message4 = $messages[3];
2436
 
2437
        $this->assertStringContainsString('Message 1', $message1->text);
2438
        $this->assertStringContainsString('Message 2', $message2->text);
2439
        $this->assertStringContainsString('Message 3', $message3->text);
2440
        $this->assertStringContainsString('Message 4', $message4->text);
2441
 
2442
        // Confirm the members data is correct.
2443
        $members = $convmessages['members'];
2444
        $this->assertEquals(3, count($members));
2445
 
2446
        // Retrieve the messages from $time + 3, which should only be the 2 last messages.
2447
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2448
            'timecreated ASC', $time + 3);
2449
 
2450
        // Confirm the conversation id is correct.
2451
        $this->assertEquals($conversation->id, $convmessages['id']);
2452
 
2453
        // Confirm the message data is correct.
2454
        $messages = $convmessages['messages'];
2455
        $this->assertEquals(2, count($messages));
2456
 
2457
        $message1 = $messages[0];
2458
        $message2 = $messages[1];
2459
 
2460
        $this->assertStringContainsString('Message 3', $message1->text);
2461
        $this->assertStringContainsString('Message 4', $message2->text);
2462
 
2463
        // Confirm the members data is correct.
2464
        $members = $convmessages['members'];
2465
        $this->assertEquals(2, count($members));
2466
    }
2467
 
2468
    /**
2469
     * Test retrieving conversation messages by providing a maximum timecreated value.
2470
     */
2471
    public function test_get_conversation_messages_time_to_only() {
2472
        // Create some users.
2473
        $user1 = self::getDataGenerator()->create_user();
2474
        $user2 = self::getDataGenerator()->create_user();
2475
        $user3 = self::getDataGenerator()->create_user();
2476
        $user4 = self::getDataGenerator()->create_user();
2477
 
2478
        // Create group conversation.
2479
        $conversation = api::create_conversation(
2480
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2481
            [$user1->id, $user2->id, $user3->id, $user4->id]
2482
        );
2483
 
2484
        // The person doing the search.
2485
        $this->setUser($user1);
2486
 
2487
        // Send some messages back and forth.
2488
        $time = 1;
2489
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2490
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2491
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2492
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2493
 
2494
        // Retrieve the messages up until $time + 4, which should be all of them.
2495
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2496
            0, $time + 4);
2497
 
2498
        // Confirm the conversation id is correct.
2499
        $this->assertEquals($conversation->id, $convmessages['id']);
2500
 
2501
        // Confirm the message data is correct.
2502
        $messages = $convmessages['messages'];
2503
        $this->assertEquals(4, count($messages));
2504
 
2505
        $message1 = $messages[0];
2506
        $message2 = $messages[1];
2507
        $message3 = $messages[2];
2508
        $message4 = $messages[3];
2509
 
2510
        $this->assertStringContainsString('Message 1', $message1->text);
2511
        $this->assertStringContainsString('Message 2', $message2->text);
2512
        $this->assertStringContainsString('Message 3', $message3->text);
2513
        $this->assertStringContainsString('Message 4', $message4->text);
2514
 
2515
        // Confirm the members data is correct.
2516
        $members = $convmessages['members'];
2517
        $this->assertEquals(3, count($members));
2518
 
2519
        // Retrieve the messages up until $time + 2, which should be the first two.
2520
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0, 'timecreated ASC',
2521
            0, $time + 2);
2522
 
2523
        // Confirm the conversation id is correct.
2524
        $this->assertEquals($conversation->id, $convmessages['id']);
2525
 
2526
        // Confirm the message data is correct.
2527
        $messages = $convmessages['messages'];
2528
        $this->assertEquals(2, count($messages));
2529
 
2530
        $message1 = $messages[0];
2531
        $message2 = $messages[1];
2532
 
2533
        $this->assertStringContainsString('Message 1', $message1->text);
2534
        $this->assertStringContainsString('Message 2', $message2->text);
2535
 
2536
        // Confirm the members data is correct.
2537
        $members = $convmessages['members'];
2538
        $this->assertEquals(2, count($members));
2539
    }
2540
 
2541
    /**
2542
     * Test retrieving conversation messages by providing a minimum and maximum timecreated value.
2543
     */
2544
    public function test_get_conversation_messages_time_from_and_to() {
2545
        // Create some users.
2546
        $user1 = self::getDataGenerator()->create_user();
2547
        $user2 = self::getDataGenerator()->create_user();
2548
        $user3 = self::getDataGenerator()->create_user();
2549
        $user4 = self::getDataGenerator()->create_user();
2550
 
2551
        // Create group conversation.
2552
        $conversation = api::create_conversation(
2553
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2554
            [$user1->id, $user2->id, $user3->id, $user4->id]
2555
        );
2556
 
2557
        // The person doing the search.
2558
        $this->setUser($user1);
2559
 
2560
        // Send some messages back and forth.
2561
        $time = 1;
2562
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2563
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2564
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2565
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2566
 
2567
        // Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
2568
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0,
2569
            'timecreated ASC', $time + 2, $time + 3);
2570
 
2571
        // Confirm the conversation id is correct.
2572
        $this->assertEquals($conversation->id, $convmessages['id']);
2573
 
2574
        // Confirm the message data is correct.
2575
        $messages = $convmessages['messages'];
2576
        $this->assertEquals(2, count($messages));
2577
 
2578
        $message1 = $messages[0];
2579
        $message2 = $messages[1];
2580
 
2581
        $this->assertStringContainsString('Message 2', $message1->text);
2582
        $this->assertStringContainsString('Message 3', $message2->text);
2583
 
2584
        // Confirm the members data is correct.
2585
        $members = $convmessages['members'];
2586
        $this->assertEquals(2, count($members));
2587
    }
2588
 
2589
 
2590
    /**
2591
     * Test retrieving conversation messages by providing a limitfrom value.
2592
     */
2593
    public function test_get_conversation_messages_limitfrom_only() {
2594
        // Create some users.
2595
        $user1 = self::getDataGenerator()->create_user();
2596
        $user2 = self::getDataGenerator()->create_user();
2597
        $user3 = self::getDataGenerator()->create_user();
2598
        $user4 = self::getDataGenerator()->create_user();
2599
 
2600
        // Create group conversation.
2601
        $conversation = api::create_conversation(
2602
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2603
            [$user1->id, $user2->id, $user3->id, $user4->id]
2604
        );
2605
 
2606
        // The person doing the search.
2607
        $this->setUser($user1);
2608
 
2609
        // Send some messages back and forth.
2610
        $time = 1;
2611
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2612
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2613
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2614
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2615
 
2616
        // Retrieve the messages from $time, which should be all of them.
2617
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 2);
2618
 
2619
        // Confirm the conversation id is correct.
2620
        $messages = $convmessages['messages'];
2621
        $this->assertEquals($conversation->id, $convmessages['id']);
2622
 
2623
        // Confirm the message data is correct.
2624
        $this->assertEquals(2, count($messages));
2625
 
2626
        $message1 = $messages[0];
2627
        $message2 = $messages[1];
2628
 
2629
        $this->assertStringContainsString('Message 3', $message1->text);
2630
        $this->assertStringContainsString('Message 4', $message2->text);
2631
 
2632
        // Confirm the members data is correct.
2633
        $members = $convmessages['members'];
2634
        $this->assertEquals(2, count($members));
2635
    }
2636
 
2637
    /**
2638
     * Test retrieving conversation messages by providing a limitnum value.
2639
     */
2640
    public function test_get_conversation_messages_limitnum() {
2641
        // Create some users.
2642
        $user1 = self::getDataGenerator()->create_user();
2643
        $user2 = self::getDataGenerator()->create_user();
2644
        $user3 = self::getDataGenerator()->create_user();
2645
        $user4 = self::getDataGenerator()->create_user();
2646
 
2647
        // Create group conversation.
2648
        $conversation = api::create_conversation(
2649
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2650
            [$user1->id, $user2->id, $user3->id, $user4->id]
2651
        );
2652
 
2653
        // The person doing the search.
2654
        $this->setUser($user1);
2655
 
2656
        // Send some messages back and forth.
2657
        $time = 1;
2658
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
2659
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
2660
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
2661
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
2662
 
2663
        // Retrieve the messages from $time, which should be all of them.
2664
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 2, 1);
2665
 
2666
        // Confirm the conversation id is correct.
2667
        $messages = $convmessages['messages'];
2668
        $this->assertEquals($conversation->id, $convmessages['id']);
2669
 
2670
        // Confirm the message data is correct.
2671
        $messages = $convmessages['messages'];
2672
        $this->assertEquals(1, count($messages));
2673
 
2674
        $message1 = $messages[0];
2675
 
2676
        $this->assertStringContainsString('Message 3', $message1->text);
2677
 
2678
        // Confirm the members data is correct.
2679
        $members = $convmessages['members'];
2680
        $this->assertEquals(1, count($members));
2681
    }
2682
 
2683
    /**
2684
     * Tests retrieving most recent conversation message.
2685
     */
2686
    public function test_get_most_recent_conversation_message() {
2687
        // Create some users.
2688
        $user1 = self::getDataGenerator()->create_user();
2689
        $user2 = self::getDataGenerator()->create_user();
2690
        $user3 = self::getDataGenerator()->create_user();
2691
 
2692
        // Create group conversation.
2693
        $conversation = api::create_conversation(
2694
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
2695
            [$user1->id, $user2->id, $user3->id]
2696
        );
2697
 
2698
        // The person getting the most recent conversation message.
2699
        $this->setUser($user1);
2700
 
2701
        // Send some messages back and forth.
2702
        $time = 1;
2703
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Yo!', $time + 1);
2704
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Sup mang?', $time + 2);
2705
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Writing PHPUnit tests!', $time + 3);
2706
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Word.', $time + 4);
2707
 
2708
        // Retrieve the most recent messages.
2709
        $message = api::get_most_recent_conversation_message($conversation->id, $user1->id);
2710
 
2711
        // Check the results are correct.
2712
        $this->assertEquals($user2->id, $message->useridfrom);
2713
        $this->assertStringContainsString('Word.', $message->text);
2714
    }
2715
 
2716
    /**
2717
     * Tests checking if a user can mark all messages as read.
2718
     */
2719
    public function test_can_mark_all_messages_as_read() {
2720
        // Set as the admin.
2721
        $this->setAdminUser();
2722
 
2723
        // Create some users.
2724
        $user1 = self::getDataGenerator()->create_user();
2725
        $user2 = self::getDataGenerator()->create_user();
2726
        $user3 = self::getDataGenerator()->create_user();
2727
 
2728
        // Send some messages back and forth.
2729
        $time = 1;
2730
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2731
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2732
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2733
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2734
 
2735
        $conversationid = api::get_conversation_between_users([$user1->id, $user2->id]);
2736
 
2737
        // The admin can do anything.
2738
        $this->assertTrue(api::can_mark_all_messages_as_read($user1->id, $conversationid));
2739
 
2740
        // Set as the user 1.
2741
        $this->setUser($user1);
2742
 
2743
        // The user can mark the messages as he is in the conversation.
2744
        $this->assertTrue(api::can_mark_all_messages_as_read($user1->id, $conversationid));
2745
 
2746
        // User 1 can not mark the messages read for user 2.
2747
        $this->assertFalse(api::can_mark_all_messages_as_read($user2->id, $conversationid));
2748
 
2749
        // This user is not a part of the conversation.
2750
        $this->assertFalse(api::can_mark_all_messages_as_read($user3->id, $conversationid));
2751
    }
2752
 
2753
    /**
2754
     * Tests checking if a user can delete a conversation.
2755
     */
2756
    public function test_can_delete_conversation() {
2757
        // Set as the admin.
2758
        $this->setAdminUser();
2759
 
2760
        // Create some users.
2761
        $user1 = self::getDataGenerator()->create_user();
2762
        $user2 = self::getDataGenerator()->create_user();
2763
 
2764
        // Send some messages back and forth.
2765
        $time = 1;
2766
        $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2767
        $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2768
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2769
        $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2770
 
2771
        $conversationid = api::get_conversation_between_users([$user1->id, $user2->id]);
2772
 
2773
        // The admin can do anything.
2774
        $this->assertTrue(api::can_delete_conversation($user1->id, $conversationid));
2775
 
2776
        // Set as the user 1.
2777
        $this->setUser($user1);
2778
 
2779
        // They can delete their own messages.
2780
        $this->assertTrue(api::can_delete_conversation($user1->id, $conversationid));
2781
 
2782
        // They can't delete someone elses.
2783
        $this->assertFalse(api::can_delete_conversation($user2->id, $conversationid));
2784
    }
2785
 
2786
    /**
2787
     * Tests deleting a conversation by conversation id.
2788
     */
2789
    public function test_delete_conversation_by_id() {
2790
        global $DB;
2791
 
2792
        // Create some users.
2793
        $user1 = self::getDataGenerator()->create_user();
2794
        $user2 = self::getDataGenerator()->create_user();
2795
 
2796
        // The person doing the search.
2797
        $this->setUser($user1);
2798
 
2799
        // Get self-conversation.
2800
        $sc1 = api::get_self_conversation($user1->id);
2801
        $sc2 = api::get_self_conversation($user2->id);
2802
 
2803
        // Send some messages back and forth.
2804
        $time = 1;
2805
        $m1id = $this->send_fake_message($user1, $user2, 'Yo!', 0, $time + 1);
2806
        $m2id = $this->send_fake_message($user2, $user1, 'Sup mang?', 0, $time + 2);
2807
        $m3id = $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!', 0, $time + 3);
2808
        $m4id = $this->send_fake_message($user2, $user1, 'Word.', 0, $time + 4);
2809
        $m5id = testhelper::send_fake_message_to_conversation($user1, $sc1->id, 'Hi to myself!', $time + 5);
2810
        $m6id = testhelper::send_fake_message_to_conversation($user2, $sc2->id, 'I am talking with myself', $time + 6);
2811
 
2812
        $conversationid = api::get_conversation_between_users([$user1->id, $user2->id]);
2813
 
2814
        // Delete the individual conversation between user1 and user2 (only for user1).
2815
        api::delete_conversation_by_id($user1->id, $conversationid);
2816
 
2817
        $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2818
        $this->assertCount(4, $muas);
2819
        // Sort by id.
2820
        ksort($muas);
2821
 
2822
        $mua1 = array_shift($muas);
2823
        $mua2 = array_shift($muas);
2824
        $mua3 = array_shift($muas);
2825
        $mua4 = array_shift($muas);
2826
 
2827
        $this->assertEquals($user1->id, $mua1->userid);
2828
        $this->assertEquals($m1id, $mua1->messageid);
2829
        $this->assertEquals(api::MESSAGE_ACTION_DELETED, $mua1->action);
2830
 
2831
        $this->assertEquals($user1->id, $mua2->userid);
2832
        $this->assertEquals($m2id, $mua2->messageid);
2833
        $this->assertEquals(api::MESSAGE_ACTION_DELETED, $mua2->action);
2834
 
2835
        $this->assertEquals($user1->id, $mua3->userid);
2836
        $this->assertEquals($m3id, $mua3->messageid);
2837
        $this->assertEquals(api::MESSAGE_ACTION_DELETED, $mua3->action);
2838
 
2839
        $this->assertEquals($user1->id, $mua4->userid);
2840
        $this->assertEquals($m4id, $mua4->messageid);
2841
        $this->assertEquals(api::MESSAGE_ACTION_DELETED, $mua4->action);
2842
 
2843
        // Delete the self-conversation as user 1.
2844
        api::delete_conversation_by_id($user1->id, $sc1->id);
2845
 
2846
        $muas = $DB->get_records('message_user_actions', array(), 'timecreated ASC');
2847
        $this->assertCount(5, $muas);
2848
 
2849
        // Sort by id.
2850
        ksort($muas);
2851
 
2852
        $mua1 = array_shift($muas);
2853
        $mua2 = array_shift($muas);
2854
        $mua3 = array_shift($muas);
2855
        $mua4 = array_shift($muas);
2856
        $mua5 = array_shift($muas);
2857
 
2858
        // Check only messages in self-conversion for user1 are deleted (self-conversation for user2 shouldn't be removed).
2859
        $this->assertEquals($user1->id, $mua5->userid);
2860
        $this->assertEquals($m5id, $mua5->messageid);
2861
        $this->assertEquals(api::MESSAGE_ACTION_DELETED, $mua5->action);
2862
    }
2863
 
2864
    /**
2865
     * Tests counting unread conversations.
2866
     */
2867
    public function test_count_unread_conversations() {
2868
        $this->resetAfterTest(true);
2869
 
2870
        // Create some users.
2871
        $user1 = self::getDataGenerator()->create_user();
2872
        $user2 = self::getDataGenerator()->create_user();
2873
        $user3 = self::getDataGenerator()->create_user();
2874
        $user4 = self::getDataGenerator()->create_user();
2875
 
2876
        // The person wanting the conversation count.
2877
        $this->setUser($user1);
2878
 
2879
        // Send some messages back and forth, have some different conversations with different users.
2880
        $this->send_fake_message($user1, $user2, 'Yo!');
2881
        $this->send_fake_message($user2, $user1, 'Sup mang?');
2882
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
2883
        $this->send_fake_message($user2, $user1, 'Word.');
2884
 
2885
        $this->send_fake_message($user1, $user3, 'Booyah');
2886
        $this->send_fake_message($user3, $user1, 'Whaaat?');
2887
        $this->send_fake_message($user1, $user3, 'Nothing.');
2888
        $this->send_fake_message($user3, $user1, 'Cool.');
2889
 
2890
        $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
2891
        $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
2892
        $this->send_fake_message($user1, $user4, 'Dope.');
2893
 
2894
        // Check the amount for the current user.
2895
        $this->assertEquals(3, api::count_unread_conversations());
2896
 
2897
        // Check the amount for the second user.
2898
        $this->assertEquals(1, api::count_unread_conversations($user2));
2899
    }
2900
 
2901
    /**
2902
     * Tests counting unread conversations where one conversation is disabled.
2903
     */
2904
    public function test_count_unread_conversations_disabled() {
2905
        $this->resetAfterTest(true);
2906
 
2907
        // Create some users.
2908
        $user1 = self::getDataGenerator()->create_user();
2909
        $user2 = self::getDataGenerator()->create_user();
2910
        $user3 = self::getDataGenerator()->create_user();
2911
        $user4 = self::getDataGenerator()->create_user();
2912
 
2913
        // The person wanting the conversation count.
2914
        $this->setUser($user1);
2915
 
2916
        // Send some messages back and forth, have some different conversations with different users.
2917
        $this->send_fake_message($user1, $user2, 'Yo!');
2918
        $this->send_fake_message($user2, $user1, 'Sup mang?');
2919
        $this->send_fake_message($user1, $user2, 'Writing PHPUnit tests!');
2920
        $this->send_fake_message($user2, $user1, 'Word.');
2921
 
2922
        $this->send_fake_message($user1, $user3, 'Booyah');
2923
        $this->send_fake_message($user3, $user1, 'Whaaat?');
2924
        $this->send_fake_message($user1, $user3, 'Nothing.');
2925
        $this->send_fake_message($user3, $user1, 'Cool.');
2926
 
2927
        $this->send_fake_message($user1, $user4, 'Hey mate, you see the new messaging UI in Moodle?');
2928
        $this->send_fake_message($user4, $user1, 'Yah brah, it\'s pretty rad.');
2929
        $this->send_fake_message($user1, $user4, 'Dope.');
2930
 
2931
        // Let's disable the last conversation.
2932
        $conversationid = api::get_conversation_between_users([$user1->id, $user4->id]);
2933
        api::disable_conversation($conversationid);
2934
 
2935
        // Check that the disabled conversation was not included.
2936
        $this->assertEquals(2, api::count_unread_conversations());
2937
    }
2938
 
2939
    /**
2940
     * Tests deleting a conversation.
2941
     */
2942
    public function test_get_all_message_preferences() {
2943
        $user = self::getDataGenerator()->create_user();
2944
        $this->setUser($user);
2945
 
2946
        // Set a couple of preferences to test.
2947
        set_user_preference('message_provider_mod_assign_assign_notification_enabled', 'popup', $user);
2948
        set_user_preference('message_provider_mod_feedback_submission_enabled', 'email', $user);
2949
 
2950
        $processors = get_message_processors();
2951
        $providers = message_get_providers_for_user($user->id);
2952
        $prefs = api::get_all_message_preferences($processors, $providers, $user);
2953
 
2954
        $this->assertEquals(1, $prefs->mod_assign_assign_notification_enabled['popup']);
2955
        $this->assertEquals(1, $prefs->mod_feedback_submission_enabled['email']);
2956
    }
2957
 
2958
    /**
2959
     * Tests the user can send a message.
2960
     */
2961
    public function test_can_send_message() {
2962
        // Create some users.
2963
        $user1 = self::getDataGenerator()->create_user();
2964
        $user2 = self::getDataGenerator()->create_user();
2965
 
2966
        // Set as the first user.
2967
        $this->setUser($user1);
2968
 
2969
        // With the default privacy setting, users can't message them.
2970
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
2971
 
2972
        // Enrol users to the same course.
2973
        $course = $this->getDataGenerator()->create_course();
2974
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
2975
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
2976
        // After enrolling users to the course, they should be able to message them with the default privacy setting.
2977
        $this->assertTrue(api::can_send_message($user2->id, $user1->id));
2978
    }
2979
 
2980
    /**
2981
     * Tests the user can't send a message without proper capability.
2982
     */
2983
    public function test_can_send_message_without_sendmessage_cap() {
2984
        global $DB;
2985
 
2986
        // Create some users.
2987
        $user1 = self::getDataGenerator()->create_user();
2988
        $user2 = self::getDataGenerator()->create_user();
2989
 
2990
        // Set as the user 1.
2991
        $this->setUser($user1);
2992
 
2993
        // Remove the capability to send a message.
2994
        $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
2995
        unassign_capability('moodle/site:sendmessage', $roleids['user'],
2996
            \context_system::instance());
2997
 
2998
        // Check that we can not post a message without the capability.
2999
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
3000
    }
3001
 
3002
    /**
3003
     * Tests the user can send a message when they are contact.
3004
     */
3005
    public function test_can_send_message_when_contact() {
3006
        // Create some users.
3007
        $user1 = self::getDataGenerator()->create_user();
3008
        $user2 = self::getDataGenerator()->create_user();
3009
 
3010
        // Set as the first user.
3011
        $this->setUser($user1);
3012
 
3013
        // Check that we can not send user2 a message.
3014
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
3015
 
3016
        // Add users as contacts.
3017
        api::add_contact($user1->id, $user2->id);
3018
 
3019
        // Check that the return result is now true.
3020
        $this->assertTrue(api::can_send_message($user2->id, $user1->id));
3021
    }
3022
 
3023
    /**
3024
     * Tests the user can't send a message if they are not a contact and the user
3025
     * has requested messages only from contacts.
3026
     */
3027
    public function test_can_send_message_when_not_contact() {
3028
        // Create some users.
3029
        $user1 = self::getDataGenerator()->create_user();
3030
        $user2 = self::getDataGenerator()->create_user();
3031
 
3032
        // Set as the first user.
3033
        $this->setUser($user1);
3034
 
3035
        // Set the second user's preference to not receive messages from non-contacts.
3036
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3037
 
3038
        // Check that we can not send user 2 a message.
3039
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
3040
    }
3041
 
3042
    /**
3043
     * Tests the user can't send a message if they are blocked.
3044
     */
3045
    public function test_can_send_message_when_blocked() {
3046
        // Create some users.
3047
        $user1 = self::getDataGenerator()->create_user();
3048
        $user2 = self::getDataGenerator()->create_user();
3049
 
3050
        // Set the user.
3051
        $this->setUser($user1);
3052
 
3053
        // Block the second user.
3054
        api::block_user($user1->id, $user2->id);
3055
 
3056
        // Check that the second user can no longer send the first user a message.
3057
        $this->assertFalse(api::can_send_message($user1->id, $user2->id));
3058
    }
3059
 
3060
    /**
3061
     * Tests the user can send a message when site-wide messaging setting is enabled,
3062
     * even if they are not a contact and are not members of the same course.
3063
     */
3064
    public function test_can_send_message_site_messaging_setting() {
3065
        // Create some users.
3066
        $user1 = self::getDataGenerator()->create_user();
3067
        $user2 = self::getDataGenerator()->create_user();
3068
 
3069
        // Set as the first user.
3070
        $this->setUser($user1);
3071
 
3072
        // By default, user only can be messaged by contacts and members of any of his/her courses.
3073
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
3074
 
3075
        // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
3076
        set_config('messagingallusers', true);
3077
 
3078
        // Set the second user's preference to receive messages from everybody.
3079
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_SITE, $user2->id);
3080
 
3081
        // Check that we can send user2 a message.
3082
        $this->assertTrue(api::can_send_message($user2->id, $user1->id));
3083
 
3084
        // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
3085
        // and members sharing a course with her.
3086
        set_config('messagingallusers', false);
3087
 
3088
        // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
3089
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
3090
 
3091
        // Enrol users to the same course.
3092
        $course = $this->getDataGenerator()->create_course();
3093
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3094
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3095
        // Check that we can send user2 a message because they are sharing a course.
3096
        $this->assertTrue(api::can_send_message($user2->id, $user1->id));
3097
 
3098
        // Set the second user's preference to receive messages only from contacts.
3099
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3100
        // Check that now the user2 can't be contacted because user1 is not their contact.
3101
        $this->assertFalse(api::can_send_message($user2->id, $user1->id));
3102
 
3103
        // Make contacts user1 and user2.
3104
        api::add_contact($user2->id, $user1->id);
3105
        // Check that we can send user2 a message because they are contacts.
3106
        $this->assertTrue(api::can_send_message($user2->id, $user1->id));
3107
    }
3108
 
3109
    /**
3110
     * Tests the user with the messageanyuser capability can send a message.
3111
     */
3112
    public function test_can_send_message_with_messageanyuser_cap() {
3113
        global $DB;
3114
 
3115
        // Create some users.
3116
        $teacher1 = self::getDataGenerator()->create_user();
3117
        $student1 = self::getDataGenerator()->create_user();
3118
        $student2 = self::getDataGenerator()->create_user();
3119
 
3120
        // Create users not enrolled in any course.
3121
        $user1 = self::getDataGenerator()->create_user();
3122
 
3123
        // Create a course.
3124
        $course1 = $this->getDataGenerator()->create_course();
3125
 
3126
        // Enrol the users in the course.
3127
        $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher');
3128
        $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student');
3129
        $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student');
3130
 
3131
        // Set some student preferences to not receive messages from non-contacts.
3132
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_ONLYCONTACTS, $student1->id);
3133
 
3134
        // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
3135
        $this->assertTrue(api::can_send_message($student1->id, $teacher1->id));
3136
 
3137
        // Check that the teacher can't contact user1 because it's not his teacher.
3138
        $this->assertFalse(api::can_send_message($user1->id, $teacher1->id));
3139
 
3140
        // Remove the messageanyuser capability from the course1 for teachers.
3141
        $coursecontext = \context_course::instance($course1->id);
3142
        $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
3143
        assign_capability('moodle/site:messageanyuser', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
3144
        $coursecontext->mark_dirty();
3145
 
3146
        // Check that we can't send user1 a message because they are not contacts.
3147
        $this->assertFalse(api::can_send_message($student1->id, $teacher1->id));
3148
 
3149
        // However, teacher can message student2 because they are sharing a course.
3150
        $this->assertTrue(api::can_send_message($student2->id, $teacher1->id));
3151
    }
3152
 
3153
    /**
3154
     * Tests the user when blocked will not be able to send messages if they are blocked.
3155
     */
3156
    public function test_can_send_message_even_if_blocked() {
3157
        $this->resetAfterTest();
3158
 
3159
        $user1 = self::getDataGenerator()->create_user();
3160
        $user2 = self::getDataGenerator()->create_user();
3161
 
3162
        $this->assertFalse(api::can_send_message($user2->id, $user1->id, true));
3163
    }
3164
 
3165
    /**
3166
     * Tests the user will be able to send a message even if they are blocked as the user
3167
     * has the capability 'moodle/site:messageanyuser'.
3168
     */
3169
    public function test_can_send_message_even_if_blocked_with_message_any_user_cap() {
3170
        global $DB;
3171
 
3172
        $this->resetAfterTest();
3173
 
3174
        $user1 = self::getDataGenerator()->create_user();
3175
        $user2 = self::getDataGenerator()->create_user();
3176
 
3177
        $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
3178
        assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduserrole->id, \context_system::instance(), true);
3179
 
3180
        $this->assertTrue(api::can_send_message($user2->id, $user1->id, true));
3181
    }
3182
 
3183
    /**
3184
     * Tests the user will be able to send a message even if they are blocked as the user
3185
     * has the capability 'moodle/site:readallmessages'.
3186
     */
3187
    public function test_can_send_message_even_if_blocked_with_read_all_message_cap() {
3188
        global $DB;
3189
 
3190
        $this->resetAfterTest();
3191
 
3192
        $user1 = self::getDataGenerator()->create_user();
3193
        $user2 = self::getDataGenerator()->create_user();
3194
 
3195
        $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
3196
        assign_capability('moodle/site:readallmessages', CAP_ALLOW, $authenticateduserrole->id, \context_system::instance(), true);
3197
 
3198
        $this->assertTrue(api::can_send_message($user2->id, $user1->id, true));
3199
    }
3200
 
3201
    /**
3202
     * Tests the user can not always send a message if they are blocked just because they share a course.
3203
     */
3204
    public function test_can_send_message_even_if_blocked_shared_course() {
3205
        $this->resetAfterTest();
3206
 
3207
        // Create some users.
3208
        $user1 = self::getDataGenerator()->create_user();
3209
        $user2 = self::getDataGenerator()->create_user();
3210
 
3211
        $course = self::getDataGenerator()->create_course();
3212
 
3213
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3214
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3215
 
3216
        $this->assertFalse(api::can_send_message($user2->id, $user1->id, true));
3217
    }
3218
 
3219
    /**
3220
     * Tests the user can always send a message even if they are blocked because they share a course and
3221
     * have the capability 'moodle/site:messageanyuser' at the course context.
3222
     */
3223
    public function test_can_send_message_even_if_blocked_shared_course_with_message_any_user_cap() {
3224
        global $DB;
3225
 
3226
        $this->resetAfterTest();
3227
 
3228
        $editingteacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
3229
 
3230
        $teacher = self::getDataGenerator()->create_user();
3231
        $student = self::getDataGenerator()->create_user();
3232
 
3233
        $course = self::getDataGenerator()->create_course();
3234
 
3235
        $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $editingteacherrole->id);
3236
        $this->getDataGenerator()->enrol_user($student->id, $course->id);
3237
 
3238
        assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $editingteacherrole->id,
3239
            \context_course::instance($course->id), true);
3240
 
3241
        // Check that the second user can no longer send the first user a message.
3242
        $this->assertTrue(api::can_send_message($student->id, $teacher->id, true));
3243
    }
3244
 
3245
    /**
3246
     * Verify the expected behaviour of the can_send_message_to_conversation() method for authenticated users with default settings.
3247
     */
3248
    public function test_can_send_message_to_conversation_basic() {
3249
        // Create some users.
3250
        $user1 = self::getDataGenerator()->create_user();
3251
        $user2 = self::getDataGenerator()->create_user();
3252
        $user3 = self::getDataGenerator()->create_user();
3253
 
3254
        // Create an individual conversation between user1 and user2.
3255
        $ic1 = api::create_conversation(
3256
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3257
            [
3258
                $user1->id,
3259
                $user2->id
3260
            ]
3261
        );
3262
 
3263
        // Create a group conversation between and users 1, 2 and 3.
3264
        $gc1 = api::create_conversation(
3265
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3266
            [
3267
                $user1->id,
3268
                $user2->id,
3269
                $user3->id
3270
            ]
3271
        );
3272
 
3273
        // Get a self-conversation for user1.
3274
        $sc1 = api::get_self_conversation($user1->id);
3275
 
3276
        // For group conversations, there are no user privacy checks, so only membership in the conversation is needed.
3277
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3278
 
3279
        // For self conversations, there are no user privacy checks, so only membership in the conversation is needed.
3280
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $sc1->id));
3281
 
3282
        // For individual conversations, the default privacy setting of 'only contacts and course members' applies.
3283
        // Users are not in the same course, nor are they contacts, so messages cannot be sent.
3284
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3285
 
3286
        // Enrol the users into the same course.
3287
        $course = $this->getDataGenerator()->create_course();
3288
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3289
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3290
 
3291
        // After enrolling users to the course, they should be able to message them with the default privacy setting.
3292
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $ic1->id));
3293
    }
3294
 
3295
    /**
3296
     * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the sendmessage capability.
3297
     */
3298
    public function test_can_send_message_to_conversation_sendmessage_cap() {
3299
        global $DB;
3300
 
3301
        $user1 = self::getDataGenerator()->create_user();
3302
        $user2 = self::getDataGenerator()->create_user();
3303
        $user3 = self::getDataGenerator()->create_user();
3304
 
3305
        // Enrol the users into the same course.
3306
        $course = $this->getDataGenerator()->create_course();
3307
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3308
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3309
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3310
 
3311
        // Create an individual conversation between user1 and user2.
3312
        $ic1 = api::create_conversation(
3313
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3314
            [
3315
                $user1->id,
3316
                $user2->id
3317
            ]
3318
        );
3319
 
3320
        // Group conversation between and users 1, 2 and 3.
3321
        $gc1 = api::create_conversation(
3322
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3323
            [
3324
                $user1->id,
3325
                $user2->id,
3326
                $user3->id
3327
            ]
3328
        );
3329
 
3330
        // Default settings - user1 can send a message to both conversations.
3331
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $ic1->id));
3332
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3333
 
3334
        // Remove the capability to send a message.
3335
        $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
3336
        unassign_capability('moodle/site:sendmessage', $roleids['user'], \context_system::instance());
3337
 
3338
        // Verify that a user cannot send a message to either an individual or a group conversation.
3339
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3340
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $gc1->id));
3341
    }
3342
 
3343
    /**
3344
     * Verify the behaviour of can_send_message_to_conversation() for authenticated users without the messageanyuser capability.
3345
     */
3346
    public function test_can_send_message_to_conversation_messageanyuser_cap() {
3347
        global $DB;
3348
 
3349
        $user1 = self::getDataGenerator()->create_user();
3350
        $user2 = self::getDataGenerator()->create_user();
3351
        $user3 = self::getDataGenerator()->create_user();
3352
 
3353
        // Enrol the users into the same course.
3354
        $course = $this->getDataGenerator()->create_course();
3355
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3356
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3357
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3358
 
3359
        // Create an individual conversation between user1 and user2.
3360
        $ic1 = api::create_conversation(
3361
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3362
            [
3363
                $user1->id,
3364
                $user2->id
3365
            ]
3366
        );
3367
 
3368
        // Group conversation between and users 1, 2 and 3.
3369
        $gc1 = api::create_conversation(
3370
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3371
            [
3372
                $user1->id,
3373
                $user2->id,
3374
                $user3->id
3375
            ]
3376
        );
3377
 
3378
        // Update the message preference for user2, so they can only be messaged by contacts.
3379
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3380
 
3381
        // Verify that the user cannot be contacted in the individual conversation and that groups are unaffected.
3382
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3383
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3384
 
3385
        // Assign the 'messageanyuser' capability to user1 at system context.
3386
        $systemcontext = \context_system::instance();
3387
        $authenticateduser = $DB->get_record('role', ['shortname' => 'user']);
3388
        assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, $systemcontext->id);
3389
 
3390
        // Check that user1 can now message user2 due to the capability, and that group conversations is again unaffected.
3391
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $ic1->id));
3392
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3393
    }
3394
 
3395
    /**
3396
     * Test verifying that users cannot send messages to conversations they are not a part of.
3397
     */
3398
    public function test_can_send_message_to_conversation_non_member() {
3399
        // Create some users.
3400
        $user1 = self::getDataGenerator()->create_user();
3401
        $user2 = self::getDataGenerator()->create_user();
3402
        $user3 = self::getDataGenerator()->create_user();
3403
        $user4 = self::getDataGenerator()->create_user();
3404
 
3405
        // Enrol the users into the same course.
3406
        $course = $this->getDataGenerator()->create_course();
3407
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3408
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3409
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3410
        $this->getDataGenerator()->enrol_user($user4->id, $course->id);
3411
 
3412
        // Create an individual conversation between user1 and user2.
3413
        $ic1 = api::create_conversation(
3414
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3415
            [
3416
                $user1->id,
3417
                $user2->id
3418
            ]
3419
        );
3420
 
3421
        // Create a group conversation between and users 1, 2 and 3.
3422
        $gc1 = api::create_conversation(
3423
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3424
            [
3425
                $user1->id,
3426
                $user2->id,
3427
                $user3->id
3428
            ]
3429
        );
3430
 
3431
        // Get a self-conversation for user1.
3432
        $sc1 = api::get_self_conversation($user1->id);
3433
 
3434
        // Verify, non members cannot send a message.
3435
        $this->assertFalse(api::can_send_message_to_conversation($user4->id, $gc1->id));
3436
        $this->assertFalse(api::can_send_message_to_conversation($user4->id, $ic1->id));
3437
        $this->assertFalse(api::can_send_message_to_conversation($user4->id, $sc1->id));
3438
    }
3439
 
3440
    /**
3441
     * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts only.
3442
     */
3443
    public function test_can_send_message_to_conversation_privacy_contacts_only() {
3444
        // Create some users.
3445
        $user1 = self::getDataGenerator()->create_user();
3446
        $user2 = self::getDataGenerator()->create_user();
3447
        $user3 = self::getDataGenerator()->create_user();
3448
 
3449
        // Create an individual conversation between user1 and user2.
3450
        $ic1 = api::create_conversation(
3451
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3452
            [
3453
                $user1->id,
3454
                $user2->id
3455
            ]
3456
        );
3457
 
3458
        // Create a group conversation between and users 1, 2 and 3.
3459
        $gc1 = api::create_conversation(
3460
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3461
            [
3462
                $user1->id,
3463
                $user2->id,
3464
                $user3->id
3465
            ]
3466
        );
3467
 
3468
        // Set the message privacy preference to 'contacts only' for user 2.
3469
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3470
 
3471
        // Verify that user1 cannot send a message to the individual conversation, but that the group conversation is unaffected.
3472
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3473
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3474
 
3475
        // Now, simulate a contact request (and approval) between user1 and user2.
3476
        api::create_contact_request($user1->id, $user2->id);
3477
        api::confirm_contact_request($user1->id, $user2->id);
3478
 
3479
        // Verify user1 can now message user2 again via their individual conversation.
3480
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $ic1->id));
3481
    }
3482
 
3483
    /**
3484
     * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to contacts / course members.
3485
     */
3486
    public function test_can_send_message_to_conversation_privacy_contacts_course() {
3487
        // Create some users.
3488
        $user1 = self::getDataGenerator()->create_user();
3489
        $user2 = self::getDataGenerator()->create_user();
3490
        $user3 = self::getDataGenerator()->create_user();
3491
 
3492
        // Set the message privacy preference to 'contacts + course members' for user 2.
3493
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_COURSEMEMBER, $user2->id);
3494
 
3495
        // Create an individual conversation between user1 and user2.
3496
        $ic1 = api::create_conversation(
3497
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3498
            [
3499
                $user1->id,
3500
                $user2->id
3501
            ]
3502
        );
3503
 
3504
        // Create a group conversation between and users 1, 2 and 3.
3505
        $gc1 = api::create_conversation(
3506
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3507
            [
3508
                $user1->id,
3509
                $user2->id,
3510
                $user3->id
3511
            ]
3512
        );
3513
 
3514
        // Verify that users in a group conversation can message one another (i.e. privacy controls ignored).
3515
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3516
 
3517
        // Verify that user1 can not message user2 unless they are either contacts, or share a course.
3518
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3519
 
3520
        // Enrol the users into the same course.
3521
        $course = $this->getDataGenerator()->create_course();
3522
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3523
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3524
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3525
 
3526
        // Verify that user1 can send a message to user2, based on the shared course, without being a contact.
3527
        $this->assertFalse(api::is_contact($user1->id, $user2->id));
3528
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $ic1->id));
3529
    }
3530
 
3531
    /**
3532
     * Test verifying the behaviour of the can_send_message_to_conversation method when privacy is set to any user.
3533
     */
3534
    public function test_can_send_message_to_conversation_privacy_sitewide() {
3535
        // Create some users.
3536
        $user1 = self::getDataGenerator()->create_user();
3537
        $user2 = self::getDataGenerator()->create_user();
3538
        $user3 = self::getDataGenerator()->create_user();
3539
 
3540
        // Create an individual conversation between user1 and user2.
3541
        $ic1 = api::create_conversation(
3542
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3543
            [
3544
                $user1->id,
3545
                $user2->id
3546
            ]
3547
        );
3548
 
3549
        // Create a group conversation between and users 1, 2 and 3.
3550
        $gc1 = api::create_conversation(
3551
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3552
            [
3553
                $user1->id,
3554
                $user2->id,
3555
                $user3->id
3556
            ]
3557
        );
3558
 
3559
        // By default, the messaging privacy dictates that users can only be contacted by contacts, and members of their courses.
3560
        // Verify also, that groups are not restricted in this way.
3561
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3562
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3563
 
3564
        // Enable site-wide messagging privacy setting.
3565
        // This enables a privacy option for users, allowing them to choose to be contactable by anybody on the site.
3566
        set_config('messagingallusers', true);
3567
 
3568
        // Set the second user's preference to receive messages from everybody.
3569
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_SITE, $user2->id);
3570
 
3571
        // Check that user1 can send user2 a message, and that the group conversation is unaffected.
3572
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $ic1->id));
3573
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3574
 
3575
        // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
3576
        // and members sharing a course with her.
3577
        set_config('messagingallusers', false);
3578
 
3579
        // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
3580
        // Verify also that the group conversation is unaffected.
3581
        $this->assertFalse(api::can_send_message_to_conversation($user1->id, $ic1->id));
3582
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3583
    }
3584
 
3585
    /**
3586
     * Test verifying the behaviour of the can_send_message_to_conversation method when a user is blocked.
3587
     */
3588
    public function test_can_send_message_to_conversation_when_blocked() {
3589
        $user1 = self::getDataGenerator()->create_user();
3590
        $user2 = self::getDataGenerator()->create_user();
3591
        $user3 = self::getDataGenerator()->create_user();
3592
 
3593
        // Create an individual conversation between user1 and user2.
3594
        $ic1 = api::create_conversation(
3595
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3596
            [
3597
                $user1->id,
3598
                $user2->id
3599
            ]
3600
        );
3601
 
3602
        // Create a group conversation between and users 1, 2 and 3.
3603
        $gc1 = api::create_conversation(
3604
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3605
            [
3606
                $user1->id,
3607
                $user2->id,
3608
                $user3->id
3609
            ]
3610
        );
3611
 
3612
        // Enrol the users into the same course.
3613
        $course = $this->getDataGenerator()->create_course();
3614
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
3615
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
3616
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
3617
 
3618
        // Block the second user.
3619
        api::block_user($user1->id, $user2->id);
3620
 
3621
        // Check that user2 can not send user1 a message in their individual conversation.
3622
        $this->assertFalse(api::can_send_message_to_conversation($user2->id, $ic1->id));
3623
 
3624
        // Verify that group conversations are unaffected.
3625
        $this->assertTrue(api::can_send_message_to_conversation($user1->id, $gc1->id));
3626
        $this->assertTrue(api::can_send_message_to_conversation($user2->id, $gc1->id));
3627
    }
3628
 
3629
    /**
3630
     * Tests get_user_privacy_messaging_preference method.
3631
     */
3632
    public function test_get_user_privacy_messaging_preference() {
3633
        // Create some users.
3634
        $user1 = self::getDataGenerator()->create_user();
3635
        $user2 = self::getDataGenerator()->create_user();
3636
        $user3 = self::getDataGenerator()->create_user();
3637
 
3638
        // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
3639
        set_config('messagingallusers', true);
3640
 
3641
        // Set some user preferences.
3642
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_SITE, $user1->id);
3643
        set_user_preference('message_blocknoncontacts', api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
3644
 
3645
        // Check the returned value for each user.
3646
        $this->assertEquals(
3647
            api::MESSAGE_PRIVACY_SITE,
3648
            api::get_user_privacy_messaging_preference($user1->id)
3649
        );
3650
        $this->assertEquals(
3651
            api::MESSAGE_PRIVACY_ONLYCONTACTS,
3652
            api::get_user_privacy_messaging_preference($user2->id)
3653
        );
3654
        $this->assertEquals(
3655
            api::MESSAGE_PRIVACY_SITE,
3656
            api::get_user_privacy_messaging_preference($user3->id)
3657
        );
3658
 
3659
        // Disable site-wide messagging privacy setting. The user will be able to receive messages from members of their course.
3660
        set_config('messagingallusers', false);
3661
 
3662
        // Check the returned value for each user.
3663
        $this->assertEquals(
3664
            api::MESSAGE_PRIVACY_COURSEMEMBER,
3665
            api::get_user_privacy_messaging_preference($user1->id)
3666
        );
3667
        $this->assertEquals(
3668
            api::MESSAGE_PRIVACY_ONLYCONTACTS,
3669
            api::get_user_privacy_messaging_preference($user2->id)
3670
        );
3671
        $this->assertEquals(
3672
            api::MESSAGE_PRIVACY_COURSEMEMBER,
3673
            api::get_user_privacy_messaging_preference($user3->id)
3674
        );
3675
    }
3676
 
3677
    /*
3678
     * Tes get_message_processor api.
3679
     */
3680
    public function test_get_message_processor() {
3681
        $processors = get_message_processors(true);
3682
        if (empty($processors)) {
3683
            $this->markTestSkipped("No message processors found");
3684
        }
3685
 
3686
        $name = key($processors);
3687
        $processor = current($processors);
3688
        $testprocessor = api::get_message_processor($name);
3689
        $this->assertEquals($processor->name, $testprocessor->name);
3690
        $this->assertEquals($processor->enabled, $testprocessor->enabled);
3691
        $this->assertEquals($processor->available, $testprocessor->available);
3692
        $this->assertEquals($processor->configured, $testprocessor->configured);
3693
 
3694
        // Disable processor and test.
3695
        api::update_processor_status($testprocessor, 0);
3696
        $testprocessor = api::get_message_processor($name, true);
3697
        $this->assertEmpty($testprocessor);
3698
        $testprocessor = api::get_message_processor($name);
3699
        $this->assertEquals($processor->name, $testprocessor->name);
3700
        $this->assertEquals(0, $testprocessor->enabled);
3701
 
3702
        // Enable again and test.
3703
        api::update_processor_status($testprocessor, 1);
3704
        $testprocessor = api::get_message_processor($name, true);
3705
        $this->assertEquals($processor->name, $testprocessor->name);
3706
        $this->assertEquals(1, $testprocessor->enabled);
3707
        $testprocessor = api::get_message_processor($name);
3708
        $this->assertEquals($processor->name, $testprocessor->name);
3709
        $this->assertEquals(1, $testprocessor->enabled);
3710
    }
3711
 
3712
    /**
3713
     * Test method update_processor_status.
3714
     */
3715
    public function test_update_processor_status() {
3716
        $processors = get_message_processors();
3717
        if (empty($processors)) {
3718
            $this->markTestSkipped("No message processors found");
3719
        }
3720
        $name = key($processors);
3721
        $testprocessor = current($processors);
3722
 
3723
        // Enable.
3724
        api::update_processor_status($testprocessor, 1);
3725
        $testprocessor = api::get_message_processor($name);
3726
        $this->assertEquals(1, $testprocessor->enabled);
3727
 
3728
        // Disable.
3729
        api::update_processor_status($testprocessor, 0);
3730
        $testprocessor = api::get_message_processor($name);
3731
        $this->assertEquals(0, $testprocessor->enabled);
3732
 
3733
        // Enable again.
3734
        api::update_processor_status($testprocessor, 1);
3735
        $testprocessor = api::get_message_processor($name);
3736
        $this->assertEquals(1, $testprocessor->enabled);
3737
    }
3738
 
3739
    /**
3740
     * Test method is_user_enabled.
3741
     */
3742
    public function is_user_enabled() {
3743
        $processors = get_message_processors();
3744
        if (empty($processors)) {
3745
            $this->markTestSkipped("No message processors found");
3746
        }
3747
        $name = key($processors);
3748
        $testprocessor = current($processors);
3749
 
3750
        // Enable.
3751
        api::update_processor_status($testprocessor, 1);
3752
        $status = api::is_processor_enabled($name);
3753
        $this->assertEquals(1, $status);
3754
 
3755
        // Disable.
3756
        api::update_processor_status($testprocessor, 0);
3757
        $status = api::is_processor_enabled($name);
3758
        $this->assertEquals(0, $status);
3759
 
3760
        // Enable again.
3761
        api::update_processor_status($testprocessor, 1);
3762
        $status = api::is_processor_enabled($name);
3763
        $this->assertEquals(1, $status);
3764
    }
3765
 
3766
    /**
3767
     * Test returning blocked users.
3768
     */
3769
    public function test_get_blocked_users() {
3770
        global $USER;
3771
 
3772
        // Set this user as the admin.
3773
        $this->setAdminUser();
3774
 
3775
        // Create a user to add to the admin's contact list.
3776
        $user1 = $this->getDataGenerator()->create_user();
3777
        $user2 = $this->getDataGenerator()->create_user();
3778
 
3779
        // Add users to the admin's contact list.
3780
        api::block_user($USER->id, $user2->id);
3781
 
3782
        $this->assertCount(1, api::get_blocked_users($USER->id));
3783
 
3784
        // Block other user.
3785
        api::block_user($USER->id, $user1->id);
3786
        $this->assertCount(2, api::get_blocked_users($USER->id));
3787
 
3788
        // Test deleting users.
3789
        delete_user($user1);
3790
        $this->assertCount(1, api::get_blocked_users($USER->id));
3791
    }
3792
 
3793
    /**
3794
     * Test marking a message as read.
3795
     */
3796
    public function test_mark_message_as_read() {
3797
        global $DB;
3798
 
3799
        $user1 = self::getDataGenerator()->create_user();
3800
        $user2 = self::getDataGenerator()->create_user();
3801
 
3802
        $this->send_fake_message($user1, $user2);
3803
        $m2id = $this->send_fake_message($user1, $user2);
3804
        $this->send_fake_message($user2, $user1);
3805
        $m4id = $this->send_fake_message($user2, $user1);
3806
 
3807
        $m2 = $DB->get_record('messages', ['id' => $m2id]);
3808
        $m4 = $DB->get_record('messages', ['id' => $m4id]);
3809
        api::mark_message_as_read($user2->id, $m2, 11);
3810
        api::mark_message_as_read($user1->id, $m4, 12);
3811
 
3812
        // Confirm there are two user actions.
3813
        $muas = $DB->get_records('message_user_actions', [], 'timecreated ASC');
3814
        $this->assertEquals(2, count($muas));
3815
 
3816
        // Confirm they are correct.
3817
        $mua1 = array_shift($muas);
3818
        $mua2 = array_shift($muas);
3819
 
3820
        // Confirm first action.
3821
        $this->assertEquals($user2->id, $mua1->userid);
3822
        $this->assertEquals($m2id, $mua1->messageid);
3823
        $this->assertEquals(api::MESSAGE_ACTION_READ, $mua1->action);
3824
        $this->assertEquals(11, $mua1->timecreated);
3825
 
3826
        // Confirm second action.
3827
        $this->assertEquals($user1->id, $mua2->userid);
3828
        $this->assertEquals($m4id, $mua2->messageid);
3829
        $this->assertEquals(api::MESSAGE_ACTION_READ, $mua2->action);
3830
        $this->assertEquals(12, $mua2->timecreated);
3831
    }
3832
 
3833
    /**
3834
     * Test marking a notification as read.
3835
     */
3836
    public function test_mark_notification_as_read() {
3837
        global $DB;
3838
 
3839
        $user1 = self::getDataGenerator()->create_user();
3840
        $user2 = self::getDataGenerator()->create_user();
3841
 
3842
        $this->send_fake_message($user1, $user2, 'Notification 1', 1);
3843
        $n2id = $this->send_fake_message($user1, $user2, 'Notification 2', 1);
3844
        $this->send_fake_message($user2, $user1, 'Notification 3', 1);
3845
        $n4id = $this->send_fake_message($user2, $user1, 'Notification 4', 1);
3846
 
3847
        $n2 = $DB->get_record('notifications', ['id' => $n2id]);
3848
        $n4 = $DB->get_record('notifications', ['id' => $n4id]);
3849
 
3850
        api::mark_notification_as_read($n2, 11);
3851
        api::mark_notification_as_read($n4, 12);
3852
 
3853
        // Retrieve the notifications.
3854
        $n2 = $DB->get_record('notifications', ['id' => $n2id]);
3855
        $n4 = $DB->get_record('notifications', ['id' => $n4id]);
3856
 
3857
        // Confirm they have been marked as read.
3858
        $this->assertEquals(11, $n2->timeread);
3859
        $this->assertEquals(12, $n4->timeread);
3860
    }
3861
 
3862
    /**
3863
     * Test a conversation is not returned if there is none.
3864
     */
3865
    public function test_get_conversation_between_users_no_conversation() {
3866
        $user1 = self::getDataGenerator()->create_user();
3867
        $user2 = self::getDataGenerator()->create_user();
3868
 
3869
        $this->assertFalse(api::get_conversation_between_users([$user1->id, $user2->id]));
3870
    }
3871
 
3872
    /**
3873
     * Test count_conversation_members for non existing conversation.
3874
     */
3875
    public function test_count_conversation_members_no_existing_conversation() {
3876
        $this->assertEquals(0,
3877
            api::count_conversation_members(0));
3878
    }
3879
 
3880
    /**
3881
     * Test count_conversation_members for existing conversation.
3882
     */
3883
    public function test_count_conversation_members_existing_conversation() {
3884
        $user1 = self::getDataGenerator()->create_user();
3885
        $user2 = self::getDataGenerator()->create_user();
3886
 
3887
        $conversation = api::create_conversation(
3888
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3889
            [
3890
                $user1->id,
3891
                $user2->id
3892
            ]
3893
        );
3894
        $conversationid = $conversation->id;
3895
 
3896
        $this->assertEquals(2,
3897
            api::count_conversation_members($conversationid));
3898
    }
3899
 
3900
    /**
3901
     * Test add_members_to_conversation for an individual conversation.
3902
     */
3903
    public function test_add_members_to_individual_conversation() {
3904
        $user1 = self::getDataGenerator()->create_user();
3905
        $user2 = self::getDataGenerator()->create_user();
3906
        $user3 = self::getDataGenerator()->create_user();
3907
 
3908
        $conversation = api::create_conversation(
3909
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
3910
            [
3911
                $user1->id,
3912
                $user2->id
3913
            ]
3914
        );
3915
        $conversationid = $conversation->id;
3916
 
3917
        $this->expectException('moodle_exception');
3918
        api::add_members_to_conversation([$user3->id], $conversationid);
3919
    }
3920
 
3921
    /**
3922
     * Test add_members_to_conversation for existing conversation.
3923
     */
3924
    public function test_add_members_to_existing_conversation() {
3925
        $user1 = self::getDataGenerator()->create_user();
3926
        $user2 = self::getDataGenerator()->create_user();
3927
        $user3 = self::getDataGenerator()->create_user();
3928
 
3929
        $conversation = api::create_conversation(
3930
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3931
            [
3932
                $user1->id,
3933
                $user2->id
3934
            ]
3935
        );
3936
        $conversationid = $conversation->id;
3937
 
3938
        $this->assertNull(api::add_members_to_conversation([$user3->id], $conversationid));
3939
        $this->assertEquals(3,
3940
            api::count_conversation_members($conversationid));
3941
    }
3942
 
3943
    /**
3944
     * Test add_members_to_conversation for non existing conversation.
3945
     */
3946
    public function test_add_members_to_no_existing_conversation() {
3947
        $user1 = self::getDataGenerator()->create_user();
3948
 
3949
        // Throw dml_missing_record_exception for non existing conversation.
3950
        $this->expectException('dml_missing_record_exception');
3951
        api::add_members_to_conversation([$user1->id], 0);
3952
    }
3953
 
3954
    /**
3955
     * Test add_member_to_conversation for non existing user.
3956
     */
3957
    public function test_add_members_to_no_existing_user() {
3958
        $user1 = self::getDataGenerator()->create_user();
3959
        $user2 = self::getDataGenerator()->create_user();
3960
 
3961
        $conversation = api::create_conversation(
3962
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3963
            [
3964
                $user1->id,
3965
                $user2->id
3966
            ]
3967
        );
3968
        $conversationid = $conversation->id;
3969
 
3970
        // Don't throw an error for non existing user, but don't add it as a member.
3971
        $this->assertNull(api::add_members_to_conversation([0], $conversationid));
3972
        $this->assertEquals(2,
3973
            api::count_conversation_members($conversationid));
3974
    }
3975
 
3976
    /**
3977
     * Test add_members_to_conversation for current conversation member.
3978
     */
3979
    public function test_add_members_to_current_conversation_member() {
3980
        $user1 = self::getDataGenerator()->create_user();
3981
        $user2 = self::getDataGenerator()->create_user();
3982
 
3983
        $conversation = api::create_conversation(
3984
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
3985
            [
3986
                $user1->id,
3987
                $user2->id
3988
            ]
3989
        );
3990
        $conversationid = $conversation->id;
3991
 
3992
        // Don't add as a member a user that is already conversation member.
3993
        $this->assertNull(api::add_members_to_conversation([$user1->id], $conversationid));
3994
        $this->assertEquals(2,
3995
            api::count_conversation_members($conversationid));
3996
    }
3997
 
3998
    /**
3999
     * Test add_members_to_conversation for multiple users.
4000
     */
4001
    public function test_add_members_for_multiple_users() {
4002
        $user1 = self::getDataGenerator()->create_user();
4003
        $user2 = self::getDataGenerator()->create_user();
4004
        $user3 = self::getDataGenerator()->create_user();
4005
        $user4 = self::getDataGenerator()->create_user();
4006
 
4007
        $conversation = api::create_conversation(
4008
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4009
            [
4010
                $user1->id,
4011
                $user2->id
4012
            ]
4013
        );
4014
        $conversationid = $conversation->id;
4015
 
4016
        $this->assertNull(api::add_members_to_conversation([$user3->id, $user4->id], $conversationid));
4017
        $this->assertEquals(4,
4018
            api::count_conversation_members($conversationid));
4019
    }
4020
 
4021
    /**
4022
     * Test add_members_to_conversation for multiple users, included non existing and current conversation members
4023
     */
4024
    public function test_add_members_for_multiple_not_valid_users() {
4025
        $user1 = self::getDataGenerator()->create_user();
4026
        $user2 = self::getDataGenerator()->create_user();
4027
        $user3 = self::getDataGenerator()->create_user();
4028
 
4029
        $conversation = api::create_conversation(
4030
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4031
            [
4032
                $user1->id,
4033
                $user2->id
4034
            ]
4035
        );
4036
        $conversationid = $conversation->id;
4037
 
4038
        // Don't throw errors, but don't add as members users don't exist or are already conversation members.
4039
        $this->assertNull(api::add_members_to_conversation([$user3->id, $user1->id, 0], $conversationid));
4040
        $this->assertEquals(3,
4041
            api::count_conversation_members($conversationid));
4042
    }
4043
 
4044
    /**
4045
     * Test remove_members_from_conversation for individual conversation.
4046
     */
4047
    public function test_remove_members_from_individual_conversation() {
4048
        $user1 = self::getDataGenerator()->create_user();
4049
        $user2 = self::getDataGenerator()->create_user();
4050
 
4051
        $conversation = api::create_conversation(
4052
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4053
            [
4054
                $user1->id,
4055
                $user2->id
4056
            ]
4057
        );
4058
        $conversationid = $conversation->id;
4059
 
4060
        $this->expectException('moodle_exception');
4061
        api::remove_members_from_conversation([$user1->id], $conversationid);
4062
    }
4063
 
4064
    /**
4065
     * Test remove_members_from_conversation for existing conversation.
4066
     */
4067
    public function test_remove_members_from_existing_conversation() {
4068
        $user1 = self::getDataGenerator()->create_user();
4069
        $user2 = self::getDataGenerator()->create_user();
4070
 
4071
        $conversation = api::create_conversation(
4072
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4073
            [
4074
                $user1->id,
4075
                $user2->id
4076
            ]
4077
        );
4078
        $conversationid = $conversation->id;
4079
 
4080
        $this->assertNull(api::remove_members_from_conversation([$user1->id], $conversationid));
4081
        $this->assertEquals(1,
4082
            api::count_conversation_members($conversationid));
4083
    }
4084
 
4085
    /**
4086
     * Test remove_members_from_conversation for non existing conversation.
4087
     */
4088
    public function test_remove_members_from_no_existing_conversation() {
4089
        $user1 = self::getDataGenerator()->create_user();
4090
 
4091
        // Throw dml_missing_record_exception for non existing conversation.
4092
        $this->expectException('dml_missing_record_exception');
4093
        api::remove_members_from_conversation([$user1->id], 0);
4094
    }
4095
 
4096
    /**
4097
     * Test remove_members_from_conversation for non existing user.
4098
     */
4099
    public function test_remove_members_for_no_existing_user() {
4100
        $user1 = self::getDataGenerator()->create_user();
4101
        $user2 = self::getDataGenerator()->create_user();
4102
 
4103
        $conversation = api::create_conversation(
4104
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4105
            [
4106
                $user1->id,
4107
                $user2->id
4108
            ]
4109
        );
4110
        $conversationid = $conversation->id;
4111
 
4112
        $this->assertNull(api::remove_members_from_conversation([0], $conversationid));
4113
        $this->assertEquals(2,
4114
            api::count_conversation_members($conversationid));
4115
    }
4116
 
4117
    /**
4118
     * Test remove_members_from_conversation for multiple users.
4119
     */
4120
    public function test_remove_members_for_multiple_users() {
4121
        $user1 = self::getDataGenerator()->create_user();
4122
        $user2 = self::getDataGenerator()->create_user();
4123
        $user3 = self::getDataGenerator()->create_user();
4124
        $user4 = self::getDataGenerator()->create_user();
4125
 
4126
        $conversation = api::create_conversation(
4127
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4128
            [
4129
                $user1->id,
4130
                $user2->id
4131
            ]
4132
        );
4133
        $conversationid = $conversation->id;
4134
 
4135
        $this->assertNull(api::add_members_to_conversation([$user3->id, $user4->id], $conversationid));
4136
        $this->assertNull(api::remove_members_from_conversation([$user3->id, $user4->id], $conversationid));
4137
        $this->assertEquals(2,
4138
            api::count_conversation_members($conversationid));
4139
    }
4140
 
4141
    /**
4142
     * Test remove_members_from_conversation for multiple non valid users.
4143
     */
4144
    public function test_remove_members_for_multiple_no_valid_users() {
4145
        $user1 = self::getDataGenerator()->create_user();
4146
        $user2 = self::getDataGenerator()->create_user();
4147
        $user3 = self::getDataGenerator()->create_user();
4148
        $user4 = self::getDataGenerator()->create_user();
4149
 
4150
        $conversation = api::create_conversation(
4151
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4152
            [
4153
                $user1->id,
4154
                $user2->id
4155
            ]
4156
        );
4157
        $conversationid = $conversation->id;
4158
 
4159
        $this->assertNull(api::add_members_to_conversation([$user3->id], $conversationid));
4160
        $this->assertNull(
4161
            api::remove_members_from_conversation([$user2->id, $user3->id, $user4->id, 0], $conversationid)
4162
        );
4163
        $this->assertEquals(1,
4164
            api::count_conversation_members($conversationid));
4165
    }
4166
 
4167
    /**
4168
     * Test count_conversation_members for empty conversation.
4169
     */
4170
    public function test_count_conversation_members_empty_conversation() {
4171
        $user1 = self::getDataGenerator()->create_user();
4172
        $user2 = self::getDataGenerator()->create_user();
4173
 
4174
        $conversation = api::create_conversation(
4175
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4176
            [
4177
                $user1->id,
4178
                $user2->id
4179
            ]
4180
        );
4181
        $conversationid = $conversation->id;
4182
 
4183
        $this->assertNull(api::remove_members_from_conversation([$user1->id, $user2->id], $conversationid));
4184
 
4185
        $this->assertEquals(0,
4186
            api::count_conversation_members($conversationid));
4187
    }
4188
 
4189
    /**
4190
     * Test can create a contact request.
4191
     */
4192
    public function test_can_create_contact_request() {
4193
        global $CFG;
4194
 
4195
        $user1 = self::getDataGenerator()->create_user();
4196
        $user2 = self::getDataGenerator()->create_user();
4197
 
4198
        // Disable messaging.
4199
        $CFG->messaging = 0;
4200
        $this->assertFalse(api::can_create_contact($user1->id, $user2->id));
4201
 
4202
        // Re-enable messaging.
4203
        $CFG->messaging = 1;
4204
 
4205
        // Allow users to message anyone site-wide.
4206
        $CFG->messagingallusers = 1;
4207
        $this->assertTrue(api::can_create_contact($user1->id, $user2->id));
4208
 
4209
        // Disallow users from messaging anyone site-wide.
4210
        $CFG->messagingallusers = 0;
4211
        $this->assertFalse(api::can_create_contact($user1->id, $user2->id));
4212
 
4213
        // Put the users in the same course so a contact request should be possible.
4214
        $course = self::getDataGenerator()->create_course();
4215
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
4216
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
4217
        $this->assertTrue(api::can_create_contact($user1->id, $user2->id));
4218
    }
4219
 
4220
    /**
4221
     * Test creating a contact request.
4222
     */
4223
    public function test_create_contact_request() {
4224
        global $DB;
4225
 
4226
        $user1 = self::getDataGenerator()->create_user();
4227
        $user2 = self::getDataGenerator()->create_user();
4228
 
4229
        $sink = $this->redirectMessages();
4230
        $request = api::create_contact_request($user1->id, $user2->id);
4231
        $messages = $sink->get_messages();
4232
        $sink->close();
4233
        // Test customdata.
4234
        $customdata = json_decode($messages[0]->customdata);
4235
        $this->assertObjectHasProperty('notificationiconurl', $customdata);
4236
        $this->assertObjectHasProperty('actionbuttons', $customdata);
4237
        $this->assertCount(2, (array) $customdata->actionbuttons);
4238
 
4239
        $this->assertEquals($user1->id, $request->userid);
4240
        $this->assertEquals($user2->id, $request->requesteduserid);
4241
    }
4242
 
4243
    /**
4244
     * Test confirming a contact request.
4245
     */
4246
    public function test_confirm_contact_request() {
4247
        global $DB;
4248
 
4249
        $user1 = self::getDataGenerator()->create_user();
4250
        $user2 = self::getDataGenerator()->create_user();
4251
 
4252
        api::create_contact_request($user1->id, $user2->id);
4253
 
4254
        api::confirm_contact_request($user1->id, $user2->id);
4255
 
4256
        $this->assertEquals(0, $DB->count_records('message_contact_requests'));
4257
 
4258
        $contact = $DB->get_records('message_contacts');
4259
 
4260
        $this->assertCount(1, $contact);
4261
 
4262
        $contact = reset($contact);
4263
 
4264
        $this->assertEquals($user1->id, $contact->userid);
4265
        $this->assertEquals($user2->id, $contact->contactid);
4266
    }
4267
 
4268
    /**
4269
     * Test declining a contact request.
4270
     */
4271
    public function test_decline_contact_request() {
4272
        global $DB;
4273
 
4274
        $user1 = self::getDataGenerator()->create_user();
4275
        $user2 = self::getDataGenerator()->create_user();
4276
 
4277
        api::create_contact_request($user1->id, $user2->id);
4278
 
4279
        api::decline_contact_request($user1->id, $user2->id);
4280
 
4281
        $this->assertEquals(0, $DB->count_records('message_contact_requests'));
4282
        $this->assertEquals(0, $DB->count_records('message_contacts'));
4283
    }
4284
 
4285
    /**
4286
     * Test retrieving contact requests.
4287
     */
4288
    public function test_get_contact_requests() {
4289
        global $PAGE;
4290
 
4291
        $user1 = self::getDataGenerator()->create_user();
4292
        $user2 = self::getDataGenerator()->create_user();
4293
        $user3 = self::getDataGenerator()->create_user();
4294
 
4295
        // Block one user, their request should not show up.
4296
        api::block_user($user1->id, $user3->id);
4297
 
4298
        api::create_contact_request($user2->id, $user1->id);
4299
        api::create_contact_request($user3->id, $user1->id);
4300
 
4301
        $requests = api::get_contact_requests($user1->id);
4302
 
4303
        $this->assertCount(1, $requests);
4304
 
4305
        $request = reset($requests);
4306
        $userpicture = new \user_picture($user2);
4307
        $profileimageurl = $userpicture->get_url($PAGE)->out(false);
4308
 
4309
        $this->assertEquals($user2->id, $request->id);
4310
        $this->assertEquals(fullname($user2), $request->fullname);
4311
        $this->assertObjectHasProperty('profileimageurl', $request);
4312
        $this->assertObjectHasProperty('profileimageurlsmall', $request);
4313
        $this->assertObjectHasProperty('isonline', $request);
4314
        $this->assertObjectHasProperty('showonlinestatus', $request);
4315
        $this->assertObjectHasProperty('isblocked', $request);
4316
        $this->assertObjectHasProperty('iscontact', $request);
4317
    }
4318
 
4319
    /**
4320
     * Test the get_contact_requests() function when the user has blocked the sender of the request.
4321
     */
4322
    public function test_get_contact_requests_blocked_sender() {
4323
        $user1 = self::getDataGenerator()->create_user();
4324
        $user2 = self::getDataGenerator()->create_user();
4325
 
4326
        // User1 blocks User2.
4327
        api::block_user($user1->id, $user2->id);
4328
 
4329
        // User2 tries to add User1 as a contact.
4330
        api::create_contact_request($user2->id, $user1->id);
4331
 
4332
        // Verify we don't see the contact request from the blocked user User2 in the requests for User1.
4333
        $requests = api::get_contact_requests($user1->id);
4334
        $this->assertEmpty($requests);
4335
    }
4336
 
4337
    /**
4338
     * Test getting contact requests when there are none.
4339
     */
4340
    public function test_get_contact_requests_no_requests() {
4341
        $this->resetAfterTest();
4342
 
4343
        $user1 = self::getDataGenerator()->create_user();
4344
 
4345
        $requests = api::get_contact_requests($user1->id);
4346
 
4347
        $this->assertEmpty($requests);
4348
    }
4349
 
4350
    /**
4351
     * Test getting contact requests with limits.
4352
     */
4353
    public function test_get_contact_requests_with_limits() {
4354
        $this->resetAfterTest();
4355
 
4356
        $user1 = self::getDataGenerator()->create_user();
4357
        $user2 = self::getDataGenerator()->create_user();
4358
        $user3 = self::getDataGenerator()->create_user();
4359
 
4360
        api::create_contact_request($user2->id, $user1->id);
4361
        api::create_contact_request($user3->id, $user1->id);
4362
 
4363
        $requests = api::get_contact_requests($user1->id, 0, 1);
4364
 
4365
        $this->assertCount(1, $requests);
4366
    }
4367
 
4368
    /**
4369
     * Test adding contacts.
4370
     */
4371
    public function test_add_contact() {
4372
        global $DB;
4373
 
4374
        $user1 = self::getDataGenerator()->create_user();
4375
        $user2 = self::getDataGenerator()->create_user();
4376
 
4377
        api::add_contact($user1->id, $user2->id);
4378
 
4379
        $contact = $DB->get_records('message_contacts');
4380
 
4381
        $this->assertCount(1, $contact);
4382
 
4383
        $contact = reset($contact);
4384
 
4385
        $this->assertEquals($user1->id, $contact->userid);
4386
        $this->assertEquals($user2->id, $contact->contactid);
4387
    }
4388
 
4389
    /**
4390
     * Test removing contacts.
4391
     */
4392
    public function test_remove_contact() {
4393
        global $DB;
4394
 
4395
        $user1 = self::getDataGenerator()->create_user();
4396
        $user2 = self::getDataGenerator()->create_user();
4397
 
4398
        api::add_contact($user1->id, $user2->id);
4399
        api::remove_contact($user1->id, $user2->id);
4400
 
4401
        $this->assertEquals(0, $DB->count_records('message_contacts'));
4402
    }
4403
 
4404
    /**
4405
     * Test blocking users.
4406
     */
4407
    public function test_block_user() {
4408
        global $DB;
4409
 
4410
        $user1 = self::getDataGenerator()->create_user();
4411
        $user2 = self::getDataGenerator()->create_user();
4412
 
4413
        api::block_user($user1->id, $user2->id);
4414
 
4415
        $blockedusers = $DB->get_records('message_users_blocked');
4416
 
4417
        $this->assertCount(1, $blockedusers);
4418
 
4419
        $blockeduser = reset($blockedusers);
4420
 
4421
        $this->assertEquals($user1->id, $blockeduser->userid);
4422
        $this->assertEquals($user2->id, $blockeduser->blockeduserid);
4423
    }
4424
 
4425
    /**
4426
     * Test unblocking users.
4427
     */
4428
    public function test_unblock_user() {
4429
        global $DB;
4430
 
4431
        $user1 = self::getDataGenerator()->create_user();
4432
        $user2 = self::getDataGenerator()->create_user();
4433
 
4434
        api::block_user($user1->id, $user2->id);
4435
        api::unblock_user($user1->id, $user2->id);
4436
 
4437
        $this->assertEquals(0, $DB->count_records('message_users_blocked'));
4438
    }
4439
 
4440
    /**
4441
     * Test muting a conversation.
4442
     */
4443
    public function test_mute_conversation() {
4444
        global $DB;
4445
 
4446
        $user1 = self::getDataGenerator()->create_user();
4447
        $user2 = self::getDataGenerator()->create_user();
4448
 
4449
        $conversation = api::create_conversation(
4450
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4451
            [
4452
                $user1->id,
4453
                $user2->id
4454
            ]
4455
        );
4456
        $conversationid = $conversation->id;
4457
 
4458
        api::mute_conversation($user1->id, $conversationid);
4459
 
4460
        $mutedconversation = $DB->get_records('message_conversation_actions');
4461
 
4462
        $this->assertCount(1, $mutedconversation);
4463
 
4464
        $mutedconversation = reset($mutedconversation);
4465
 
4466
        $this->assertEquals($user1->id, $mutedconversation->userid);
4467
        $this->assertEquals($conversationid, $mutedconversation->conversationid);
4468
        $this->assertEquals(api::CONVERSATION_ACTION_MUTED, $mutedconversation->action);
4469
    }
4470
 
4471
    /**
4472
     * Test unmuting a conversation.
4473
     */
4474
    public function test_unmute_conversation() {
4475
        global $DB;
4476
 
4477
        $user1 = self::getDataGenerator()->create_user();
4478
        $user2 = self::getDataGenerator()->create_user();
4479
 
4480
        $conversation = api::create_conversation(
4481
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4482
            [
4483
                $user1->id,
4484
                $user2->id
4485
            ]
4486
        );
4487
        $conversationid = $conversation->id;
4488
 
4489
        api::mute_conversation($user1->id, $conversationid);
4490
        api::unmute_conversation($user1->id, $conversationid);
4491
 
4492
        $this->assertEquals(0, $DB->count_records('message_conversation_actions'));
4493
    }
4494
 
4495
    /**
4496
     * Test if a conversation is muted.
4497
     */
4498
    public function test_is_conversation_muted() {
4499
        $user1 = self::getDataGenerator()->create_user();
4500
        $user2 = self::getDataGenerator()->create_user();
4501
 
4502
        $conversation = api::create_conversation(
4503
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4504
            [
4505
                $user1->id,
4506
                $user2->id
4507
            ]
4508
        );
4509
        $conversationid = $conversation->id;
4510
 
4511
        $this->assertFalse(api::is_conversation_muted($user1->id, $conversationid));
4512
 
4513
        api::mute_conversation($user1->id, $conversationid);
4514
 
4515
        $this->assertTrue(api::is_conversation_muted($user1->id, $conversationid));
4516
    }
4517
 
4518
    /**
4519
     * Test is contact check.
4520
     */
4521
    public function test_is_contact() {
4522
        $user1 = self::getDataGenerator()->create_user();
4523
        $user2 = self::getDataGenerator()->create_user();
4524
        $user3 = self::getDataGenerator()->create_user();
4525
 
4526
        api::add_contact($user1->id, $user2->id);
4527
 
4528
        $this->assertTrue(api::is_contact($user1->id, $user2->id));
4529
        $this->assertTrue(api::is_contact($user2->id, $user1->id));
4530
        $this->assertFalse(api::is_contact($user2->id, $user3->id));
4531
    }
4532
 
4533
    /**
4534
     * Test get contact.
4535
     */
4536
    public function test_get_contact() {
4537
        $user1 = self::getDataGenerator()->create_user();
4538
        $user2 = self::getDataGenerator()->create_user();
4539
 
4540
        api::add_contact($user1->id, $user2->id);
4541
 
4542
        $contact = api::get_contact($user1->id, $user2->id);
4543
 
4544
        $this->assertEquals($user1->id, $contact->userid);
4545
        $this->assertEquals($user2->id, $contact->contactid);
4546
    }
4547
 
4548
    /**
4549
     * Test is blocked checked.
4550
     */
4551
    public function test_is_blocked() {
4552
        $user1 = self::getDataGenerator()->create_user();
4553
        $user2 = self::getDataGenerator()->create_user();
4554
 
4555
        $this->assertFalse(api::is_blocked($user1->id, $user2->id));
4556
        $this->assertFalse(api::is_blocked($user2->id, $user1->id));
4557
 
4558
        api::block_user($user1->id, $user2->id);
4559
 
4560
        $this->assertTrue(api::is_blocked($user1->id, $user2->id));
4561
        $this->assertFalse(api::is_blocked($user2->id, $user1->id));
4562
    }
4563
 
4564
    /**
4565
     * Test the contact request exist check.
4566
     */
4567
    public function test_does_contact_request_exist() {
4568
        $user1 = self::getDataGenerator()->create_user();
4569
        $user2 = self::getDataGenerator()->create_user();
4570
 
4571
        $this->assertFalse(api::does_contact_request_exist($user1->id, $user2->id));
4572
        $this->assertFalse(api::does_contact_request_exist($user2->id, $user1->id));
4573
 
4574
        api::create_contact_request($user1->id, $user2->id);
4575
 
4576
        $this->assertTrue(api::does_contact_request_exist($user1->id, $user2->id));
4577
        $this->assertTrue(api::does_contact_request_exist($user2->id, $user1->id));
4578
    }
4579
 
4580
    /**
4581
     * Test the get_received_contact_requests_count() function.
4582
     */
4583
    public function test_get_received_contact_requests_count() {
4584
        $user1 = self::getDataGenerator()->create_user();
4585
        $user2 = self::getDataGenerator()->create_user();
4586
        $user3 = self::getDataGenerator()->create_user();
4587
        $user4 = self::getDataGenerator()->create_user();
4588
 
4589
        $this->assertEquals(0, api::get_received_contact_requests_count($user1->id));
4590
 
4591
        api::create_contact_request($user2->id, $user1->id);
4592
 
4593
        $this->assertEquals(1, api::get_received_contact_requests_count($user1->id));
4594
 
4595
        api::create_contact_request($user3->id, $user1->id);
4596
 
4597
        $this->assertEquals(2, api::get_received_contact_requests_count($user1->id));
4598
 
4599
        api::create_contact_request($user1->id, $user4->id);
4600
        // Function should ignore sent requests.
4601
        $this->assertEquals(2, api::get_received_contact_requests_count($user1->id));
4602
    }
4603
 
4604
    /**
4605
     * Test the get_received_contact_requests_count() function when the user has blocked the sender of the request.
4606
     */
4607
    public function test_get_received_contact_requests_count_blocked_sender() {
4608
        $user1 = self::getDataGenerator()->create_user();
4609
        $user2 = self::getDataGenerator()->create_user();
4610
 
4611
        // User1 blocks User2.
4612
        api::block_user($user1->id, $user2->id);
4613
 
4614
        // User2 tries to add User1 as a contact.
4615
        api::create_contact_request($user2->id, $user1->id);
4616
 
4617
        // Verify we don't see the contact request from the blocked user User2 in the count for User1.
4618
        $this->assertEquals(0, api::get_received_contact_requests_count($user1->id));
4619
    }
4620
 
4621
    /**
4622
     * Test the get_contact_requests_between_users() function.
4623
     */
4624
    public function test_get_contact_requests_between_users() {
4625
        $user1 = self::getDataGenerator()->create_user();
4626
        $user2 = self::getDataGenerator()->create_user();
4627
        $user3 = self::getDataGenerator()->create_user();
4628
        $user4 = self::getDataGenerator()->create_user();
4629
 
4630
        $this->assertEquals([], api::get_contact_requests_between_users($user1->id, $user2->id));
4631
 
4632
        $request1 = api::create_contact_request($user2->id, $user1->id);
4633
        $results = api::get_contact_requests_between_users($user1->id, $user2->id);
4634
        $results = array_values($results);
4635
 
4636
        $this->assertCount(1, $results);
4637
        $result = $results[0];
4638
        $this->assertEquals($request1->id, $result->id);
4639
 
4640
        $request2 = api::create_contact_request($user1->id, $user2->id);
4641
        $results = api::get_contact_requests_between_users($user1->id, $user2->id);
4642
        $results = array_values($results);
4643
 
4644
        $this->assertCount(2, $results);
4645
        $actual = [(int) $results[0]->id, (int) $results[1]->id];
4646
        $expected = [(int) $request1->id, (int) $request2->id];
4647
 
4648
        sort($actual);
4649
        sort($expected);
4650
 
4651
        $this->assertEquals($expected, $actual);
4652
 
4653
        // Request from a different user.
4654
        api::create_contact_request($user3->id, $user1->id);
4655
 
4656
        $results = api::get_contact_requests_between_users($user1->id, $user2->id);
4657
        $results = array_values($results);
4658
 
4659
        $this->assertCount(2, $results);
4660
        $actual = [(int) $results[0]->id, (int) $results[1]->id];
4661
        $expected = [(int) $request1->id, (int) $request2->id];
4662
 
4663
        sort($actual);
4664
        sort($expected);
4665
 
4666
        $this->assertEquals($expected, $actual);
4667
    }
4668
 
4669
    /**
4670
     * Test the user in conversation check.
4671
     */
4672
    public function test_is_user_in_conversation() {
4673
        $user1 = self::getDataGenerator()->create_user();
4674
        $user2 = self::getDataGenerator()->create_user();
4675
 
4676
        $conversation = api::create_conversation(
4677
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4678
            [
4679
                $user1->id,
4680
                $user2->id
4681
            ]
4682
        );
4683
        $conversationid = $conversation->id;
4684
 
4685
        $this->assertTrue(api::is_user_in_conversation($user1->id, $conversationid));
4686
    }
4687
 
4688
    /**
4689
     * Test the user in conversation check when they are not.
4690
     */
4691
    public function test_is_user_in_conversation_when_not() {
4692
        $user1 = self::getDataGenerator()->create_user();
4693
        $user2 = self::getDataGenerator()->create_user();
4694
        $user3 = self::getDataGenerator()->create_user();
4695
 
4696
        $conversation = api::create_conversation(
4697
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4698
            [
4699
                $user1->id,
4700
                $user2->id
4701
            ]
4702
        );
4703
        $conversationid = $conversation->id;
4704
 
4705
        $this->assertFalse(api::is_user_in_conversation($user3->id, $conversationid));
4706
    }
4707
 
4708
    /**
4709
     * Test can create a group conversation.
4710
     */
4711
    public function test_can_create_group_conversation() {
4712
        global $CFG;
4713
 
4714
        $student = self::getDataGenerator()->create_user();
4715
        $teacher = self::getDataGenerator()->create_user();
4716
        $course = self::getDataGenerator()->create_course();
4717
 
4718
        $coursecontext = \context_course::instance($course->id);
4719
 
4720
        $this->getDataGenerator()->enrol_user($student->id, $course->id);
4721
        $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
4722
 
4723
        // Disable messaging.
4724
        $CFG->messaging = 0;
4725
        $this->assertFalse(api::can_create_group_conversation($student->id, $coursecontext));
4726
 
4727
        // Re-enable messaging.
4728
        $CFG->messaging = 1;
4729
 
4730
        // Student shouldn't be able to.
4731
        $this->assertFalse(api::can_create_group_conversation($student->id, $coursecontext));
4732
 
4733
        // Teacher should.
4734
        $this->assertTrue(api::can_create_group_conversation($teacher->id, $coursecontext));
4735
    }
4736
 
4737
    /**
4738
     * Test creating an individual conversation.
4739
     */
4740
    public function test_create_conversation_individual() {
4741
        $user1 = self::getDataGenerator()->create_user();
4742
        $user2 = self::getDataGenerator()->create_user();
4743
 
4744
        $conversation = api::create_conversation(
4745
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
4746
            [
4747
                $user1->id,
4748
                $user2->id
4749
            ],
4750
            'A conversation name'
4751
        );
4752
 
4753
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, $conversation->type);
4754
        $this->assertEquals('A conversation name', $conversation->name);
4755
        $this->assertEquals(helper::get_conversation_hash([$user1->id, $user2->id]), $conversation->convhash);
4756
 
4757
        $this->assertCount(2, $conversation->members);
4758
 
4759
        $member1 = array_shift($conversation->members);
4760
        $member2 = array_shift($conversation->members);
4761
 
4762
        $this->assertEquals($user1->id, $member1->userid);
4763
        $this->assertEquals($conversation->id, $member1->conversationid);
4764
 
4765
        $this->assertEquals($user2->id, $member2->userid);
4766
        $this->assertEquals($conversation->id, $member2->conversationid);
4767
    }
4768
 
4769
    /**
4770
     * Test creating a group conversation.
4771
     */
4772
    public function test_create_conversation_group() {
4773
        $user1 = self::getDataGenerator()->create_user();
4774
        $user2 = self::getDataGenerator()->create_user();
4775
        $user3 = self::getDataGenerator()->create_user();
4776
 
4777
        $conversation = api::create_conversation(
4778
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4779
            [
4780
                $user1->id,
4781
                $user2->id,
4782
                $user3->id
4783
            ],
4784
            'A conversation name'
4785
        );
4786
 
4787
        $this->assertEquals(api::MESSAGE_CONVERSATION_TYPE_GROUP, $conversation->type);
4788
        $this->assertEquals('A conversation name', $conversation->name);
4789
        $this->assertNull($conversation->convhash);
4790
 
4791
        $this->assertCount(3, $conversation->members);
4792
 
4793
        $member1 = array_shift($conversation->members);
4794
        $member2 = array_shift($conversation->members);
4795
        $member3 = array_shift($conversation->members);
4796
 
4797
        $this->assertEquals($user1->id, $member1->userid);
4798
        $this->assertEquals($conversation->id, $member1->conversationid);
4799
 
4800
        $this->assertEquals($user2->id, $member2->userid);
4801
        $this->assertEquals($conversation->id, $member2->conversationid);
4802
 
4803
        $this->assertEquals($user3->id, $member3->userid);
4804
        $this->assertEquals($conversation->id, $member3->conversationid);
4805
    }
4806
 
4807
    /**
4808
     * Test creating an invalid conversation.
4809
     */
4810
    public function test_create_conversation_invalid() {
4811
        $this->expectException('moodle_exception');
4812
        api::create_conversation(3, [1, 2, 3]);
4813
    }
4814
 
4815
    /**
4816
     * Test creating an individual conversation with too many members.
4817
     */
4818
    public function test_create_conversation_individual_too_many_members() {
4819
        $this->expectException('moodle_exception');
4820
        api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, [1, 2, 3]);
4821
    }
4822
 
4823
    /**
4824
     * Test create message conversation with area.
4825
     */
4826
    public function test_create_conversation_with_area() {
4827
        $contextid = 111;
4828
        $itemid = 222;
4829
        $name = 'Name of conversation';
4830
        $conversation = api::create_conversation(
4831
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4832
            [],
4833
            $name,
4834
            api::MESSAGE_CONVERSATION_DISABLED,
4835
            'core_group',
4836
            'groups',
4837
            $itemid,
4838
            $contextid
4839
        );
4840
 
4841
        $this->assertEquals(api::MESSAGE_CONVERSATION_DISABLED, $conversation->enabled);
4842
        $this->assertEquals('core_group', $conversation->component);
4843
        $this->assertEquals('groups', $conversation->itemtype);
4844
        $this->assertEquals($itemid, $conversation->itemid);
4845
        $this->assertEquals($contextid, $conversation->contextid);
4846
    }
4847
 
4848
    /**
4849
     * Test get_conversation_by_area.
4850
     */
4851
    public function test_get_conversation_by_area() {
4852
        $contextid = 111;
4853
        $itemid = 222;
4854
        $name = 'Name of conversation';
4855
        $createconversation = api::create_conversation(
4856
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4857
            [],
4858
            $name,
4859
            api::MESSAGE_CONVERSATION_DISABLED,
4860
            'core_group',
4861
            'groups',
4862
            $itemid,
4863
            $contextid
4864
        );
4865
        $conversation = api::get_conversation_by_area('core_group', 'groups', $itemid, $contextid);
4866
 
4867
        $this->assertEquals($createconversation->id, $conversation->id);
4868
        $this->assertEquals(api::MESSAGE_CONVERSATION_DISABLED, $conversation->enabled);
4869
        $this->assertEquals('core_group', $conversation->component);
4870
        $this->assertEquals('groups', $conversation->itemtype);
4871
        $this->assertEquals($itemid, $conversation->itemid);
4872
        $this->assertEquals($contextid, $conversation->contextid);
4873
    }
4874
 
4875
    /**
4876
     * Test enable_conversation.
4877
     */
4878
    public function test_enable_conversation() {
4879
        global $DB;
4880
 
4881
        $name = 'Name of conversation';
4882
 
4883
        $conversation = api::create_conversation(
4884
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4885
            [],
4886
            $name,
4887
            api::MESSAGE_CONVERSATION_DISABLED
4888
        );
4889
 
4890
        $this->assertEquals(api::MESSAGE_CONVERSATION_DISABLED, $conversation->enabled);
4891
        api::enable_conversation($conversation->id);
4892
        $conversationenabled = $DB->get_field('message_conversations', 'enabled', ['id' => $conversation->id]);
4893
        $this->assertEquals(api::MESSAGE_CONVERSATION_ENABLED, $conversationenabled);
4894
    }
4895
 
4896
    /**
4897
     * Test disable_conversation.
4898
     */
4899
    public function test_disable_conversation() {
4900
        global $DB;
4901
 
4902
        $name = 'Name of conversation';
4903
 
4904
        $conversation = api::create_conversation(
4905
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4906
            [],
4907
            $name,
4908
            api::MESSAGE_CONVERSATION_ENABLED
4909
        );
4910
 
4911
        $this->assertEquals(api::MESSAGE_CONVERSATION_ENABLED, $conversation->enabled);
4912
        api::disable_conversation($conversation->id);
4913
        $conversationenabled = $DB->get_field('message_conversations', 'enabled', ['id' => $conversation->id]);
4914
        $this->assertEquals(api::MESSAGE_CONVERSATION_DISABLED, $conversationenabled);
4915
    }
4916
 
4917
    /**
4918
     * Test update_conversation_name.
4919
     */
4920
    public function test_update_conversation_name() {
4921
        global $DB;
4922
 
4923
        $conversation = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_GROUP, []);
4924
 
4925
        $newname = 'New name of conversation';
4926
        api::update_conversation_name($conversation->id, $newname);
4927
 
4928
        $this->assertEquals(
4929
                $newname,
4930
                $DB->get_field('message_conversations', 'name', ['id' => $conversation->id])
4931
        );
4932
    }
4933
 
4934
    /**
4935
     * Test returning members in a conversation with no contact requests.
4936
     */
4937
    public function test_get_conversation_members() {
4938
        $lastaccess = new \stdClass();
4939
        $lastaccess->lastaccess = time();
4940
 
4941
        $user1 = self::getDataGenerator()->create_user($lastaccess);
4942
        $user2 = self::getDataGenerator()->create_user();
4943
        $user3 = self::getDataGenerator()->create_user();
4944
 
4945
        // This user will not be in the conversation, but a contact request will exist for them.
4946
        $user4 = self::getDataGenerator()->create_user();
4947
 
4948
        // Add some contact requests.
4949
        api::create_contact_request($user1->id, $user3->id);
4950
        api::create_contact_request($user1->id, $user4->id);
4951
        api::create_contact_request($user2->id, $user3->id);
4952
 
4953
        // User 1 and 2 are already contacts.
4954
        api::add_contact($user1->id, $user2->id);
4955
 
4956
        // User 1 has blocked user 3.
4957
        api::block_user($user1->id, $user3->id);
4958
        $conversation = api::create_conversation(
4959
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
4960
            [
4961
                $user1->id,
4962
                $user2->id,
4963
                $user3->id
4964
            ]
4965
        );
4966
        $conversationid = $conversation->id;
4967
        $members = api::get_conversation_members($user1->id, $conversationid, false);
4968
 
4969
        // Sort them by id.
4970
        ksort($members);
4971
        $this->assertCount(3, $members);
4972
        $member1 = array_shift($members);
4973
        $member2 = array_shift($members);
4974
        $member3 = array_shift($members);
4975
 
4976
        // Confirm the standard fields are OK.
4977
        $this->assertEquals($user1->id, $member1->id);
4978
        $this->assertEquals(fullname($user1), $member1->fullname);
4979
        $this->assertEquals(true, $member1->isonline);
4980
        $this->assertEquals(true, $member1->showonlinestatus);
4981
        $this->assertEquals(false, $member1->iscontact);
4982
        $this->assertEquals(false, $member1->isblocked);
4983
        $this->assertObjectHasProperty('contactrequests', $member1);
4984
        $this->assertEmpty($member1->contactrequests);
4985
 
4986
        $this->assertEquals($user2->id, $member2->id);
4987
        $this->assertEquals(fullname($user2), $member2->fullname);
4988
        $this->assertEquals(false, $member2->isonline);
4989
        $this->assertEquals(true, $member2->showonlinestatus);
4990
        $this->assertEquals(true, $member2->iscontact);
4991
        $this->assertEquals(false, $member2->isblocked);
4992
        $this->assertObjectHasProperty('contactrequests', $member2);
4993
        $this->assertEmpty($member2->contactrequests);
4994
 
4995
        $this->assertEquals($user3->id, $member3->id);
4996
        $this->assertEquals(fullname($user3), $member3->fullname);
4997
        $this->assertEquals(false, $member3->isonline);
4998
        $this->assertEquals(true, $member3->showonlinestatus);
4999
        $this->assertEquals(false, $member3->iscontact);
5000
        $this->assertEquals(true, $member3->isblocked);
5001
        $this->assertObjectHasProperty('contactrequests', $member3);
5002
        $this->assertEmpty($member3->contactrequests);
5003
    }
5004
 
5005
    /**
5006
     * Test returning members in a conversation with contact requests.
5007
     */
5008
    public function test_get_conversation_members_with_contact_requests() {
5009
        $lastaccess = new \stdClass();
5010
        $lastaccess->lastaccess = time();
5011
 
5012
        $user1 = self::getDataGenerator()->create_user($lastaccess);
5013
        $user2 = self::getDataGenerator()->create_user();
5014
        $user3 = self::getDataGenerator()->create_user();
5015
 
5016
        // This user will not be in the conversation, but a contact request will exist for them.
5017
        $user4 = self::getDataGenerator()->create_user();
5018
        // Add some contact requests.
5019
        api::create_contact_request($user1->id, $user2->id);
5020
        api::create_contact_request($user1->id, $user3->id);
5021
        api::create_contact_request($user1->id, $user4->id);
5022
        api::create_contact_request($user2->id, $user3->id);
5023
 
5024
        // User 1 and 2 are already contacts.
5025
        api::add_contact($user1->id, $user2->id);
5026
        // User 1 has blocked user 3.
5027
        api::block_user($user1->id, $user3->id);
5028
 
5029
        $conversation = api::create_conversation(
5030
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
5031
            [
5032
                $user1->id,
5033
                $user2->id,
5034
                $user3->id
5035
            ]
5036
        );
5037
        $conversationid = $conversation->id;
5038
 
5039
        $members = api::get_conversation_members($user1->id, $conversationid, true);
5040
 
5041
        // Sort them by id.
5042
        ksort($members);
5043
 
5044
        $this->assertCount(3, $members);
5045
 
5046
        $member1 = array_shift($members);
5047
        $member2 = array_shift($members);
5048
        $member3 = array_shift($members);
5049
 
5050
        // Confirm the standard fields are OK.
5051
        $this->assertEquals($user1->id, $member1->id);
5052
        $this->assertEquals(fullname($user1), $member1->fullname);
5053
        $this->assertEquals(true, $member1->isonline);
5054
        $this->assertEquals(true, $member1->showonlinestatus);
5055
        $this->assertEquals(false, $member1->iscontact);
5056
        $this->assertEquals(false, $member1->isblocked);
5057
        $this->assertCount(2, $member1->contactrequests);
5058
 
5059
        $this->assertEquals($user2->id, $member2->id);
5060
        $this->assertEquals(fullname($user2), $member2->fullname);
5061
        $this->assertEquals(false, $member2->isonline);
5062
        $this->assertEquals(true, $member2->showonlinestatus);
5063
        $this->assertEquals(true, $member2->iscontact);
5064
        $this->assertEquals(false, $member2->isblocked);
5065
        $this->assertCount(1, $member2->contactrequests);
5066
 
5067
        $this->assertEquals($user3->id, $member3->id);
5068
        $this->assertEquals(fullname($user3), $member3->fullname);
5069
        $this->assertEquals(false, $member3->isonline);
5070
        $this->assertEquals(true, $member3->showonlinestatus);
5071
        $this->assertEquals(false, $member3->iscontact);
5072
        $this->assertEquals(true, $member3->isblocked);
5073
        $this->assertCount(1, $member3->contactrequests);
5074
 
5075
        // Confirm the contact requests are OK.
5076
        $request1 = array_shift($member1->contactrequests);
5077
        $request2 = array_shift($member1->contactrequests);
5078
 
5079
        $this->assertEquals($user1->id, $request1->userid);
5080
        $this->assertEquals($user2->id, $request1->requesteduserid);
5081
 
5082
        $this->assertEquals($user1->id, $request2->userid);
5083
        $this->assertEquals($user3->id, $request2->requesteduserid);
5084
 
5085
        $request1 = array_shift($member2->contactrequests);
5086
 
5087
        $this->assertEquals($user1->id, $request1->userid);
5088
        $this->assertEquals($user2->id, $request1->requesteduserid);
5089
 
5090
        $request1 = array_shift($member3->contactrequests);
5091
 
5092
        $this->assertEquals($user1->id, $request1->userid);
5093
        $this->assertEquals($user3->id, $request1->requesteduserid);
5094
    }
5095
 
5096
    /**
5097
     * Test returning members of a self conversation.
5098
     */
5099
    public function test_get_conversation_members_with_self_conversation() {
5100
        $lastaccess = new \stdClass();
5101
        $lastaccess->lastaccess = time();
5102
 
5103
        $user1 = self::getDataGenerator()->create_user($lastaccess);
5104
 
5105
        $selfconversation = api::get_self_conversation($user1->id);
5106
        testhelper::send_fake_message_to_conversation($user1, $selfconversation->id, 'This is a self-message!');
5107
 
5108
        // Get the members for the self-conversation.
5109
        $members = api::get_conversation_members($user1->id, $selfconversation->id);
5110
        $this->assertCount(1, $members);
5111
 
5112
        $member1 = array_shift($members);
5113
 
5114
        // Confirm the standard fields are OK.
5115
        $this->assertEquals($user1->id, $member1->id);
5116
        $this->assertEquals(fullname($user1), $member1->fullname);
5117
        $this->assertEquals(true, $member1->isonline);
5118
        $this->assertEquals(true, $member1->showonlinestatus);
5119
        $this->assertEquals(false, $member1->iscontact);
5120
        $this->assertEquals(false, $member1->isblocked);
5121
    }
5122
 
5123
    /**
5124
     * Test verifying that messages can be sent to existing individual conversations.
5125
     */
5126
    public function test_send_message_to_conversation_individual_conversation() {
5127
        // Get a bunch of conversations, some group, some individual and in different states.
5128
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
5129
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
5130
 
5131
        // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
5132
        $course = $this->getDataGenerator()->create_course();
5133
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
5134
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
5135
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
5136
        $this->getDataGenerator()->enrol_user($user4->id, $course->id);
5137
 
5138
        // Redirect messages.
5139
        // This marks messages as read, but we can still observe and verify the number of conversation recipients,
5140
        // based on the message_viewed events generated as part of marking the message as read for each user.
5141
        $this->preventResetByRollback();
5142
        $sink = $this->redirectMessages();
5143
 
5144
        // Send a message to an individual conversation.
5145
        $sink = $this->redirectEvents();
5146
        $messagessink = $this->redirectMessages();
5147
        $message1 = api::send_message_to_conversation($user1->id, $ic1->id, 'this is a message', FORMAT_MOODLE);
5148
        $events = $sink->get_events();
5149
        $messages = $messagessink->get_messages();
5150
        // Test customdata.
5151
        $customdata = json_decode($messages[0]->customdata);
5152
        $this->assertObjectHasProperty('notificationiconurl', $customdata);
5153
        $this->assertObjectHasProperty('actionbuttons', $customdata);
5154
        $this->assertCount(1, (array) $customdata->actionbuttons);
5155
        $this->assertObjectHasProperty('placeholders', $customdata);
5156
        $this->assertCount(1, (array) $customdata->placeholders);
5157
 
5158
        // Verify the message returned.
5159
        $this->assertInstanceOf(\stdClass::class, $message1);
5160
        $this->assertObjectHasProperty('id', $message1);
5161
        $this->assertEquals($user1->id, $message1->useridfrom);
5162
        $this->assertEquals('this is a message', $message1->text);
5163
        $this->assertObjectHasProperty('timecreated', $message1);
5164
 
5165
        // Verify events. Note: the event is a message read event because of an if (PHPUNIT) conditional within message_send(),
5166
        // however, we can still determine the number and ids of any recipients this way.
5167
        $this->assertCount(1, $events);
5168
        $userids = array_column($events, 'userid');
5169
        $this->assertNotContainsEquals($user1->id, $userids);
5170
        $this->assertContainsEquals($user2->id, $userids);
5171
    }
5172
 
5173
    /**
5174
     * Test verifying that messages can be sent to existing group conversations.
5175
     */
5176
    public function test_send_message_to_conversation_group_conversation() {
5177
        // Get a bunch of conversations, some group, some individual and in different states.
5178
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
5179
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
5180
 
5181
        // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
5182
        $course = $this->getDataGenerator()->create_course();
5183
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
5184
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
5185
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
5186
        $this->getDataGenerator()->enrol_user($user4->id, $course->id);
5187
 
5188
        // Redirect messages.
5189
        // This marks messages as read, but we can still observe and verify the number of conversation recipients,
5190
        // based on the message_viewed events generated as part of marking the message as read for each user.
5191
        $this->preventResetByRollback();
5192
        $sink = $this->redirectMessages();
5193
 
5194
        // Send a message to a group conversation.
5195
        $sink = $this->redirectEvents();
5196
        $messagessink = $this->redirectMessages();
5197
        $message1 = api::send_message_to_conversation($user1->id, $gc2->id, 'message to the group', FORMAT_MOODLE);
5198
        $events = $sink->get_events();
5199
        $messages = $messagessink->get_messages();
5200
        // Verify the message returned.
5201
        $this->assertInstanceOf(\stdClass::class, $message1);
5202
        $this->assertObjectHasProperty('id', $message1);
5203
        $this->assertEquals($user1->id, $message1->useridfrom);
5204
        $this->assertEquals('message to the group', $message1->text);
5205
        $this->assertObjectHasProperty('timecreated', $message1);
5206
        // Test customdata.
5207
        $customdata = json_decode($messages[0]->customdata);
5208
        $this->assertObjectHasProperty('actionbuttons', $customdata);
5209
        $this->assertCount(1, (array) $customdata->actionbuttons);
5210
        $this->assertObjectHasProperty('placeholders', $customdata);
5211
        $this->assertCount(1, (array) $customdata->placeholders);
5212
        $this->assertObjectNotHasProperty('notificationiconurl', $customdata);    // No group image means no image.
5213
 
5214
        // Verify events. Note: the event is a message read event because of an if (PHPUNIT) conditional within message_send(),
5215
        // however, we can still determine the number and ids of any recipients this way.
5216
        $this->assertCount(2, $events);
5217
        $userids = array_column($events, 'userid');
5218
        $this->assertNotContainsEquals($user1->id, $userids);
5219
        $this->assertContainsEquals($user3->id, $userids);
5220
        $this->assertContainsEquals($user4->id, $userids);
5221
    }
5222
 
5223
    /**
5224
     * Test verifying that messages can be sent to existing linked group conversations.
5225
     */
5226
    public function test_send_message_to_conversation_linked_group_conversation() {
5227
        global $CFG, $PAGE;
5228
 
5229
        // Create some users.
5230
        $user1 = self::getDataGenerator()->create_user();
5231
        $user2 = self::getDataGenerator()->create_user();
5232
        $user3 = self::getDataGenerator()->create_user();
5233
 
5234
        $course = $this->getDataGenerator()->create_course();
5235
 
5236
        // Create a group with a linked conversation and a valid image.
5237
        $this->setAdminUser();
5238
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
5239
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
5240
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
5241
        $group = $this->getDataGenerator()->create_group([
5242
            'courseid' => $course->id,
5243
            'enablemessaging' => 1,
5244
            'picturepath' => $CFG->dirroot . '/lib/tests/fixtures/gd-logo.png'
5245
        ]);
5246
 
5247
        // Add users to group.
5248
        $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $user1->id));
5249
        $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $user2->id));
5250
 
5251
        // Verify the group with the image works as expected.
5252
        $conversations = api::get_conversations($user1->id);
5253
        $this->assertEquals(2, $conversations[0]->membercount);
5254
        $this->assertEquals($course->shortname, $conversations[0]->subname);
5255
        $groupimageurl = get_group_picture_url($group, $group->courseid, true);
5256
        $this->assertEquals($groupimageurl, $conversations[0]->imageurl);
5257
 
5258
        // Redirect messages.
5259
        // This marks messages as read, but we can still observe and verify the number of conversation recipients,
5260
        // based on the message_viewed events generated as part of marking the message as read for each user.
5261
        $this->preventResetByRollback();
5262
        $sink = $this->redirectMessages();
5263
 
5264
        // Send a message to a group conversation.
5265
        $messagessink = $this->redirectMessages();
5266
        $message1 = api::send_message_to_conversation($user1->id, $conversations[0]->id,
5267
            'message to the group', FORMAT_MOODLE);
5268
        $messages = $messagessink->get_messages();
5269
        // Verify the message returned.
5270
        $this->assertInstanceOf(\stdClass::class, $message1);
5271
        $this->assertObjectHasProperty('id', $message1);
5272
        $this->assertEquals($user1->id, $message1->useridfrom);
5273
        $this->assertEquals('message to the group', $message1->text);
5274
        $this->assertObjectHasProperty('timecreated', $message1);
5275
        // Test customdata.
5276
        $customdata = json_decode($messages[0]->customdata);
5277
        $this->assertObjectHasProperty('notificationiconurl', $customdata);
5278
        $this->assertObjectHasProperty('notificationsendericonurl', $customdata);
5279
        $this->assertEquals($groupimageurl, $customdata->notificationiconurl);
5280
        $this->assertEquals($group->name, $customdata->conversationname);
5281
        $userpicture = new \user_picture($user1);
5282
        $userpicture->size = 1; // Use f1 size.
5283
        $this->assertEquals($userpicture->get_url($PAGE)->out(false), $customdata->notificationsendericonurl);
5284
    }
5285
 
5286
    /**
5287
     * Test verifying that messages cannot be sent to conversations that don't exist.
5288
     */
5289
    public function test_send_message_to_conversation_non_existent_conversation() {
5290
        // Get a bunch of conversations, some group, some individual and in different states.
5291
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
5292
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
5293
 
5294
        $this->expectException(\moodle_exception::class);
5295
        api::send_message_to_conversation($user1->id, 0, 'test', FORMAT_MOODLE);
5296
    }
5297
 
5298
    /**
5299
     * Test verifying that messages cannot be sent to conversations by users who are not members.
5300
     */
5301
    public function test_send_message_to_conversation_non_member() {
5302
        // Get a bunch of conversations, some group, some individual and in different states.
5303
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
5304
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
5305
 
5306
        // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
5307
        $course = $this->getDataGenerator()->create_course();
5308
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
5309
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
5310
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
5311
        $this->getDataGenerator()->enrol_user($user4->id, $course->id);
5312
 
5313
        $this->expectException(\moodle_exception::class);
5314
        api::send_message_to_conversation($user3->id, $ic1->id, 'test', FORMAT_MOODLE);
5315
    }
5316
 
5317
    /**
5318
     * Test verifying that messages cannot be sent to conversations by users who are not members.
5319
     */
5320
    public function test_send_message_to_conversation_blocked_user() {
5321
        // Get a bunch of conversations, some group, some individual and in different states.
5322
        list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3,
5323
            $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data();
5324
 
5325
        // Enrol the users into the same course so the privacy checks will pass using default (contact+course members) setting.
5326
        $course = $this->getDataGenerator()->create_course();
5327
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
5328
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
5329
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
5330
        $this->getDataGenerator()->enrol_user($user4->id, $course->id);
5331
 
5332
        // User 1 blocks user 2.
5333
        api::block_user($user1->id, $user2->id);
5334
 
5335
        // Verify that a message can be sent to any group conversation in which user1 and user2 are members.
5336
        $this->assertNotEmpty(api::send_message_to_conversation($user1->id, $gc2->id, 'Hey guys', FORMAT_PLAIN));
5337
 
5338
        // User 2 cannot send a message to the conversation with user 1.
5339
        $this->expectException(\moodle_exception::class);
5340
        api::send_message_to_conversation($user2->id, $ic1->id, 'test', FORMAT_MOODLE);
5341
    }
5342
 
5343
    /**
5344
     * Test the get_conversation() function with a muted conversation.
5345
     */
5346
    public function test_get_conversation_with_muted_conversation() {
5347
        $this->resetAfterTest();
5348
 
5349
        $user1 = self::getDataGenerator()->create_user();
5350
        $user2 = self::getDataGenerator()->create_user();
5351
 
5352
        $this->setUser($user1);
5353
 
5354
        $conversation = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
5355
            [$user1->id, $user2->id]);
5356
 
5357
        $conversation = api::get_conversation($user1->id, $conversation->id);
5358
 
5359
        $this->assertFalse($conversation->ismuted);
5360
 
5361
        // Now, mute the conversation.
5362
        api::mute_conversation($user1->id, $conversation->id);
5363
 
5364
        $conversation = api::get_conversation($user1->id, $conversation->id);
5365
 
5366
        $this->assertTrue($conversation->ismuted);
5367
    }
5368
 
5369
    /**
5370
     * Data provider for test_get_conversation_counts().
5371
     */
5372
    public function get_conversation_counts_test_cases() {
5373
        $typeindividual = api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
5374
        $typegroup = api::MESSAGE_CONVERSATION_TYPE_GROUP;
5375
        $typeself = api::MESSAGE_CONVERSATION_TYPE_SELF;
5376
        list($user1, $user2, $user3, $user4, $user5, $user6, $user7, $user8) = [0, 1, 2, 3, 4, 5, 6, 7];
5377
        $conversations = [
5378
            [
5379
                'type' => $typeindividual,
5380
                'users' => [$user1, $user2],
5381
                'messages' => [$user1, $user2, $user2],
5382
                'favourites' => [$user1],
5383
                'enabled' => null // Individual conversations cannot be disabled.
5384
            ],
5385
            [
5386
                'type' => $typeindividual,
5387
                'users' => [$user1, $user3],
5388
                'messages' => [$user1, $user3, $user1],
5389
                'favourites' => [],
5390
                'enabled' => null // Individual conversations cannot be disabled.
5391
            ],
5392
            [
5393
                'type' => $typegroup,
5394
                'users' => [$user1, $user2, $user3, $user4],
5395
                'messages' => [$user1, $user2, $user3, $user4],
5396
                'favourites' => [],
5397
                'enabled' => true
5398
            ],
5399
            [
5400
                'type' => $typegroup,
5401
                'users' => [$user2, $user3, $user4],
5402
                'messages' => [$user2, $user3, $user4],
5403
                'favourites' => [],
5404
                'enabled' => true
5405
            ],
5406
            [
5407
                'type' => $typegroup,
5408
                'users' => [$user6, $user7],
5409
                'messages' => [$user6, $user7, $user7],
5410
                'favourites' => [$user6],
5411
                'enabled' => false
5412
            ],
5413
            [
5414
                'type' => $typeself,
5415
                'users' => [$user8],
5416
                'messages' => [$user8],
5417
                'favourites' => [],
5418
                'enabled' => null // Self-conversations cannot be disabled.
5419
            ],
5420
        ];
5421
 
5422
        return [
5423
            'No conversations' => [
5424
                'conversationConfigs' => $conversations,
5425
                'deletemessagesuser' => null,
5426
                'deletemessages' => [],
5427
                'arguments' => [$user5],
5428
                'expectedcounts' => ['favourites' => 1, 'types' => [
5429
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5430
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5431
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5432
                ]],
5433
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5434
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5435
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5436
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5437
                ]],
5438
                'deletedusers' => []
5439
            ],
5440
            'No individual conversations, 2 group conversations' => [
5441
                'conversationConfigs' => $conversations,
5442
                'deletemessagesuser' => null,
5443
                'deletemessages' => [],
5444
                'arguments' => [$user4],
5445
                'expectedcounts' => ['favourites' => 1, 'types' => [
5446
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5447
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5448
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5449
                ]],
5450
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5451
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5452
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5453
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5454
                ]],
5455
                'deletedusers' => []
5456
            ],
5457
            '2 individual conversations (one favourited), 1 group conversation' => [
5458
                'conversationConfigs' => $conversations,
5459
                'deletemessagesuser' => null,
5460
                'deletemessages' => [],
5461
                'arguments' => [$user1],
5462
                'expectedcounts' => ['favourites' => 2, 'types' => [
5463
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5464
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5465
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5466
                ]],
5467
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5468
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5469
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5470
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5471
                ]],
5472
                'deletedusers' => []
5473
            ],
5474
            '1 individual conversation, 2 group conversations' => [
5475
                'conversationConfigs' => $conversations,
5476
                'deletemessagesuser' => null,
5477
                'deletemessages' => [],
5478
                'arguments' => [$user2],
5479
                'expectedcounts' => ['favourites' => 1, 'types' => [
5480
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5481
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5482
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5483
                ]],
5484
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5485
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5486
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5487
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5488
                ]],
5489
                'deletedusers' => []
5490
            ],
5491
            '2 group conversations only' => [
5492
                'conversationConfigs' => $conversations,
5493
                'deletemessagesuser' => null,
5494
                'deletemessages' => [],
5495
                'arguments' => [$user4],
5496
                'expectedcounts' => ['favourites' => 1, 'types' => [
5497
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5498
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5499
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5500
                ]],
5501
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5502
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5503
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5504
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5505
                ]],
5506
                'deletedusers' => []
5507
            ],
5508
            'All conversation types, delete a message from individual favourited, messages remaining' => [
5509
                'conversationConfigs' => $conversations,
5510
                'deletemessagesuser' => $user1,
5511
                'deletemessages' => [0],
5512
                'arguments' => [$user1],
5513
                'expectedcounts' => ['favourites' => 2, 'types' => [
5514
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5515
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5516
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5517
                ]],
5518
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5519
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5520
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5521
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5522
                ]],
5523
                'deletedusers' => []
5524
            ],
5525
            'All conversation types, delete a message from individual non-favourited, messages remaining' => [
5526
                'conversationConfigs' => $conversations,
5527
                'deletemessagesuser' => $user1,
5528
                'deletemessages' => [3],
5529
                'arguments' => [$user1],
5530
                'expectedcounts' => ['favourites' => 2, 'types' => [
5531
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5532
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5533
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5534
                ]],
5535
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5536
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5537
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5538
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5539
                ]],
5540
                'deletedusers' => []
5541
            ],
5542
            'All conversation types, delete all messages from individual favourited, no messages remaining' => [
5543
                'conversationConfigs' => $conversations,
5544
                'deletemessagesuser' => $user1,
5545
                'deletemessages' => [0, 1, 2],
5546
                'arguments' => [$user1],
5547
                'expectedcounts' => ['favourites' => 1, 'types' => [
5548
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5549
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5550
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5551
                ]],
5552
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5553
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5554
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5555
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5556
                ]],
5557
                'deletedusers' => []
5558
            ],
5559
            'All conversation types, delete all messages from individual non-favourited, no messages remaining' => [
5560
                'conversationConfigs' => $conversations,
5561
                'deletemessagesuser' => $user1,
5562
                'deletemessages' => [3, 4, 5],
5563
                'arguments' => [$user1],
5564
                'expectedcounts' => ['favourites' => 2, 'types' => [
5565
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5566
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5567
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5568
                ]],
5569
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5570
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5571
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5572
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5573
                ]],
5574
                'deletedusers' => []
5575
            ],
5576
            'All conversation types, delete all messages from individual favourited, no messages remaining, different user' => [
5577
                'conversationConfigs' => $conversations,
5578
                'deletemessagesuser' => $user1,
5579
                'deletemessages' => [0, 1, 2],
5580
                'arguments' => [$user2],
5581
                'expectedcounts' => ['favourites' => 1, 'types' => [
5582
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5583
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5584
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5585
                ]],
5586
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5587
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5588
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5589
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5590
                ]],
5591
                'deletedusers' => []
5592
            ],
5593
            'All conversation types, delete all messages from individual non-favourited, no messages remaining, different user' => [
5594
                'conversationConfigs' => $conversations,
5595
                'deletemessagesuser' => $user1,
5596
                'deletemessages' => [3, 4, 5],
5597
                'arguments' => [$user3],
5598
                'expectedcounts' => ['favourites' => 1, 'types' => [
5599
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5600
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5601
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5602
                ]],
5603
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5604
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5605
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 2,
5606
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5607
                ]],
5608
                'deletedusers' => []
5609
            ],
5610
            'All conversation types, delete some messages from group non-favourited, messages remaining,' => [
5611
                'conversationConfigs' => $conversations,
5612
                'deletemessagesuser' => $user1,
5613
                'deletemessages' => [6, 7],
5614
                'arguments' => [$user1],
5615
                'expectedcounts' => ['favourites' => 2, 'types' => [
5616
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5617
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5618
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5619
                ]],
5620
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5621
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5622
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5623
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5624
                ]],
5625
                'deletedusers' => []
5626
            ],
5627
            'All conversation types, delete all messages from group non-favourited, no messages remaining,' => [
5628
                'conversationConfigs' => $conversations,
5629
                'deletemessagesuser' => $user1,
5630
                'deletemessages' => [6, 7, 8, 9],
5631
                'arguments' => [$user1],
5632
                'expectedcounts' => ['favourites' => 2, 'types' => [
5633
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5634
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5635
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5636
                ]],
5637
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5638
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5639
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5640
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5641
                ]],
5642
                'deletedusers' => []
5643
            ],
5644
            'All conversation types, another user soft deleted' => [
5645
                'conversationConfigs' => $conversations,
5646
                'deletemessagesuser' => null,
5647
                'deletemessages' => [],
5648
                'arguments' => [$user1],
5649
                'expectedcounts' => ['favourites' => 2, 'types' => [
5650
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5651
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5652
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5653
                ]],
5654
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5655
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5656
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5657
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5658
                ]],
5659
                'deletedusers' => [$user2]
5660
            ],
5661
            'All conversation types, all group users soft deleted' => [
5662
                'conversationConfigs' => $conversations,
5663
                'deletemessagesuser' => null,
5664
                'deletemessages' => [],
5665
                'arguments' => [$user1],
5666
                'expectedcounts' => ['favourites' => 2, 'types' => [
5667
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5668
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5669
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5670
                ]],
5671
                'expectedunreadcounts' => ['favourites' => 1, 'types' => [
5672
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 1,
5673
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 1,
5674
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5675
                ]],
5676
                'deletedusers' => [$user2, $user3, $user4]
5677
            ],
5678
            'Group conversation which is disabled, favourited' => [
5679
                'conversationConfigs' => $conversations,
5680
                'deletemessagesuser' => null,
5681
                'deletemessages' => [],
5682
                'arguments' => [$user6],
5683
                'expectedcounts' => ['favourites' => 1, 'types' => [
5684
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5685
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5686
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5687
                ]],
5688
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5689
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5690
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5691
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5692
                ]],
5693
                'deletedusers' => []
5694
            ],
5695
            'Group conversation which is disabled, non-favourited' => [
5696
                'conversationConfigs' => $conversations,
5697
                'deletemessagesuser' => null,
5698
                'deletemessages' => [],
5699
                'arguments' => [$user7],
5700
                'expectedcounts' => ['favourites' => 1, 'types' => [
5701
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5702
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5703
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5704
                ]],
5705
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5706
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5707
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5708
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5709
                ]],
5710
                'deletedusers' => []
5711
            ],
5712
            'Conversation with self' => [
5713
                'conversationConfigs' => $conversations,
5714
                'deletemessagesuser' => null,
5715
                'deletemessages' => [],
5716
                'arguments' => [$user8],
5717
                'expectedcounts' => ['favourites' => 0, 'types' => [
5718
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5719
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5720
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 1
5721
                ]],
5722
                'expectedunreadcounts' => ['favourites' => 0, 'types' => [
5723
                    api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
5724
                    api::MESSAGE_CONVERSATION_TYPE_GROUP => 0,
5725
                    api::MESSAGE_CONVERSATION_TYPE_SELF => 0
5726
                ]],
5727
                'deletedusers' => []
5728
            ],
5729
        ];
5730
    }
5731
 
5732
    /**
5733
     * Test the get_conversation_counts() function.
5734
     *
5735
     * @dataProvider get_conversation_counts_test_cases
5736
     * @param array $conversationconfigs Conversations to create
5737
     * @param int $deletemessagesuser The user who is deleting the messages
5738
     * @param array $deletemessages The list of messages to delete (by index)
5739
     * @param array $arguments Arguments for the count conversations function
5740
     * @param array $expectedcounts the expected conversation counts
5741
     * @param array $expectedunreadcounts the expected unread conversation counts
5742
     * @param array $deletedusers the array of users to soft delete.
5743
     */
5744
    public function test_get_conversation_counts(
5745
        $conversationconfigs,
5746
        $deletemessagesuser,
5747
        $deletemessages,
5748
        $arguments,
5749
        $expectedcounts,
5750
        $expectedunreadcounts,
5751
        $deletedusers
5752
    ) {
5753
        $generator = $this->getDataGenerator();
5754
        $users = [
5755
            $generator->create_user(),
5756
            $generator->create_user(),
5757
            $generator->create_user(),
5758
            $generator->create_user(),
5759
            $generator->create_user(),
5760
            $generator->create_user(),
5761
            $generator->create_user(),
5762
            $generator->create_user()
5763
        ];
5764
 
5765
        $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null;
5766
        $arguments[0] = $users[$arguments[0]]->id;
5767
        $systemcontext = \context_system::instance();
5768
        $conversations = [];
5769
        $messageids = [];
5770
 
5771
        foreach ($conversationconfigs as $config) {
5772
            $conversation = api::create_conversation(
5773
                $config['type'],
5774
                array_map(function($userindex) use ($users) {
5775
                    return $users[$userindex]->id;
5776
                }, $config['users']),
5777
                null,
5778
                ($config['enabled'] ?? true)
5779
            );
5780
 
5781
            foreach ($config['messages'] as $userfromindex) {
5782
                $userfrom = $users[$userfromindex];
5783
                $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id);
5784
            }
5785
 
5786
            // Remove the self conversations created by the generator,
5787
            // so we can choose to set that ourself and honour the original intention of the test.
5788
            $userids = array_map(function($userindex) use ($users) {
5789
                return $users[$userindex]->id;
5790
            }, $config['users']);
5791
            foreach ($userids as $userid) {
5792
                if ($conversation->type == api::MESSAGE_CONVERSATION_TYPE_SELF) {
5793
                    api::unset_favourite_conversation($conversation->id, $userid);
5794
                }
5795
            }
5796
 
5797
            foreach ($config['favourites'] as $userfromindex) {
5798
                $userfrom = $users[$userfromindex];
5799
                $usercontext = \context_user::instance($userfrom->id);
5800
                $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
5801
                $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext);
5802
            }
5803
 
5804
            $conversations[] = $conversation;
5805
        }
5806
 
5807
        foreach ($deletemessages as $messageindex) {
5808
            api::delete_message($deleteuser->id, $messageids[$messageindex]);
5809
        }
5810
 
5811
        foreach ($deletedusers as $deleteduser) {
5812
            delete_user($users[$deleteduser]);
5813
        }
5814
 
5815
        $counts = api::get_conversation_counts(...$arguments);
5816
 
5817
        $this->assertEquals($expectedcounts['favourites'], $counts['favourites']);
5818
        $this->assertEquals($expectedcounts['types'][api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL],
5819
            $counts['types'][api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
5820
        $this->assertEquals($expectedcounts['types'][api::MESSAGE_CONVERSATION_TYPE_GROUP],
5821
            $counts['types'][api::MESSAGE_CONVERSATION_TYPE_GROUP]);
5822
        $this->assertEquals($expectedcounts['types'][api::MESSAGE_CONVERSATION_TYPE_SELF],
5823
            $counts['types'][api::MESSAGE_CONVERSATION_TYPE_SELF]);
5824
    }
5825
 
5826
    /**
5827
     * Test the count_contacts() function.
5828
     */
5829
    public function test_count_contacts() {
5830
        $user1 = self::getDataGenerator()->create_user();
5831
        $user2 = self::getDataGenerator()->create_user();
5832
        $user3 = self::getDataGenerator()->create_user();
5833
 
5834
        $this->assertEquals(0, api::count_contacts($user1->id));
5835
 
5836
        api::create_contact_request($user1->id, $user2->id);
5837
 
5838
        // Still zero until the request is confirmed.
5839
        $this->assertEquals(0, api::count_contacts($user1->id));
5840
 
5841
        api::confirm_contact_request($user1->id, $user2->id);
5842
 
5843
        $this->assertEquals(1, api::count_contacts($user1->id));
5844
 
5845
        api::create_contact_request($user3->id, $user1->id);
5846
 
5847
        // Still one until the request is confirmed.
5848
        $this->assertEquals(1, api::count_contacts($user1->id));
5849
 
5850
        api::confirm_contact_request($user3->id, $user1->id);
5851
 
5852
        $this->assertEquals(2, api::count_contacts($user1->id));
5853
    }
5854
 
5855
    /**
5856
     * Test the get_unread_conversation_counts() function.
5857
     *
5858
     * @dataProvider get_conversation_counts_test_cases
5859
     * @param array $conversationconfigs Conversations to create
5860
     * @param int $deletemessagesuser The user who is deleting the messages
5861
     * @param array $deletemessages The list of messages to delete (by index)
5862
     * @param array $arguments Arguments for the count conversations function
5863
     * @param array $expectedcounts the expected conversation counts
5864
     * @param array $expectedunreadcounts the expected unread conversation counts
5865
     * @param array $deletedusers the list of users to soft-delete.
5866
     */
5867
    public function test_get_unread_conversation_counts(
5868
        $conversationconfigs,
5869
        $deletemessagesuser,
5870
        $deletemessages,
5871
        $arguments,
5872
        $expectedcounts,
5873
        $expectedunreadcounts,
5874
        $deletedusers
5875
    ) {
5876
        $this->resetAfterTest();
5877
        $generator = $this->getDataGenerator();
5878
        $users = [
5879
            $generator->create_user(),
5880
            $generator->create_user(),
5881
            $generator->create_user(),
5882
            $generator->create_user(),
5883
            $generator->create_user(),
5884
            $generator->create_user(),
5885
            $generator->create_user(),
5886
            $generator->create_user()
5887
        ];
5888
 
5889
        $deleteuser = !is_null($deletemessagesuser) ? $users[$deletemessagesuser] : null;
5890
        $this->setUser($users[$arguments[0]]);
5891
        $arguments[0] = $users[$arguments[0]]->id;
5892
        $systemcontext = \context_system::instance();
5893
        $conversations = [];
5894
        $messageids = [];
5895
 
5896
        foreach ($conversationconfigs as $config) {
5897
            $conversation = api::create_conversation(
5898
                $config['type'],
5899
                array_map(function($userindex) use ($users) {
5900
                    return $users[$userindex]->id;
5901
                }, $config['users']),
5902
                null,
5903
                ($config['enabled'] ?? true)
5904
            );
5905
 
5906
            foreach ($config['messages'] as $userfromindex) {
5907
                $userfrom = $users[$userfromindex];
5908
                $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id);
5909
            }
5910
 
5911
            foreach ($config['favourites'] as $userfromindex) {
5912
                $userfrom = $users[$userfromindex];
5913
                $usercontext = \context_user::instance($userfrom->id);
5914
                $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
5915
                $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext);
5916
            }
5917
 
5918
            $conversations[] = $conversation;
5919
        }
5920
 
5921
        foreach ($deletemessages as $messageindex) {
5922
            api::delete_message($deleteuser->id, $messageids[$messageindex]);
5923
        }
5924
 
5925
        foreach ($deletedusers as $deleteduser) {
5926
            delete_user($users[$deleteduser]);
5927
        }
5928
 
5929
        $counts = api::get_unread_conversation_counts(...$arguments);
5930
 
5931
        $this->assertEquals($expectedunreadcounts['favourites'], $counts['favourites']);
5932
        $this->assertEquals($expectedunreadcounts['types'][api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL],
5933
            $counts['types'][api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]);
5934
        $this->assertEquals($expectedunreadcounts['types'][api::MESSAGE_CONVERSATION_TYPE_GROUP],
5935
            $counts['types'][api::MESSAGE_CONVERSATION_TYPE_GROUP]);
5936
        $this->assertEquals($expectedunreadcounts['types'][api::MESSAGE_CONVERSATION_TYPE_SELF],
5937
            $counts['types'][api::MESSAGE_CONVERSATION_TYPE_SELF]);
5938
    }
5939
 
5940
    public function test_delete_all_conversation_data() {
5941
        global $DB;
5942
 
5943
        $this->resetAfterTest();
5944
 
5945
        $this->setAdminUser();
5946
 
5947
        $course1 = $this->getDataGenerator()->create_course();
5948
        $coursecontext1 = \context_course::instance($course1->id);
5949
 
5950
        $user1 = $this->getDataGenerator()->create_user();
5951
        $user2 = $this->getDataGenerator()->create_user();
5952
 
5953
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
5954
        $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
5955
 
5956
        $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id, 'enablemessaging' => 1));
5957
        $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id, 'enablemessaging' => 1));
5958
 
5959
        // Add users to both groups.
5960
        $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
5961
        $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id));
5962
 
5963
        $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user1->id));
5964
        $this->getDataGenerator()->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
5965
 
5966
        $groupconversation1 = api::get_conversation_by_area(
5967
            'core_group',
5968
            'groups',
5969
            $group1->id,
5970
            $coursecontext1->id
5971
        );
5972
 
5973
        $groupconversation2 = api::get_conversation_by_area(
5974
            'core_group',
5975
            'groups',
5976
            $group2->id,
5977
            $coursecontext1->id
5978
        );
5979
 
5980
        // Send a few messages.
5981
        $g1m1 = testhelper::send_fake_message_to_conversation($user1, $groupconversation1->id);
5982
        $g1m2 = testhelper::send_fake_message_to_conversation($user2, $groupconversation1->id);
5983
        $g1m3 = testhelper::send_fake_message_to_conversation($user1, $groupconversation1->id);
5984
        $g1m4 = testhelper::send_fake_message_to_conversation($user2, $groupconversation1->id);
5985
 
5986
        $g2m1 = testhelper::send_fake_message_to_conversation($user1, $groupconversation2->id);
5987
        $g2m2 = testhelper::send_fake_message_to_conversation($user2, $groupconversation2->id);
5988
        $g2m3 = testhelper::send_fake_message_to_conversation($user1, $groupconversation2->id);
5989
        $g2m4 = testhelper::send_fake_message_to_conversation($user2, $groupconversation2->id);
5990
 
5991
        // Favourite the conversation for several of the users.
5992
        api::set_favourite_conversation($groupconversation1->id, $user1->id);
5993
        api::set_favourite_conversation($groupconversation1->id, $user2->id);
5994
 
5995
        // Delete a few messages.
5996
        api::delete_message($user1->id, $g1m1);
5997
        api::delete_message($user1->id, $g1m2);
5998
        api::delete_message($user1->id, $g2m1);
5999
        api::delete_message($user1->id, $g2m2);
6000
 
6001
        // Mute the conversations.
6002
        api::mute_conversation($user1->id, $groupconversation1->id);
6003
        api::mute_conversation($user1->id, $groupconversation2->id);
6004
 
6005
        // Now, delete all the data for the group 1 conversation.
6006
        api::delete_all_conversation_data($groupconversation1->id);
6007
 
6008
        // Confirm group conversation was deleted just for the group 1 conversation.
6009
        $this->assertEquals(0, $DB->count_records('message_conversations', ['id' => $groupconversation1->id]));
6010
        $this->assertEquals(1, $DB->count_records('message_conversations', ['id' => $groupconversation2->id]));
6011
 
6012
        // Confirm conversation members were deleted just for the group 1 conversation.
6013
        $this->assertEquals(0, $DB->count_records('message_conversation_members', ['conversationid' => $groupconversation1->id]));
6014
        $this->assertEquals(2, $DB->count_records('message_conversation_members', ['conversationid' => $groupconversation2->id]));
6015
 
6016
        // Confirm message conversation actions were deleted just for the group 1 conversation.
6017
        $this->assertEquals(0, $DB->count_records('message_conversation_actions', ['conversationid' => $groupconversation1->id]));
6018
        $this->assertEquals(1, $DB->count_records('message_conversation_actions', ['conversationid' => $groupconversation2->id]));
6019
 
6020
        // Confirm message user actions were deleted just for the group 1 conversation.
6021
        $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m1]));
6022
        $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m2]));
6023
        $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m3]));
6024
        $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g1m4]));
6025
        $this->assertEquals(1, $DB->count_records('message_user_actions', ['messageid' => $g2m1]));
6026
        $this->assertEquals(1, $DB->count_records('message_user_actions', ['messageid' => $g2m2]));
6027
        $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g2m3]));
6028
        $this->assertEquals(0, $DB->count_records('message_user_actions', ['messageid' => $g2m4]));
6029
 
6030
        // Confirm messages were deleted just for the group 1 conversation.
6031
        $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m1]));
6032
        $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m2]));
6033
        $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m3]));
6034
        $this->assertEquals(0, $DB->count_records('messages', ['id' => $g1m4]));
6035
        $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m1]));
6036
        $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m2]));
6037
        $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m3]));
6038
        $this->assertEquals(1, $DB->count_records('messages', ['id' => $g2m4]));
6039
 
6040
        // Confirm favourites were deleted for both users.
6041
        $user1service = \core_favourites\service_factory::get_service_for_user_context(\context_user::instance($user1->id));
6042
        $this->assertFalse($user1service->favourite_exists('core_message', 'message_conversations', $groupconversation1->id,
6043
            $coursecontext1));
6044
        $user2service = \core_favourites\service_factory::get_service_for_user_context(\context_user::instance($user1->id));
6045
        $this->assertFalse($user2service->favourite_exists('core_message', 'message_conversations', $groupconversation1->id,
6046
            $coursecontext1));
6047
    }
6048
 
6049
    /**
6050
     * Tests the user can delete message for all users as a teacher.
6051
     */
6052
    public function test_can_delete_message_for_all_users_teacher() {
6053
        global $DB;
6054
        $this->resetAfterTest(true);
6055
 
6056
        // Create fake data to test it.
6057
        list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
6058
 
6059
        // Allow Teacher can delete messages for all.
6060
        $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']);
6061
        assign_capability('moodle/site:deleteanymessage', CAP_ALLOW, $editingteacher->id, \context_system::instance());
6062
 
6063
        // Set as the first user.
6064
        $this->setUser($teacher);
6065
 
6066
        // Send a message to private conversation and in a group conversation.
6067
        $messageidind = testhelper::send_fake_message_to_conversation($teacher, $convindividual->id);
6068
        $messageidgrp = testhelper::send_fake_message_to_conversation($teacher, $convgroup->id);
6069
 
6070
        // Teacher cannot delete message for everyone in a private conversation.
6071
        $this->assertFalse(api::can_delete_message_for_all_users($teacher->id, $messageidind));
6072
 
6073
        // Teacher can delete message for everyone in a group conversation.
6074
        $this->assertTrue(api::can_delete_message_for_all_users($teacher->id, $messageidgrp));
6075
    }
6076
 
6077
    /**
6078
     * Tests the user can delete message for all users as a student.
6079
     */
6080
    public function test_can_delete_message_for_all_users_student() {
6081
        $this->resetAfterTest(true);
6082
 
6083
        // Create fake data to test it.
6084
        list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
6085
 
6086
        // Set as the first user.
6087
        $this->setUser($student1);
6088
 
6089
        // Send a message to private conversation and in a group conversation.
6090
        $messageidind = testhelper::send_fake_message_to_conversation($teacher, $convindividual->id);
6091
        $messageidgrp = testhelper::send_fake_message_to_conversation($teacher, $convgroup->id);
6092
 
6093
        // Student1 cannot delete message for everyone in a private conversation.
6094
        $this->assertFalse(api::can_delete_message_for_all_users($student1->id, $messageidind));
6095
 
6096
        // Student1 cannot delete message for everyone in a group conversation.
6097
        $this->assertFalse(api::can_delete_message_for_all_users($student1->id, $messageidgrp));
6098
    }
6099
 
6100
    /**
6101
     * Tests tdelete message for all users in group conversation.
6102
     */
6103
    public function test_delete_message_for_all_users_group_conversation() {
6104
        global $DB;
6105
        $this->resetAfterTest(true);
6106
 
6107
        // Create fake data to test it.
6108
        list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
6109
 
6110
        // Send 3 messages to a group conversation.
6111
        $mgid1 = testhelper::send_fake_message_to_conversation($teacher, $convgroup->id);
6112
        $mgid2 = testhelper::send_fake_message_to_conversation($student1, $convgroup->id);
6113
        $mgid3 = testhelper::send_fake_message_to_conversation($student2, $convgroup->id);
6114
 
6115
        // Delete message 1 for all users.
6116
        api::delete_message_for_all_users($mgid1);
6117
 
6118
        // Get the messages to check if the message 1 was deleted for teacher.
6119
        $convmessages1 = api::get_conversation_messages($teacher->id, $convgroup->id);
6120
        // Only has to remains 2 messages.
6121
        $this->assertCount(2, $convmessages1['messages']);
6122
        // Check if no one of the two messages is message 1.
6123
        foreach ($convmessages1['messages'] as $message) {
6124
            $this->assertNotEquals($mgid1, $message->id);
6125
        }
6126
 
6127
        // Get the messages to check if the message 1 was deleted for student1.
6128
        $convmessages2 = api::get_conversation_messages($student1->id, $convgroup->id);
6129
        // Only has to remains 2 messages.
6130
        $this->assertCount(2, $convmessages2['messages']);
6131
        // Check if no one of the two messages is message 1.
6132
        foreach ($convmessages2['messages'] as $message) {
6133
            $this->assertNotEquals($mgid1, $message->id);
6134
        }
6135
 
6136
        // Get the messages to check if the message 1 was deleted for student2.
6137
        $convmessages3 = api::get_conversation_messages($student2->id, $convgroup->id);
6138
        // Only has to remains 2 messages.
6139
        $this->assertCount(2, $convmessages3['messages']);
6140
        // Check if no one of the two messages is message 1.
6141
        foreach ($convmessages3['messages'] as $message) {
6142
            $this->assertNotEquals($mgid1, $message->id);
6143
        }
6144
    }
6145
 
6146
    /**
6147
     * Tests delete message for all users in private conversation.
6148
     */
6149
    public function test_delete_message_for_all_users_individual_conversation() {
6150
        global $DB;
6151
        $this->resetAfterTest(true);
6152
 
6153
        // Create fake data to test it.
6154
        list($teacher, $student1, $student2, $convgroup, $convindividual) = $this->create_delete_message_test_data();
6155
 
6156
        // Send 2 messages in a individual conversation.
6157
        $mid1 = testhelper::send_fake_message_to_conversation($teacher, $convindividual->id);
6158
        $mid2 = testhelper::send_fake_message_to_conversation($student1, $convindividual->id);
6159
 
6160
        // Delete the first message for all users.
6161
        api::delete_message_for_all_users($mid1);
6162
 
6163
        // Get the messages to check if the message 1 was deleted for teacher.
6164
        $convmessages1 = api::get_conversation_messages($teacher->id, $convindividual->id);
6165
        // Only has to remains 1 messages for teacher.
6166
        $this->assertCount(1, $convmessages1['messages']);
6167
        // Check the one messages remains not is the first message.
6168
        $this->assertNotEquals($mid1, $convmessages1['messages'][0]->id);
6169
 
6170
        // Get the messages to check if the message 1 was deleted for student1.
6171
        $convmessages2 = api::get_conversation_messages($student1->id, $convindividual->id);
6172
        // Only has to remains 1 messages for student1.
6173
        $this->assertCount(1, $convmessages2['messages']);
6174
        // Check the one messages remains not is the first message.
6175
        $this->assertNotEquals($mid1, $convmessages2['messages'][0]->id);
6176
    }
6177
 
6178
    /**
6179
     * Test retrieving conversation messages by providing a timefrom higher than last message timecreated. It should return no
6180
     * messages but keep the return structure to not break when called from the ws.
6181
     */
6182
    public function test_get_conversation_messages_timefrom_higher_than_last_timecreated() {
6183
        // Create some users.
6184
        $user1 = self::getDataGenerator()->create_user();
6185
        $user2 = self::getDataGenerator()->create_user();
6186
        $user3 = self::getDataGenerator()->create_user();
6187
        $user4 = self::getDataGenerator()->create_user();
6188
 
6189
        // Create group conversation.
6190
        $conversation = api::create_conversation(
6191
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
6192
            [$user1->id, $user2->id, $user3->id, $user4->id]
6193
        );
6194
 
6195
        // The person doing the search.
6196
        $this->setUser($user1);
6197
 
6198
        // Send some messages back and forth.
6199
        $time = 1;
6200
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 1', $time + 1);
6201
        testhelper::send_fake_message_to_conversation($user2, $conversation->id, 'Message 2', $time + 2);
6202
        testhelper::send_fake_message_to_conversation($user1, $conversation->id, 'Message 3', $time + 3);
6203
        testhelper::send_fake_message_to_conversation($user3, $conversation->id, 'Message 4', $time + 4);
6204
 
6205
        // Retrieve the messages from $time + 5, which should return no messages.
6206
        $convmessages = api::get_conversation_messages($user1->id, $conversation->id, 0, 0, '', $time + 5);
6207
 
6208
        // Confirm the conversation id is correct.
6209
        $this->assertEquals($conversation->id, $convmessages['id']);
6210
 
6211
        // Confirm the message data is correct.
6212
        $messages = $convmessages['messages'];
6213
        $this->assertEquals(0, count($messages));
6214
 
6215
        // Confirm that members key is present.
6216
        $this->assertArrayHasKey('members', $convmessages);
6217
    }
6218
 
6219
    /**
6220
     * Helper to seed the database with initial state with data.
6221
     */
6222
    protected function create_delete_message_test_data() {
6223
        // Create some users.
6224
        $teacher = self::getDataGenerator()->create_user();
6225
        $student1 = self::getDataGenerator()->create_user();
6226
        $student2 = self::getDataGenerator()->create_user();
6227
 
6228
        // Create a course and enrol the users.
6229
        $course = $this->getDataGenerator()->create_course();
6230
        $coursecontext = \context_course::instance($course->id);
6231
        $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
6232
        $this->getDataGenerator()->enrol_user($student1->id, $course->id, 'student');
6233
        $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student');
6234
 
6235
        // Create a group and added the users into.
6236
        $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
6237
        groups_add_member($group1->id, $teacher->id);
6238
        groups_add_member($group1->id, $student1->id);
6239
        groups_add_member($group1->id, $student2->id);
6240
 
6241
        // Create a group conversation linked with the course.
6242
        $convgroup = api::create_conversation(
6243
            api::MESSAGE_CONVERSATION_TYPE_GROUP,
6244
            [$teacher->id, $student1->id, $student2->id],
6245
            'Group test delete for everyone', api::MESSAGE_CONVERSATION_ENABLED,
6246
            'core_group',
6247
            'groups',
6248
            $group1->id,
6249
            \context_course::instance($course->id)->id
6250
        );
6251
 
6252
        // Create and individual conversation.
6253
        $convindividual = api::create_conversation(
6254
            api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
6255
            [$teacher->id, $student1->id]
6256
        );
6257
 
6258
        return [$teacher, $student1, $student2, $convgroup, $convindividual];
6259
    }
6260
 
6261
    /**
6262
     * Comparison function for sorting contacts.
6263
     *
6264
     * @param \stdClass $a
6265
     * @param \stdClass $b
6266
     * @return bool
6267
     */
6268
    protected static function sort_contacts($a, $b) {
6269
        return $a->userid > $b->userid;
6270
    }
6271
}