Proyectos de Subversion Moodle

Rev

Rev 11 | | Comparar con el anterior | Ultima modificación | Ver Log |

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