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