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 mod_forum;
18
 
19
use mod_forum\local\container;
20
use mod_forum\local\entities\forum;
21
use mod_forum\local\managers\capability as capability_manager;
22
use mod_forum_tests_generator_trait;
23
 
24
defined('MOODLE_INTERNAL') || die();
25
 
26
global $CFG;
27
require_once(__DIR__ . '/generator_trait.php');
28
 
29
/**
30
 * The capability manager tests.
31
 *
32
 * @package    mod_forum
33
 * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 * @coversDefaultClass \mod_forum\local\managers\capability
36
 */
37
class managers_capability_test extends \advanced_testcase {
38
    // Make use of the test generator trait.
39
    use mod_forum_tests_generator_trait;
40
 
41
    /** @var stdClass */
42
    private $user;
43
 
44
    /** @var \mod_forum\local\factories\entity */
45
    private $entityfactory;
46
 
47
    /** @var \mod_forum\local\factories\manager */
48
    private $managerfactory;
49
 
50
    /** @var stdClass */
51
    private $course;
52
 
53
    /** @var stdClass */
54
    private $forumrecord;
55
 
56
    /** @var stdClass */
57
    private $coursemodule;
58
 
59
    /** @var context */
60
    private $context;
61
 
62
    /** @var int */
63
    private $roleid;
64
 
65
    /** @var \mod_forum\local\entities\discussion */
66
    private $discussion;
67
 
68
    /** @var stdClass */
69
    private $discussionrecord;
70
 
71
    /** @var \mod_forum\local\entities\post */
72
    private $post;
73
 
74
    /** @var stdClass */
75
    private $postrecord;
76
 
77
    /**
78
     * Setup function before each test.
79
     */
80
    public function setUp(): void {
81
        global $DB;
82
 
83
        // We must clear the subscription caches. This has to be done both before each test, and after in case of other
84
        // tests using these functions.
85
        \mod_forum\subscriptions::reset_forum_cache();
86
 
87
        $datagenerator = $this->getDataGenerator();
88
        $this->user = $datagenerator->create_user();
89
        $this->managerfactory = container::get_manager_factory();
90
        $this->entityfactory = container::get_entity_factory();
91
        $this->course = $datagenerator->create_course();
92
        $this->forumrecord = $datagenerator->create_module('forum', ['course' => $this->course->id]);
93
        $this->coursemodule = get_coursemodule_from_instance('forum', $this->forumrecord->id);
94
        $this->context = \context_module::instance($this->coursemodule->id);
95
        $this->roleid = $DB->get_field('role', 'id', ['shortname' => 'teacher'], MUST_EXIST);
96
 
97
        $datagenerator->enrol_user($this->user->id, $this->course->id, 'teacher');
98
        [$discussion, $post] = $this->helper_post_to_forum($this->forumrecord, $this->user, ['timemodified' => time() - 100]);
99
        $this->discussion = $this->entityfactory->get_discussion_from_stdClass($discussion);
100
        $this->discussionrecord = $discussion;
101
        $this->post = $this->entityfactory->get_post_from_stdClass(
102
            (object) array_merge((array) $post, ['timecreated' => time() - 100])
103
        );
104
        $this->postrecord = $post;
105
 
106
        $this->setUser($this->user);
107
    }
108
 
109
    /**
110
     * Tear down function after each test.
111
     */
112
    public function tearDown(): void {
113
        // We must clear the subscription caches. This has to be done both before each test, and after in case of other
114
        // tests using these functions.
115
        \mod_forum\subscriptions::reset_forum_cache();
116
    }
117
 
118
    /**
119
     * Helper function to create a forum entity.
120
     *
121
     * @param array $forumproperties List of properties to override the prebuilt forum
122
     * @return forum
123
     */
124
    private function create_forum(array $forumproperties = []) {
125
        $forumrecord = (object) array_merge((array) $this->forumrecord, $forumproperties);
126
        return $this->entityfactory->get_forum_from_stdClass(
127
            $forumrecord,
128
            $this->context,
129
            $this->coursemodule,
130
            $this->course
131
        );
132
    }
133
 
134
    /**
135
     * Helper function to assign a capability to the prebuilt role (teacher).
136
     *
137
     * @param string $capability Name of the capability
138
     * @param context|null $context The context to assign the capability in
139
     */
140
    private function give_capability($capability, $context = null) {
141
        $context = $context ?? $this->context;
142
        assign_capability($capability, CAP_ALLOW, $this->roleid, $context->id, true);
143
    }
144
 
145
    /**
146
     * Helper function to prevent a capability to the prebuilt role (teacher).
147
     *
148
     * @param string $capability Name of the capability
149
     * @param context|null $context The context to assign the capability in
150
     */
151
    private function prevent_capability($capability, $context = null) {
152
        $context = $context ?? $this->context;
153
        assign_capability($capability, CAP_PREVENT, $this->roleid, $context->id, true);
154
    }
155
 
156
    /**
157
     * Test can_subscribe_to_forum.
158
     *
159
     * @covers ::can_subscribe_to_forum
160
     */
11 efrain 161
    public function test_can_subscribe_to_forum(): void {
1 efrain 162
        $this->resetAfterTest();
163
 
164
        $forum = $this->create_forum();
165
        $guestuser = $this->getDataGenerator()->create_user();
166
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
167
 
168
        $this->assertFalse($capabilitymanager->can_subscribe_to_forum($guestuser));
169
        $this->assertTrue($capabilitymanager->can_subscribe_to_forum($this->user));
170
    }
171
 
172
    /**
173
     * Test can_create_discussions.
174
     *
175
     * @covers ::can_create_discussions
176
     */
11 efrain 177
    public function test_can_create_discussions(): void {
1 efrain 178
        $this->resetAfterTest();
179
 
180
        $forum = $this->create_forum();
181
        $guestuser = $this->getDataGenerator()->create_user();
182
        $user = $this->user;
183
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
184
 
185
        $this->assertFalse($capabilitymanager->can_create_discussions($guestuser));
186
 
187
        $this->prevent_capability('mod/forum:startdiscussion');
188
        $this->assertFalse($capabilitymanager->can_create_discussions($user));
189
 
190
        $this->give_capability('mod/forum:startdiscussion');
191
        $this->assertTrue($capabilitymanager->can_create_discussions($user));
192
 
193
        $forum = $this->create_forum(['type' => 'news']);
194
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
195
 
196
        $this->prevent_capability('mod/forum:addnews');
197
        $this->assertFalse($capabilitymanager->can_create_discussions($user));
198
 
199
        $this->give_capability('mod/forum:addnews');
200
        $this->assertTrue($capabilitymanager->can_create_discussions($user));
201
 
202
        $forum = $this->create_forum(['type' => 'qanda']);
203
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
204
 
205
        $this->prevent_capability('mod/forum:addquestion');
206
        $this->assertFalse($capabilitymanager->can_create_discussions($user));
207
 
208
        $this->give_capability('mod/forum:addquestion');
209
        $this->assertTrue($capabilitymanager->can_create_discussions($user));
210
 
211
        // Test a forum in group mode.
212
        $forumrecord = $this->getDataGenerator()->create_module(
213
            'forum',
214
            ['course' => $this->course->id, 'groupmode' => SEPARATEGROUPS]
215
        );
216
        $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
217
        $context = \context_module::instance($coursemodule->id);
218
        $forum = $this->entityfactory->get_forum_from_stdClass(
219
            $forumrecord,
220
            $context,
221
            $coursemodule,
222
            $this->course
223
        );
224
 
225
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
226
 
227
        $this->assertFalse($capabilitymanager->can_create_discussions($user));
228
 
229
        $this->give_capability('moodle/site:accessallgroups', $context);
230
        $this->assertTrue($capabilitymanager->can_create_discussions($user));
231
 
232
        $this->prevent_capability('moodle/site:accessallgroups', $context);
233
        $this->assertFalse($capabilitymanager->can_create_discussions($user));
234
 
235
        $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
236
        $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
237
 
238
        $this->assertTrue($capabilitymanager->can_create_discussions($user, $group->id));
239
 
240
        // Test if cut off date is reached.
241
        $now = time();
242
        $forum = $this->create_forum(['cutoffdate' => $now + 86400 , 'blockafter' => 5, 'blockperiod' => 86400]);
243
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
244
        $this->prevent_capability('mod/forum:postwithoutthrottling');
245
        $this->assertTrue($capabilitymanager->can_create_discussions($user));
246
 
247
        $forum = $this->create_forum(['cutoffdate' => $now + 86400 , 'blockafter' => 1, 'blockperiod' => 86400]);
248
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
249
        $this->prevent_capability('mod/forum:postwithoutthrottling');
250
        $this->assertFalse($capabilitymanager->can_create_discussions($user));
251
    }
252
 
253
    /**
254
     * Test can_access_all_groups.
255
     *
256
     * @covers ::can_access_all_groups
257
     */
11 efrain 258
    public function test_can_access_all_groups(): void {
1 efrain 259
        $this->resetAfterTest();
260
 
261
        $forum = $this->create_forum();
262
        $user = $this->user;
263
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
264
 
265
        $this->prevent_capability('moodle/site:accessallgroups');
266
        $this->assertFalse($capabilitymanager->can_access_all_groups($user));
267
 
268
        $this->give_capability('moodle/site:accessallgroups');
269
        $this->assertTrue($capabilitymanager->can_access_all_groups($user));
270
    }
271
 
272
    /**
273
     * Test can_access_group.
274
     *
275
     * @covers ::can_access_group
276
     */
11 efrain 277
    public function test_can_access_group(): void {
1 efrain 278
        $this->resetAfterTest();
279
 
280
        $forum = $this->create_forum();
281
        $user = $this->user;
282
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
283
        $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
284
 
285
        $this->prevent_capability('moodle/site:accessallgroups');
286
        $this->assertFalse($capabilitymanager->can_access_group($user, $group->id));
287
 
288
        $this->give_capability('moodle/site:accessallgroups');
289
        $this->assertTrue($capabilitymanager->can_access_group($user, $group->id));
290
 
291
        $this->prevent_capability('moodle/site:accessallgroups');
292
        $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
293
        $this->assertTrue($capabilitymanager->can_access_group($user, $group->id));
294
    }
295
 
296
    /**
297
     * Test can_view_discussions.
298
     *
299
     * @covers ::can_view_discussions
300
     */
11 efrain 301
    public function test_can_view_discussions(): void {
1 efrain 302
        $this->resetAfterTest();
303
 
304
        $forum = $this->create_forum();
305
        $user = $this->user;
306
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
307
 
308
        $this->prevent_capability('mod/forum:viewdiscussion');
309
        $this->assertFalse($capabilitymanager->can_view_discussions($user));
310
 
311
        $this->give_capability('mod/forum:viewdiscussion');
312
        $this->assertTrue($capabilitymanager->can_view_discussions($user));
313
    }
314
 
315
    /**
316
     * Test can_move_discussions.
317
     *
318
     * @covers ::can_move_discussions
319
     */
11 efrain 320
    public function test_can_move_discussions(): void {
1 efrain 321
        $this->resetAfterTest();
322
 
323
        $forum = $this->create_forum();
324
        $user = $this->user;
325
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
326
 
327
        $this->prevent_capability('mod/forum:movediscussions');
328
        $this->assertFalse($capabilitymanager->can_move_discussions($user));
329
 
330
        $this->give_capability('mod/forum:movediscussions');
331
        $this->assertTrue($capabilitymanager->can_move_discussions($user));
332
 
333
        $forum = $this->create_forum(['type' => 'single']);
334
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
335
 
336
        $this->assertFalse($capabilitymanager->can_move_discussions($user));
337
    }
338
 
339
    /**
340
     * Test can_pin_discussions.
341
     *
342
     * @covers ::can_pin_discussions
343
     */
11 efrain 344
    public function test_can_pin_discussions(): void {
1 efrain 345
        $this->resetAfterTest();
346
 
347
        $forum = $this->create_forum();
348
        $user = $this->user;
349
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
350
 
351
        $this->prevent_capability('mod/forum:pindiscussions');
352
        $this->assertFalse($capabilitymanager->can_pin_discussions($user));
353
 
354
        $this->give_capability('mod/forum:pindiscussions');
355
        $this->assertTrue($capabilitymanager->can_pin_discussions($user));
356
    }
357
 
358
    /**
359
     * Test can_split_discussions.
360
     *
361
     * @covers ::can_split_discussions
362
     */
11 efrain 363
    public function test_can_split_discussions(): void {
1 efrain 364
        $this->resetAfterTest();
365
 
366
        $forum = $this->create_forum();
367
        $user = $this->user;
368
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
369
 
370
        $this->prevent_capability('mod/forum:splitdiscussions');
371
        $this->assertFalse($capabilitymanager->can_split_discussions($user));
372
 
373
        $this->give_capability('mod/forum:splitdiscussions');
374
        $this->assertTrue($capabilitymanager->can_split_discussions($user));
375
 
376
        $forum = $this->create_forum(['type' => 'single']);
377
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
378
 
379
        $this->assertFalse($capabilitymanager->can_split_discussions($user));
380
    }
381
 
382
    /**
383
     * Test can_export_discussions.
384
     *
385
     * @covers ::can_export_discussions
386
     */
11 efrain 387
    public function test_can_export_discussions(): void {
1 efrain 388
        global $CFG;
389
        $this->resetAfterTest();
390
 
391
        $CFG->enableportfolios = true;
392
        $forum = $this->create_forum();
393
        $user = $this->user;
394
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
395
 
396
        $this->prevent_capability('mod/forum:exportdiscussion');
397
        $this->assertFalse($capabilitymanager->can_export_discussions($user));
398
 
399
        $this->give_capability('mod/forum:exportdiscussion');
400
        $this->assertTrue($capabilitymanager->can_export_discussions($user));
401
 
402
        $CFG->enableportfolios = false;
403
 
404
        $this->assertFalse($capabilitymanager->can_export_discussions($user));
405
    }
406
 
407
    /**
408
     * Test can_manually_control_post_read_status.
409
     *
410
     * @covers ::can_manually_control_post_read_status
411
     */
11 efrain 412
    public function test_can_manually_control_post_read_status(): void {
1 efrain 413
        global $CFG, $DB;
414
        $this->resetAfterTest();
415
 
416
        $CFG->forum_usermarksread = true;
417
        $forum = $this->create_forum();
418
        $user = $this->user;
419
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
420
        $cache = \cache::make('mod_forum', 'forum_is_tracked');
421
 
422
        $user->trackforums = true;
423
        $prefid = $DB->insert_record('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forum->get_id()]);
424
        $this->assertFalse($capabilitymanager->can_manually_control_post_read_status($user));
425
        $cache->purge();
426
 
427
        $DB->delete_records('forum_track_prefs', ['id' => $prefid]);
428
        $this->assertTrue($capabilitymanager->can_manually_control_post_read_status($user));
429
        $cache->purge();
430
 
431
        $CFG->forum_usermarksread = false;
432
 
433
        $this->assertFalse($capabilitymanager->can_manually_control_post_read_status($user));
434
    }
435
 
436
    /**
437
     * Test must_post_before_viewing_discussion.
438
     *
439
     * @covers ::must_post_before_viewing_discussion
440
     */
11 efrain 441
    public function test_must_post_before_viewing_discussion(): void {
1 efrain 442
        $this->resetAfterTest();
443
 
444
        $forum = $this->create_forum();
445
        $user = $this->user;
446
        $discussion = $this->discussion;
447
        $newuser = $this->getDataGenerator()->create_user();
448
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
449
        $this->getDataGenerator()->enrol_user($newuser->id, $this->course->id, 'teacher');
450
 
451
        $this->assertFalse($capabilitymanager->must_post_before_viewing_discussion($newuser, $discussion));
452
 
453
        $forum = $this->create_forum(['type' => 'qanda']);
454
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
455
 
456
        $this->prevent_capability('mod/forum:viewqandawithoutposting');
457
        $this->assertTrue($capabilitymanager->must_post_before_viewing_discussion($newuser, $discussion));
458
 
459
        $this->give_capability('mod/forum:viewqandawithoutposting');
460
        $this->assertFalse($capabilitymanager->must_post_before_viewing_discussion($newuser, $discussion));
461
 
462
        $this->prevent_capability('mod/forum:viewqandawithoutposting');
463
        // The pre-generated user has a pre-generated post in the disussion already.
464
        $this->assertFalse($capabilitymanager->must_post_before_viewing_discussion($user, $discussion));
465
    }
466
 
467
    /**
468
     * Test can_subscribe_to_discussion.
469
     *
470
     * @covers ::can_subscribe_to_discussion
471
     */
11 efrain 472
    public function test_can_subscribe_to_discussion(): void {
1 efrain 473
        $this->resetAfterTest();
474
 
475
        $forum = $this->create_forum();
476
        $discussion = $this->discussion;
477
        $guestuser = $this->getDataGenerator()->create_user();
478
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
479
 
480
        $this->assertFalse($capabilitymanager->can_subscribe_to_discussion($guestuser, $discussion));
481
        $this->assertTrue($capabilitymanager->can_subscribe_to_discussion($this->user, $discussion));
482
    }
483
 
484
    /**
485
     * Test can_move_discussion.
486
     *
487
     * @covers ::can_move_discussion
488
     */
11 efrain 489
    public function test_can_move_discussion(): void {
1 efrain 490
        $this->resetAfterTest();
491
 
492
        $forum = $this->create_forum();
493
        $discussion = $this->discussion;
494
        $user = $this->user;
495
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
496
 
497
        $this->prevent_capability('mod/forum:movediscussions');
498
        $this->assertFalse($capabilitymanager->can_move_discussion($user, $discussion));
499
 
500
        $this->give_capability('mod/forum:movediscussions');
501
        $this->assertTrue($capabilitymanager->can_move_discussion($user, $discussion));
502
 
503
        $forum = $this->create_forum(['type' => 'single']);
504
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
505
 
506
        $this->assertFalse($capabilitymanager->can_move_discussion($user, $discussion));
507
    }
508
 
509
    /**
510
     * Test can_pin_discussion.
511
     *
512
     * @covers ::can_pin_discussion
513
     */
11 efrain 514
    public function test_can_pin_discussion(): void {
1 efrain 515
        $this->resetAfterTest();
516
 
517
        $forum = $this->create_forum();
518
        $discussion = $this->discussion;
519
        $user = $this->user;
520
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
521
 
522
        $this->prevent_capability('mod/forum:pindiscussions');
523
        $this->assertFalse($capabilitymanager->can_pin_discussion($user, $discussion));
524
 
525
        $this->give_capability('mod/forum:pindiscussions');
526
        $this->assertTrue($capabilitymanager->can_pin_discussion($user, $discussion));
527
    }
528
 
529
    /**
530
     * Test can_post_in_discussion.
531
     *
532
     * @covers ::can_post_in_discussion
533
     */
11 efrain 534
    public function test_can_post_in_discussion(): void {
1 efrain 535
        $this->resetAfterTest();
536
 
537
        $discussion = $this->discussion;
538
        $user = $this->user;
539
 
540
        // Locked discussions.
541
        $lockedforum = $this->create_forum(['lockdiscussionafter' => 1]);
542
        $capabilitymanager = $this->managerfactory->get_capability_manager($lockedforum);
543
 
544
        $this->give_capability('mod/forum:canoverridediscussionlock');
545
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
546
 
547
        $this->prevent_capability('mod/forum:canoverridediscussionlock');
548
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
549
 
550
        // News forum.
551
        $newsforum = $this->create_forum(['type' => 'news']);
552
        $capabilitymanager = $this->managerfactory->get_capability_manager($newsforum);
553
 
554
        $this->give_capability('mod/forum:replynews');
555
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
556
 
557
        $this->prevent_capability('mod/forum:replynews');
558
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
559
 
560
        // General forum.
561
        $forum = $this->create_forum();
562
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
563
 
564
        $this->give_capability('mod/forum:replypost');
565
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
566
 
567
        $this->prevent_capability('mod/forum:replypost');
568
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
569
 
570
        // Forum in separate group mode.
571
        $forumrecord = $this->getDataGenerator()->create_module(
572
            'forum',
573
            ['course' => $this->course->id, 'groupmode' => SEPARATEGROUPS]
574
        );
575
        $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
576
        $context = \context_module::instance($coursemodule->id);
577
        $forum = $this->entityfactory->get_forum_from_stdClass(
578
            $forumrecord,
579
            $context,
580
            $coursemodule,
581
            $this->course
582
        );
583
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
584
 
585
        $this->give_capability('moodle/site:accessallgroups', $context);
586
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
587
 
588
        $this->prevent_capability('moodle/site:accessallgroups', $context);
589
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
590
 
591
        $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
592
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
593
            (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
594
        );
595
 
596
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
597
 
598
        $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
599
 
600
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
601
 
602
        // Forum in visible group mode.
603
        $forumrecord = $this->getDataGenerator()->create_module(
604
            'forum',
605
            ['course' => $this->course->id, 'groupmode' => VISIBLEGROUPS]
606
        );
607
        $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
608
        $context = \context_module::instance($coursemodule->id);
609
        $forum = $this->entityfactory->get_forum_from_stdClass(
610
            $forumrecord,
611
            $context,
612
            $coursemodule,
613
            $this->course
614
        );
615
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
616
 
617
        $this->give_capability('moodle/site:accessallgroups', $context);
618
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
619
 
620
        $this->prevent_capability('moodle/site:accessallgroups', $context);
621
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
622
 
623
        $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
624
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
625
            (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
626
        );
627
 
628
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
629
 
630
        $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
631
 
632
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
633
 
634
        $now = time();
635
        $forum = $this->create_forum(['cutoffdate' => $now + 86400 , 'blockafter' => 5, 'blockperiod' => 86400]);
636
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
637
        $this->prevent_capability('mod/forum:postwithoutthrottling');
638
        $this->give_capability('mod/forum:replypost');
639
        $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
640
 
641
        $forum = $this->create_forum(['cutoffdate' => $now + 86400 , 'blockafter' => 1, 'blockperiod' => 86400]);
642
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
643
        $this->prevent_capability('mod/forum:postwithoutthrottling');
644
        $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
645
    }
646
 
647
    /**
648
     * Test can_edit_post.
649
     *
650
     * @covers ::can_edit_post
651
     */
11 efrain 652
    public function test_can_edit_post(): void {
1 efrain 653
        global $CFG;
654
 
655
        $this->resetAfterTest();
656
 
657
        $forum = $this->create_forum();
658
        $discussion = $this->discussion;
659
        // The generated post is created 100 seconds in the past.
660
        $post = $this->post;
661
        $user = $this->user;
662
        $otheruser = $this->getDataGenerator()->create_user();
663
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
664
 
665
        $this->prevent_capability('mod/forum:editanypost');
666
 
667
        // 200 seconds to edit.
668
        $CFG->maxeditingtime = 200;
669
        $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
670
 
671
        // Can not edit within editing time if $post->mailnow > 0 (selected).
672
        $CFG->maxeditingtime = 200;
673
        $post = $this->entityfactory->get_post_from_stdClass(
674
            (object) array_merge((array) $this->postrecord, ['mailnow' => 1])
675
        );
676
        $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
677
 
678
        // Back to normal - mailnow not selected.
679
        $post = $this->entityfactory->get_post_from_stdClass(
680
            (object) array_merge((array) $this->postrecord, ['mailnow' => 0])
681
        );
682
 
683
        // 10 seconds to edit. No longer in editing time.
684
        $CFG->maxeditingtime = 10;
685
        $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
686
 
687
        // Can edit outside of editing time with this capability.
688
        $this->give_capability('mod/forum:editanypost');
689
        $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
690
 
691
        $CFG->maxeditingtime = 200;
692
        $this->assertFalse($capabilitymanager->can_edit_post($otheruser, $discussion, $post));
693
 
694
        $this->prevent_capability('mod/forum:editanypost');
695
 
696
        // News forum.
697
        $forum = $this->create_forum(['type' => 'news']);
698
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
699
        // Discussion hasn't started yet.
700
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
701
            (object) array_merge((array) $this->discussionrecord, ['timestart' => time() + 100])
702
        );
703
 
704
        $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
705
 
706
        // Back to a discussion that has started.
707
        $discussion = $this->discussion;
708
        // Post is a reply.
709
        $post = $this->entityfactory->get_post_from_stdClass(
710
            (object) array_merge((array) $this->postrecord, ['parent' => 5])
711
        );
712
 
713
        $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
714
 
715
        $post = $this->post;
716
        // Discussion has started and post isn't a reply so we can edit it.
717
        $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
718
 
719
        // Single forum.
720
        $forum = $this->create_forum(['type' => 'single']);
721
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
722
 
723
        // Create a new post that definitely isn't the first post of the discussion.
724
        // Only the author, and a user with editanypost can edit it.
725
        $post = $this->entityfactory->get_post_from_stdClass(
726
            (object) array_merge((array) $this->postrecord, ['id' => $post->get_id() + 100])
727
        );
728
        $this->give_capability('mod/forum:editanypost');
729
        $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
730
        $this->assertFalse($capabilitymanager->can_edit_post($otheruser, $discussion, $post));
731
 
732
        $post = $this->post;
733
        // Set the first post of the discussion to our post.
734
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
735
            (object) array_merge((array) $this->discussionrecord, ['firstpost' => $post->get_id()])
736
        );
737
 
738
        $this->prevent_capability('moodle/course:manageactivities');
739
        $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
740
 
741
        $this->give_capability('moodle/course:manageactivities');
742
        $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
743
    }
744
 
745
    /**
746
     * Test can_delete_post.
747
     *
748
     * @covers ::can_delete_post
749
     */
11 efrain 750
    public function test_can_delete_post(): void {
1 efrain 751
        global $CFG;
752
 
753
        $this->resetAfterTest();
754
 
755
        // Single forum.
756
        $forum = $this->create_forum(['type' => 'single']);
757
        // The generated post is created 100 seconds in the past.
758
        $post = $this->post;
759
        $user = $this->user;
760
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
761
 
762
        // Set the first post of the discussion to our post.
763
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
764
            (object) array_merge((array) $this->discussionrecord, ['firstpost' => $post->get_id()])
765
        );
766
 
767
        // Can't delete the first post of a single discussion forum.
768
        $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
769
 
770
        // Set the first post of the discussion to something else.
771
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
772
            (object) array_merge((array) $this->discussionrecord, ['firstpost' => $post->get_id() - 1])
773
        );
774
 
775
        $this->assertTrue($capabilitymanager->can_delete_post($user, $discussion, $post));
776
 
777
        // Back to a general forum.
778
        $forum = $this->create_forum();
779
        $this->prevent_capability('mod/forum:deleteanypost');
780
        $this->give_capability('mod/forum:deleteownpost');
781
        // 200 second editing time to make sure our post is still within it.
782
        $CFG->maxeditingtime = 200;
783
 
784
        // Can not delete within editing time if $post->mailnow > 0 (selected).
785
        $post = $this->entityfactory->get_post_from_stdClass(
786
            (object) array_merge((array) $this->postrecord, ['mailnow' => 1])
787
        );
788
        $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
789
 
790
        // Back to normal - mailnow not selected.
791
        $post = $this->entityfactory->get_post_from_stdClass(
792
            (object) array_merge((array) $this->postrecord, ['mailnow' => 0])
793
        );
794
 
795
        // Make the post owned by someone else.
796
        $post = $this->entityfactory->get_post_from_stdClass(
797
            (object) array_merge((array) $this->postrecord, ['userid' => $user->id - 1])
798
        );
799
 
800
        // Can't delete someone else's post.
801
        $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
802
        // Back to our post.
803
        $post = $this->post;
804
 
805
        // Not in editing time.
806
        $CFG->maxeditingtime = 10;
807
        $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
808
 
809
        $CFG->maxeditingtime = 200;
810
        // Remove the capability to delete own post.
811
        $this->prevent_capability('mod/forum:deleteownpost');
812
        $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
813
 
814
        $this->give_capability('mod/forum:deleteownpost');
815
        $this->assertTrue($capabilitymanager->can_delete_post($user, $discussion, $post));
816
 
817
        $this->give_capability('mod/forum:deleteanypost');
818
        $CFG->maxeditingtime = 10;
819
        $this->assertTrue($capabilitymanager->can_delete_post($user, $discussion, $post));
820
    }
821
 
822
    /**
823
     * Test can_split_post.
824
     *
825
     * @covers ::can_split_post
826
     */
11 efrain 827
    public function test_can_split_post(): void {
1 efrain 828
        $this->resetAfterTest();
829
 
830
        $forum = $this->create_forum();
831
        $user = $this->user;
832
        $discussion = $this->discussion;
833
        $post = $this->post;
834
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
835
 
836
        // Make the post a reply.
837
        $post = $this->entityfactory->get_post_from_stdClass(
838
            (object) array_merge((array) $this->postrecord, ['parent' => 5])
839
        );
840
 
841
        $this->prevent_capability('mod/forum:splitdiscussions');
842
        $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
843
 
844
        $this->give_capability('mod/forum:splitdiscussions');
845
        $this->assertTrue($capabilitymanager->can_split_post($user, $discussion, $post));
846
 
847
        // Make the post have no parent.
848
        $post = $this->entityfactory->get_post_from_stdClass(
849
            (object) array_merge((array) $this->postrecord, ['parent' => 0])
850
        );
851
 
852
        $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
853
 
854
        $forum = $this->create_forum(['type' => 'single']);
855
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
856
        // Make the post a reply.
857
        $post = $this->entityfactory->get_post_from_stdClass(
858
            (object) array_merge((array) $this->postrecord, ['parent' => 5])
859
        );
860
 
861
        // Can't split a single discussion forum.
862
        $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
863
 
864
        // Make the post a private reply.
865
        $post = $this->entityfactory->get_post_from_stdClass(
866
            (object) array_merge((array) $this->postrecord, ['parent' => 5, 'privatereplyto' => $user->id])
867
        );
868
 
869
        // Can't split at a private reply.
870
        $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
871
    }
872
 
873
    /**
874
     * Test can_reply_to_post.
875
     *
876
     * @covers ::can_reply_to_post
877
     */
11 efrain 878
    public function test_can_reply_to_post(): void {
1 efrain 879
        $this->resetAfterTest();
880
 
881
        $discussion = $this->discussion;
882
        $user = $this->user;
883
        $post = $this->post;
884
 
885
        // Locked discussions.
886
        $lockedforum = $this->create_forum(['lockdiscussionafter' => 1]);
887
        $capabilitymanager = $this->managerfactory->get_capability_manager($lockedforum);
888
 
889
        $this->give_capability('mod/forum:canoverridediscussionlock');
890
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
891
 
892
        $this->prevent_capability('mod/forum:canoverridediscussionlock');
893
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
894
 
895
        // News forum.
896
        $newsforum = $this->create_forum(['type' => 'news']);
897
        $capabilitymanager = $this->managerfactory->get_capability_manager($newsforum);
898
 
899
        $this->give_capability('mod/forum:replynews');
900
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
901
 
902
        $this->prevent_capability('mod/forum:replynews');
903
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
904
 
905
        // General forum.
906
        $forum = $this->create_forum();
907
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
908
 
909
        $this->give_capability('mod/forum:replypost');
910
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
911
 
912
        $this->prevent_capability('mod/forum:replypost');
913
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
914
 
915
        // Forum in separate group mode.
916
        $forumrecord = $this->getDataGenerator()->create_module(
917
            'forum',
918
            ['course' => $this->course->id, 'groupmode' => SEPARATEGROUPS]
919
        );
920
        $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
921
        $context = \context_module::instance($coursemodule->id);
922
        $forum = $this->entityfactory->get_forum_from_stdClass(
923
            $forumrecord,
924
            $context,
925
            $coursemodule,
926
            $this->course
927
        );
928
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
929
 
930
        $this->give_capability('moodle/site:accessallgroups', $context);
931
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
932
 
933
        $this->prevent_capability('moodle/site:accessallgroups', $context);
934
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
935
 
936
        $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
937
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
938
            (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
939
        );
940
 
941
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
942
 
943
        $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
944
 
945
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
946
 
947
        // Forum in visible group mode.
948
        $forumrecord = $this->getDataGenerator()->create_module(
949
            'forum',
950
            ['course' => $this->course->id, 'groupmode' => VISIBLEGROUPS]
951
        );
952
        $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
953
        $context = \context_module::instance($coursemodule->id);
954
        $forum = $this->entityfactory->get_forum_from_stdClass(
955
            $forumrecord,
956
            $context,
957
            $coursemodule,
958
            $this->course
959
        );
960
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
961
 
962
        $this->give_capability('moodle/site:accessallgroups', $context);
963
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
964
 
965
        $this->prevent_capability('moodle/site:accessallgroups', $context);
966
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
967
 
968
        $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
969
        $discussion = $this->entityfactory->get_discussion_from_stdClass(
970
            (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
971
        );
972
 
973
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
974
 
975
        $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
976
 
977
        $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
978
 
979
        // Make the post a private reply.
980
        $post = $this->entityfactory->get_post_from_stdClass(
981
            (object) array_merge((array) $this->postrecord, ['parent' => 5, 'privatereplyto' => $user->id])
982
        );
983
 
984
        // Can't reply to a a private reply.
985
        $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
986
    }
987
 
988
    /**
989
     * Test for \mod_forum\local\managers\capability::can_reply_to_post() involving Q & A forums.
990
     */
11 efrain 991
    public function test_can_reply_to_post_in_qanda_forum(): void {
1 efrain 992
        global $CFG;
993
 
994
        $this->resetAfterTest();
995
 
996
        // Set max editing time to 10 seconds.
997
        $CFG->maxeditingtime = 10;
998
 
999
        $qandaforum = $this->create_forum(['type' => 'qanda']);
1000
        $datagenerator = $this->getDataGenerator();
1001
        $capabilitymanager = $this->managerfactory->get_capability_manager($qandaforum);
1002
 
1003
        // Student 1.
1004
        $student1 = $datagenerator->create_user(['firstname' => 'S1']);
1005
        $datagenerator->enrol_user($student1->id, $this->course->id, 'student');
1006
        // Confirm Student 1 can reply to the question.
1007
        $this->assertTrue($capabilitymanager->can_reply_to_post($student1, $this->discussion, $this->post));
1008
 
1009
        // Student 2.
1010
        $student2 = $datagenerator->create_user(['firstname' => 'S2']);
1011
        $datagenerator->enrol_user($student2->id, $this->course->id, 'student');
1012
        // Confirm Student 2 can reply to the question.
1013
        $this->assertTrue($capabilitymanager->can_reply_to_post($student2, $this->discussion, $this->post));
1014
 
1015
        // Reply to the question as student 1.
1016
        $now = time();
1017
        $options = ['parent' => $this->post->get_id(), 'created' => $now - 100];
1018
        $student1post = $this->helper_post_to_discussion($this->forumrecord, $this->discussionrecord, $student1, $options);
1019
        $student1postentity = $this->entityfactory->get_post_from_stdClass($student1post);
1020
 
1021
        // Confirm Student 2 cannot reply student 1's answer yet.
1022
        $this->assertFalse($capabilitymanager->can_reply_to_post($student2, $this->discussion, $student1postentity));
1023
 
1024
        // Reply to the question as student 2.
1025
        $this->helper_post_to_discussion($this->forumrecord, $this->discussionrecord, $student2, $options);
1026
 
1027
        // Reinitialise capability manager first to ensure we don't return cached values.
1028
        $capabilitymanager = $this->managerfactory->get_capability_manager($qandaforum);
1029
 
1030
        // Confirm Student 2 can now reply to student 1's answer.
1031
        $this->assertTrue($capabilitymanager->can_reply_to_post($student2, $this->discussion, $student1postentity));
1032
    }
1033
 
1034
    /**
1035
     * Ensure that can_reply_privately_to_post works as expected.
1036
     *
1037
     * @covers ::can_reply_privately_to_post
1038
     */
11 efrain 1039
    public function test_can_reply_privately_to_post(): void {
1 efrain 1040
        $this->resetAfterTest();
1041
 
1042
        $forum = $this->create_forum();
1043
        $discussion = $this->discussion;
1044
        $user = $this->user;
1045
        $post = $this->post;
1046
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1047
 
1048
        // Without the capability, and with a standard post, it is not possible to reply privately.
1049
        $this->prevent_capability('mod/forum:postprivatereply');
1050
        $this->assertFalse($capabilitymanager->can_reply_privately_to_post($this->user, $post));
1051
 
1052
        // With the capability, and a standard post, it is possible to reply privately.
1053
        $this->give_capability('mod/forum:postprivatereply');
1054
        $this->assertTrue($capabilitymanager->can_reply_privately_to_post($this->user, $post));
1055
 
1056
        // Make the post a private reply.
1057
        $post = $this->entityfactory->get_post_from_stdClass(
1058
            (object) array_merge((array) $this->postrecord, ['parent' => 5, 'privatereplyto' => $user->id])
1059
        );
1060
 
1061
        // Can't ever reply to a a private reply.
1062
        $this->assertFalse($capabilitymanager->can_reply_privately_to_post($user, $post));
1063
    }
1064
 
1065
    /**
1066
     * Ensure that can_view_post works as expected.
1067
     *
1068
     * @covers ::can_view_post
1069
     */
11 efrain 1070
    public function test_can_view_post(): void {
1 efrain 1071
        $this->resetAfterTest();
1072
 
1073
        $forum = $this->create_forum();
1074
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1075
 
1076
        $user = $this->user;
1077
        $otheruser = $this->getDataGenerator()->create_user();
1078
 
1079
        $discussion = $this->discussion;
1080
        $post = $this->post;
1081
 
1082
        $postproperties = ['parent' => $post->get_id(), 'userid' => $otheruser->id, 'privatereplyto' => $otheruser->id];
1083
        $privatepost = $this->entityfactory->get_post_from_stdClass(
1084
            (object) array_merge((array) $this->postrecord, $postproperties)
1085
        );
1086
 
1087
        $this->prevent_capability('mod/forum:readprivatereplies');
1088
        $this->assertFalse($capabilitymanager->can_view_post($user, $discussion, $privatepost));
1089
    }
1090
 
1091
    /**
1092
     * Ensure that can_view_post_shell considers private replies correctly.
1093
     *
1094
     * @covers ::can_view_post_shell
1095
     */
11 efrain 1096
    public function test_can_view_post_shell(): void {
1 efrain 1097
        $this->resetAfterTest();
1098
 
1099
        $forum = $this->create_forum();
1100
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1101
 
1102
        $user = $this->user;
1103
        $otheruser = $this->getDataGenerator()->create_user();
1104
 
1105
        $discussion = $this->discussion;
1106
        $post = $this->post;
1107
 
1108
        $postproperties = ['parent' => $post->get_id(), 'userid' => $user->id, 'privatereplyto' => $user->id];
1109
        $privatepostfrommetome = $this->entityfactory->get_post_from_stdClass(
1110
            (object) array_merge((array) $this->postrecord, $postproperties)
1111
        );
1112
 
1113
        $postproperties = ['parent' => $post->get_id(), 'userid' => $user->id, 'privatereplyto' => $otheruser->id];
1114
        $privatepostfrommetoother = $this->entityfactory->get_post_from_stdClass(
1115
            (object) array_merge((array) $this->postrecord, $postproperties)
1116
        );
1117
 
1118
        $postproperties = ['parent' => $post->get_id(), 'userid' => $otheruser->id, 'privatereplyto' => $user->id];
1119
        $privatepostfromothertome = $this->entityfactory->get_post_from_stdClass(
1120
            (object) array_merge((array) $this->postrecord, $postproperties)
1121
        );
1122
 
1123
        $postproperties = ['parent' => $post->get_id(), 'userid' => $otheruser->id, 'privatereplyto' => $otheruser->id];
1124
        $privatepostfromothertoother = $this->entityfactory->get_post_from_stdClass(
1125
            (object) array_merge((array) $this->postrecord, $postproperties)
1126
        );
1127
 
1128
        // Can always view public replies, and private replies by me or to me.
1129
        $this->prevent_capability('mod/forum:readprivatereplies');
1130
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $post));
1131
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfrommetome));
1132
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfrommetoother));
1133
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfromothertome));
1134
        $this->assertFalse($capabilitymanager->can_view_post_shell($this->user, $privatepostfromothertoother));
1135
 
1136
        $this->give_capability('mod/forum:readprivatereplies');
1137
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $post));
1138
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfrommetome));
1139
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfrommetoother));
1140
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfromothertome));
1141
        $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepostfromothertoother));
1142
    }
1143
 
1144
    /**
1145
     * Test can_export_post.
1146
     *
1147
     * @covers ::can_export_post
1148
     */
11 efrain 1149
    public function test_can_export_post(): void {
1 efrain 1150
        global $CFG;
1151
        $this->resetAfterTest();
1152
 
1153
        $forum = $this->create_forum();
1154
        $post = $this->post;
1155
        $user = $this->user;
1156
        $otheruser = $this->getDataGenerator()->create_user();
1157
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1158
 
1159
        $this->getDataGenerator()->enrol_user($otheruser->id, $this->course->id, 'teacher');
1160
 
1161
        $CFG->enableportfolios = true;
1162
        $this->give_capability('mod/forum:exportpost');
1163
 
1164
        $this->assertTrue($capabilitymanager->can_export_post($otheruser, $post));
1165
 
1166
        $CFG->enableportfolios = false;
1167
        $this->assertFalse($capabilitymanager->can_export_post($otheruser, $post));
1168
 
1169
        $CFG->enableportfolios = true;
1170
        $this->prevent_capability('mod/forum:exportpost');
1171
        // Can't export another user's post without the exportpost capavility.
1172
        $this->assertFalse($capabilitymanager->can_export_post($otheruser, $post));
1173
 
1174
        $this->give_capability('mod/forum:exportownpost');
1175
        // Can export own post with the exportownpost capability.
1176
        $this->assertTrue($capabilitymanager->can_export_post($user, $post));
1177
 
1178
        $this->prevent_capability('mod/forum:exportownpost');
1179
        $this->assertFalse($capabilitymanager->can_export_post($user, $post));
1180
    }
1181
 
1182
    /**
1183
     * Test can_view_participants.
1184
     *
1185
     * @covers ::can_view_participants
1186
     */
11 efrain 1187
    public function test_can_view_participants(): void {
1 efrain 1188
        $this->resetAfterTest();
1189
 
1190
        $discussion = $this->discussion;
1191
        $user = $this->user;
1192
        $otheruser = $this->getDataGenerator()->create_user();
1193
 
1194
        $this->getDataGenerator()->enrol_user($otheruser->id, $this->course->id, 'teacher');
1195
 
1196
        $this->prevent_capability('moodle/course:viewparticipants');
1197
        $this->prevent_capability('moodle/course:enrolreview');
1198
        $this->prevent_capability('mod/forum:viewqandawithoutposting');
1199
 
1200
        $forum = $this->create_forum();
1201
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1202
 
1203
        $this->assertFalse($capabilitymanager->can_view_participants($otheruser, $discussion));
1204
 
1205
        $this->give_capability('moodle/course:viewparticipants');
1206
        $this->assertTrue($capabilitymanager->can_view_participants($otheruser, $discussion));
1207
 
1208
        $this->prevent_capability('moodle/course:viewparticipants');
1209
        $this->give_capability('moodle/course:enrolreview');
1210
        $this->assertTrue($capabilitymanager->can_view_participants($otheruser, $discussion));
1211
 
1212
        $forum = $this->create_forum(['type' => 'qanda']);
1213
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1214
 
1215
        // Q and A forum requires the user to post before they can view it.
1216
        $this->prevent_capability('mod/forum:viewqandawithoutposting');
1217
        $this->assertFalse($capabilitymanager->can_view_participants($otheruser, $discussion));
1218
 
1219
        // This user has posted.
1220
        $this->assertTrue($capabilitymanager->can_view_participants($user, $discussion));
1221
    }
1222
 
1223
    /**
1224
     * Test can_view_hidden_posts.
1225
     *
1226
     * @covers ::can_view_hidden_posts
1227
     */
11 efrain 1228
    public function test_can_view_hidden_posts(): void {
1 efrain 1229
        $this->resetAfterTest();
1230
 
1231
        $forum = $this->create_forum();
1232
        $user = $this->user;
1233
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1234
 
1235
        $this->prevent_capability('mod/forum:viewhiddentimedposts');
1236
        $this->assertFalse($capabilitymanager->can_view_hidden_posts($user));
1237
 
1238
        $this->give_capability('mod/forum:viewhiddentimedposts');
1239
        $this->assertTrue($capabilitymanager->can_view_hidden_posts($user));
1240
    }
1241
 
1242
    /**
1243
     * Test can_manage_forum.
1244
     *
1245
     * @covers ::can_manage_forum
1246
     */
11 efrain 1247
    public function test_can_manage_forum(): void {
1 efrain 1248
        $this->resetAfterTest();
1249
 
1250
        $forum = $this->create_forum();
1251
        $user = $this->user;
1252
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1253
 
1254
        $this->prevent_capability('moodle/course:manageactivities');
1255
        $this->assertFalse($capabilitymanager->can_manage_forum($user));
1256
 
1257
        $this->give_capability('moodle/course:manageactivities');
1258
        $this->assertTrue($capabilitymanager->can_manage_forum($user));
1259
    }
1260
 
1261
    /**
1262
     * Test can_manage_tags.
1263
     *
1264
     * @covers ::can_manage_tags
1265
     */
11 efrain 1266
    public function test_can_manage_tags(): void {
1 efrain 1267
        global $DB;
1268
        $this->resetAfterTest();
1269
 
1270
        $forum = $this->create_forum();
1271
        $user = $this->user;
1272
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1273
        $context = \context_system::instance();
1274
        $roleid = $DB->get_field('role', 'id', ['shortname' => 'user'], MUST_EXIST);
1275
 
1276
        assign_capability('moodle/tag:manage', CAP_PREVENT, $roleid, $context->id, true);
1277
        $this->assertFalse($capabilitymanager->can_manage_tags($user));
1278
 
1279
        assign_capability('moodle/tag:manage', CAP_ALLOW, $roleid, $context->id, true);
1280
        $this->assertTrue($capabilitymanager->can_manage_tags($user));
1281
    }
1282
 
1283
    /**
1284
     * Ensure that the can_view_any_private_reply works as expected.
1285
     *
1286
     * @covers ::can_view_any_private_reply
1287
     */
11 efrain 1288
    public function test_can_view_any_private_reply(): void {
1 efrain 1289
        $this->resetAfterTest();
1290
 
1291
        $forum = $this->create_forum();
1292
        $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1293
 
1294
        $this->give_capability('mod/forum:readprivatereplies');
1295
        $this->assertTrue($capabilitymanager->can_view_any_private_reply($this->user));
1296
        $this->prevent_capability('mod/forum:readprivatereplies');
1297
        $this->assertFalse($capabilitymanager->can_view_any_private_reply($this->user));
1298
    }
1299
 
1300
 
1301
    /**
1302
     * Test delete a post with ratings.
1303
     */
11 efrain 1304
    public function test_validate_delete_post_with_ratings(): void {
1 efrain 1305
        global $DB;
1306
        $this->resetAfterTest(true);
1307
 
1308
        // Setup test data.
1309
        $course = $this->getDataGenerator()->create_course();
1310
        $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
1311
        $user = $this->getDataGenerator()->create_user();
1312
        $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1313
        self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
1314
 
1315
        // Add a discussion.
1316
        $record = new \stdClass();
1317
        $record->course = $course->id;
1318
        $record->userid = $user->id;
1319
        $record->forum = $forum->id;
1320
        $record->created =
1321
        $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
1322
 
1323
        // Add rating.
1324
        $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
1325
        $post->totalscore = 80;
1326
        $DB->update_record('forum_posts', $post);
1327
 
1328
        $vaultfactory = container::get_vault_factory();
1329
        $forumvault = $vaultfactory->get_forum_vault();
1330
        $discussionvault = $vaultfactory->get_discussion_vault();
1331
        $postvault = $vaultfactory->get_post_vault();
1332
 
1333
        $postentity = $postvault->get_from_id($post->id);
1334
        $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id());
1335
        $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id());
1336
        $capabilitymanager = $this->managerfactory->get_capability_manager($forumentity);
1337
 
1338
        $this->setUser($user);
1339
        $this->expectExceptionMessage(get_string('couldnotdeleteratings', 'rating'));
1340
        $capabilitymanager->validate_delete_post($user, $discussionentity, $postentity, false);
1341
    }
1342
 
1343
    /**
1344
     * Test delete a post with replies.
1345
     */
11 efrain 1346
    public function test_validate_delete_post_with_replies(): void {
1 efrain 1347
        global $DB;
1348
        $this->resetAfterTest(true);
1349
 
1350
        // Setup test data.
1351
        $course = $this->getDataGenerator()->create_course();
1352
        $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
1353
        $user = $this->getDataGenerator()->create_user();
1354
        $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1355
        self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
1356
 
1357
        // Add a discussion.
1358
        $record = new \stdClass();
1359
        $record->course = $course->id;
1360
        $record->userid = $user->id;
1361
        $record->forum = $forum->id;
1362
        $record->created =
1363
        $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
1364
 
1365
        $parentpost = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
1366
        // Add a post.
1367
        $record = new \stdClass();
1368
        $record->course = $course->id;
1369
        $record->userid = $user->id;
1370
        $record->forum = $forum->id;
1371
        $record->discussion = $discussion->id;
1372
        $record->parent = $parentpost->id;
1373
        $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
1374
 
1375
        $vaultfactory = container::get_vault_factory();
1376
        $forumvault = $vaultfactory->get_forum_vault();
1377
        $discussionvault = $vaultfactory->get_discussion_vault();
1378
        $postvault = $vaultfactory->get_post_vault();
1379
 
1380
        $postentity = $postvault->get_from_id($parentpost->id);
1381
        $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id());
1382
        $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id());
1383
        $capabilitymanager = $this->managerfactory->get_capability_manager($forumentity);
1384
 
1385
        $this->setUser($user);
1386
        // Get reply count.
1387
        $replycount = $postvault->get_reply_count_for_post_id_in_discussion_id(
1388
            $user, $postentity->get_id(), $discussionentity->get_id(), true);
1389
        $this->expectExceptionMessage(get_string('couldnotdeletereplies', 'forum'));
1390
        $capabilitymanager->validate_delete_post($user, $discussionentity, $postentity, $replycount);
1391
    }
1392
 
1393
}