Proyectos de Subversion Moodle

Rev

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