Proyectos de Subversion Moodle

Rev

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