Merge branch 'MDL-65017-master' of git://github.com/jleyva/moodle
[moodle.git] / mod / forum / tests / managers_capability_test.php
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/>.
17 /**
18  * The capability manager tests.
19  *
20  * @package    mod_forum
21  * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 global $CFG;
28 require_once(__DIR__ . '/generator_trait.php');
30 use mod_forum\local\managers\capability as capability_manager;
32 /**
33  * The capability manager tests.
34  *
35  * @package    mod_forum
36  * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  * @coversDefaultClass \mod_forum\local\managers\capability
39  */
40 class mod_forum_managers_capability_testcase extends advanced_testcase {
41     // Make use of the test generator trait.
42     use mod_forum_tests_generator_trait;
44     /** @var stdClass */
45     private $user;
47     /** @var \mod_forum\local\factories\entity */
48     private $entityfactory;
50     /** @var \mod_forum\local\factories\manager */
51     private $managerfactory;
53     /** @var stdClass */
54     private $course;
56     /** @var stdClass */
57     private $forumrecord;
59     /** @var stdClass */
60     private $coursemodule;
62     /** @var context */
63     private $context;
65     /** @var int */
66     private $roleid;
68     /** @var \mod_forum\local\entities\discussion */
69     private $discussion;
71     /** @var stdClass */
72     private $discussionrecord;
74     /** @var \mod_forum\local\entities\post */
75     private $post;
77     /** @var stdClass */
78     private $postrecord;
80     /**
81      * Setup function before each test.
82      */
83     public function setUp() {
84         global $DB;
86         // We must clear the subscription caches. This has to be done both before each test, and after in case of other
87         // tests using these functions.
88         \mod_forum\subscriptions::reset_forum_cache();
90         $datagenerator = $this->getDataGenerator();
91         $this->user = $datagenerator->create_user();
92         $this->managerfactory = \mod_forum\local\container::get_manager_factory();
93         $this->entityfactory = \mod_forum\local\container::get_entity_factory();
94         $this->course = $datagenerator->create_course();
95         $this->forumrecord = $datagenerator->create_module('forum', ['course' => $this->course->id]);
96         $this->coursemodule = get_coursemodule_from_instance('forum', $this->forumrecord->id);
97         $this->context = context_module::instance($this->coursemodule->id);
98         $this->roleid = $DB->get_field('role', 'id', ['shortname' => 'teacher'], MUST_EXIST);
100         $datagenerator->enrol_user($this->user->id, $this->course->id, 'teacher');
101         [$discussion, $post] = $this->helper_post_to_forum($this->forumrecord, $this->user, ['timemodified' => time() - 100]);
102         $this->discussion = $this->entityfactory->get_discussion_from_stdclass($discussion);
103         $this->discussionrecord = $discussion;
104         $this->post = $this->entityfactory->get_post_from_stdclass(
105             (object) array_merge((array) $post, ['timecreated' => time() - 100])
106         );
107         $this->postrecord = $post;
109         $this->setUser($this->user);
110     }
112     /**
113      * Tear down function after each test.
114      */
115     public function tearDown() {
116         // We must clear the subscription caches. This has to be done both before each test, and after in case of other
117         // tests using these functions.
118         \mod_forum\subscriptions::reset_forum_cache();
119     }
121     /**
122      * Helper function to create a forum entity.
123      *
124      * @param array $forumproperties List of properties to override the prebuilt forum
125      * @return forum_entity
126      */
127     private function create_forum(array $forumproperties = []) {
128         $forumrecord = (object) array_merge((array) $this->forumrecord, $forumproperties);
129         return $this->entityfactory->get_forum_from_stdclass(
130             $forumrecord,
131             $this->context,
132             $this->coursemodule,
133             $this->course
134         );
135     }
137     /**
138      * Helper function to assign a capability to the prebuilt role (teacher).
139      *
140      * @param string $capability Name of the capability
141      * @param context|null $context The context to assign the capability in
142      */
143     private function give_capability($capability, $context = null) {
144         $context = $context ?? $this->context;
145         assign_capability($capability, CAP_ALLOW, $this->roleid, $context->id, true);
146     }
148     /**
149      * Helper function to prevent a capability to the prebuilt role (teacher).
150      *
151      * @param string $capability Name of the capability
152      * @param context|null $context The context to assign the capability in
153      */
154     private function prevent_capability($capability, $context = null) {
155         $context = $context ?? $this->context;
156         assign_capability($capability, CAP_PREVENT, $this->roleid, $context->id, true);
157     }
159     /**
160      * Test can_subscribe_to_forum.
161      *
162      * @covers ::can_subscribe_to_forum
163      */
164     public function test_can_subscribe_to_forum() {
165         $this->resetAfterTest();
167         $forum = $this->create_forum();
168         $guestuser = $this->getDataGenerator()->create_user();
169         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
171         $this->assertFalse($capabilitymanager->can_subscribe_to_forum($guestuser));
172         $this->assertTrue($capabilitymanager->can_subscribe_to_forum($this->user));
173     }
175     /**
176      * Test can_create_discussions.
177      *
178      * @covers ::can_create_discussions
179      */
180     public function test_can_create_discussions() {
181         $this->resetAfterTest();
183         $forum = $this->create_forum();
184         $guestuser = $this->getDataGenerator()->create_user();
185         $user = $this->user;
186         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
188         $this->assertFalse($capabilitymanager->can_create_discussions($guestuser));
190         $this->prevent_capability('mod/forum:startdiscussion');
191         $this->assertFalse($capabilitymanager->can_create_discussions($user));
193         $this->give_capability('mod/forum:startdiscussion');
194         $this->assertTrue($capabilitymanager->can_create_discussions($user));
196         $forum = $this->create_forum(['type' => 'news']);
197         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
199         $this->prevent_capability('mod/forum:addnews');
200         $this->assertFalse($capabilitymanager->can_create_discussions($user));
202         $this->give_capability('mod/forum:addnews');
203         $this->assertTrue($capabilitymanager->can_create_discussions($user));
205         $forum = $this->create_forum(['type' => 'qanda']);
206         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
208         $this->prevent_capability('mod/forum:addquestion');
209         $this->assertFalse($capabilitymanager->can_create_discussions($user));
211         $this->give_capability('mod/forum:addquestion');
212         $this->assertTrue($capabilitymanager->can_create_discussions($user));
214         // Test a forum in group mode.
215         $forumrecord = $this->getDataGenerator()->create_module(
216             'forum',
217             ['course' => $this->course->id, 'groupmode' => SEPARATEGROUPS]
218         );
219         $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
220         $context = context_module::instance($coursemodule->id);
221         $forum = $this->entityfactory->get_forum_from_stdclass(
222             $forumrecord,
223             $context,
224             $coursemodule,
225             $this->course
226         );
228         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
230         $this->assertFalse($capabilitymanager->can_create_discussions($user));
232         $this->give_capability('moodle/site:accessallgroups', $context);
233         $this->assertTrue($capabilitymanager->can_create_discussions($user));
235         $this->prevent_capability('moodle/site:accessallgroups', $context);
236         $this->assertFalse($capabilitymanager->can_create_discussions($user));
238         $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
239         $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
241         $this->assertTrue($capabilitymanager->can_create_discussions($user, $group->id));
242     }
244     /**
245      * Test can_access_all_groups.
246      *
247      * @covers ::can_access_all_groups
248      */
249     public function test_can_access_all_groups() {
250         $this->resetAfterTest();
252         $forum = $this->create_forum();
253         $user = $this->user;
254         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
256         $this->prevent_capability('moodle/site:accessallgroups');
257         $this->assertFalse($capabilitymanager->can_access_all_groups($user));
259         $this->give_capability('moodle/site:accessallgroups');
260         $this->assertTrue($capabilitymanager->can_access_all_groups($user));
261     }
263     /**
264      * Test can_access_group.
265      *
266      * @covers ::can_access_group
267      */
268     public function test_can_access_group() {
269         $this->resetAfterTest();
271         $forum = $this->create_forum();
272         $user = $this->user;
273         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
274         $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
276         $this->prevent_capability('moodle/site:accessallgroups');
277         $this->assertFalse($capabilitymanager->can_access_group($user, $group->id));
279         $this->give_capability('moodle/site:accessallgroups');
280         $this->assertTrue($capabilitymanager->can_access_group($user, $group->id));
282         $this->prevent_capability('moodle/site:accessallgroups');
283         $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
284         $this->assertTrue($capabilitymanager->can_access_group($user, $group->id));
285     }
287     /**
288      * Test can_view_discussions.
289      *
290      * @covers ::can_view_discussions
291      */
292     public function test_can_view_discussions() {
293         $this->resetAfterTest();
295         $forum = $this->create_forum();
296         $user = $this->user;
297         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
299         $this->prevent_capability('mod/forum:viewdiscussion');
300         $this->assertFalse($capabilitymanager->can_view_discussions($user));
302         $this->give_capability('mod/forum:viewdiscussion');
303         $this->assertTrue($capabilitymanager->can_view_discussions($user));
304     }
306     /**
307      * Test can_move_discussions.
308      *
309      * @covers ::can_move_discussions
310      */
311     public function test_can_move_discussions() {
312         $this->resetAfterTest();
314         $forum = $this->create_forum();
315         $user = $this->user;
316         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
318         $this->prevent_capability('mod/forum:movediscussions');
319         $this->assertFalse($capabilitymanager->can_move_discussions($user));
321         $this->give_capability('mod/forum:movediscussions');
322         $this->assertTrue($capabilitymanager->can_move_discussions($user));
324         $forum = $this->create_forum(['type' => 'single']);
325         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
327         $this->assertFalse($capabilitymanager->can_move_discussions($user));
328     }
330     /**
331      * Test can_pin_discussions.
332      *
333      * @covers ::can_pin_discussions
334      */
335     public function test_can_pin_discussions() {
336         $this->resetAfterTest();
338         $forum = $this->create_forum();
339         $user = $this->user;
340         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
342         $this->prevent_capability('mod/forum:pindiscussions');
343         $this->assertFalse($capabilitymanager->can_pin_discussions($user));
345         $this->give_capability('mod/forum:pindiscussions');
346         $this->assertTrue($capabilitymanager->can_pin_discussions($user));
347     }
349     /**
350      * Test can_split_discussions.
351      *
352      * @covers ::can_split_discussions
353      */
354     public function test_can_split_discussions() {
355         $this->resetAfterTest();
357         $forum = $this->create_forum();
358         $user = $this->user;
359         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
361         $this->prevent_capability('mod/forum:splitdiscussions');
362         $this->assertFalse($capabilitymanager->can_split_discussions($user));
364         $this->give_capability('mod/forum:splitdiscussions');
365         $this->assertTrue($capabilitymanager->can_split_discussions($user));
367         $forum = $this->create_forum(['type' => 'single']);
368         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
370         $this->assertFalse($capabilitymanager->can_split_discussions($user));
371     }
373     /**
374      * Test can_export_discussions.
375      *
376      * @covers ::can_export_discussions
377      */
378     public function test_can_export_discussions() {
379         global $CFG;
380         $this->resetAfterTest();
382         $CFG->enableportfolios = true;
383         $forum = $this->create_forum();
384         $user = $this->user;
385         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
387         $this->prevent_capability('mod/forum:exportdiscussion');
388         $this->assertFalse($capabilitymanager->can_export_discussions($user));
390         $this->give_capability('mod/forum:exportdiscussion');
391         $this->assertTrue($capabilitymanager->can_export_discussions($user));
393         $CFG->enableportfolios = false;
395         $this->assertFalse($capabilitymanager->can_export_discussions($user));
396     }
398     /**
399      * Test can_manually_control_post_read_status.
400      *
401      * @covers ::can_manually_control_post_read_status
402      */
403     public function test_can_manually_control_post_read_status() {
404         global $CFG, $DB;
405         $this->resetAfterTest();
407         $CFG->forum_usermarksread = true;
408         $forum = $this->create_forum();
409         $user = $this->user;
410         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
411         $cache = cache::make('mod_forum', 'forum_is_tracked');
413         $user->trackforums = true;
414         $prefid = $DB->insert_record('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forum->get_id()]);
415         $this->assertFalse($capabilitymanager->can_manually_control_post_read_status($user));
416         $cache->purge();
418         $DB->delete_records('forum_track_prefs', ['id' => $prefid]);
419         $this->assertTrue($capabilitymanager->can_manually_control_post_read_status($user));
420         $cache->purge();
422         $CFG->forum_usermarksread = false;
424         $this->assertFalse($capabilitymanager->can_manually_control_post_read_status($user));
425     }
427     /**
428      * Test must_post_before_viewing_discussion.
429      *
430      * @covers ::must_post_before_viewing_discussion
431      */
432     public function test_must_post_before_viewing_discussion() {
433         $this->resetAfterTest();
435         $forum = $this->create_forum();
436         $user = $this->user;
437         $discussion = $this->discussion;
438         $newuser = $this->getDataGenerator()->create_user();
439         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
440         $this->getDataGenerator()->enrol_user($newuser->id, $this->course->id, 'teacher');
442         $this->assertFalse($capabilitymanager->must_post_before_viewing_discussion($newuser, $discussion));
444         $forum = $this->create_forum(['type' => 'qanda']);
445         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
447         $this->prevent_capability('mod/forum:viewqandawithoutposting');
448         $this->assertTrue($capabilitymanager->must_post_before_viewing_discussion($newuser, $discussion));
450         $this->give_capability('mod/forum:viewqandawithoutposting');
451         $this->assertFalse($capabilitymanager->must_post_before_viewing_discussion($newuser, $discussion));
453         $this->prevent_capability('mod/forum:viewqandawithoutposting');
454         // The pre-generated user has a pre-generated post in the disussion already.
455         $this->assertFalse($capabilitymanager->must_post_before_viewing_discussion($user, $discussion));
456     }
458     /**
459      * Test can_subscribe_to_discussion.
460      *
461      * @covers ::can_subscribe_to_discussion
462      */
463     public function test_can_subscribe_to_discussion() {
464         $this->resetAfterTest();
466         $forum = $this->create_forum();
467         $discussion = $this->discussion;
468         $guestuser = $this->getDataGenerator()->create_user();
469         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
471         $this->assertFalse($capabilitymanager->can_subscribe_to_discussion($guestuser, $discussion));
472         $this->assertTrue($capabilitymanager->can_subscribe_to_discussion($this->user, $discussion));
473     }
475     /**
476      * Test can_move_discussion.
477      *
478      * @covers ::can_move_discussion
479      */
480     public function test_can_move_discussion() {
481         $this->resetAfterTest();
483         $forum = $this->create_forum();
484         $discussion = $this->discussion;
485         $user = $this->user;
486         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
488         $this->prevent_capability('mod/forum:movediscussions');
489         $this->assertFalse($capabilitymanager->can_move_discussion($user, $discussion));
491         $this->give_capability('mod/forum:movediscussions');
492         $this->assertTrue($capabilitymanager->can_move_discussion($user, $discussion));
494         $forum = $this->create_forum(['type' => 'single']);
495         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
497         $this->assertFalse($capabilitymanager->can_move_discussion($user, $discussion));
498     }
500     /**
501      * Test can_pin_discussion.
502      *
503      * @covers ::can_pin_discussion
504      */
505     public function test_can_pin_discussion() {
506         $this->resetAfterTest();
508         $forum = $this->create_forum();
509         $discussion = $this->discussion;
510         $user = $this->user;
511         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
513         $this->prevent_capability('mod/forum:pindiscussions');
514         $this->assertFalse($capabilitymanager->can_pin_discussion($user, $discussion));
516         $this->give_capability('mod/forum:pindiscussions');
517         $this->assertTrue($capabilitymanager->can_pin_discussion($user, $discussion));
518     }
520     /**
521      * Test can_post_in_discussion.
522      *
523      * @covers ::can_post_in_discussion
524      */
525     public function test_can_post_in_discussion() {
526         $this->resetAfterTest();
528         $discussion = $this->discussion;
529         $user = $this->user;
531         // Locked discussions.
532         $lockedforum = $this->create_forum(['lockdiscussionafter' => 1]);
533         $capabilitymanager = $this->managerfactory->get_capability_manager($lockedforum);
535         $this->give_capability('mod/forum:canoverridediscussionlock');
536         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
538         $this->prevent_capability('mod/forum:canoverridediscussionlock');
539         $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
541         // News forum.
542         $newsforum = $this->create_forum(['type' => 'news']);
543         $capabilitymanager = $this->managerfactory->get_capability_manager($newsforum);
545         $this->give_capability('mod/forum:replynews');
546         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
548         $this->prevent_capability('mod/forum:replynews');
549         $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
551         // General forum.
552         $forum = $this->create_forum();
553         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
555         $this->give_capability('mod/forum:replypost');
556         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
558         $this->prevent_capability('mod/forum:replypost');
559         $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
561         // Forum in separate group mode.
562         $forumrecord = $this->getDataGenerator()->create_module(
563             'forum',
564             ['course' => $this->course->id, 'groupmode' => SEPARATEGROUPS]
565         );
566         $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
567         $context = context_module::instance($coursemodule->id);
568         $forum = $this->entityfactory->get_forum_from_stdclass(
569             $forumrecord,
570             $context,
571             $coursemodule,
572             $this->course
573         );
574         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
576         $this->give_capability('moodle/site:accessallgroups', $context);
577         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
579         $this->prevent_capability('moodle/site:accessallgroups', $context);
580         $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
582         $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
583         $discussion = $this->entityfactory->get_discussion_from_stdclass(
584             (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
585         );
587         $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
589         $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
591         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
593         // Forum in visible group mode.
594         $forumrecord = $this->getDataGenerator()->create_module(
595             'forum',
596             ['course' => $this->course->id, 'groupmode' => VISIBLEGROUPS]
597         );
598         $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
599         $context = context_module::instance($coursemodule->id);
600         $forum = $this->entityfactory->get_forum_from_stdclass(
601             $forumrecord,
602             $context,
603             $coursemodule,
604             $this->course
605         );
606         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
608         $this->give_capability('moodle/site:accessallgroups', $context);
609         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
611         $this->prevent_capability('moodle/site:accessallgroups', $context);
612         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
614         $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
615         $discussion = $this->entityfactory->get_discussion_from_stdclass(
616             (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
617         );
619         $this->assertFalse($capabilitymanager->can_post_in_discussion($user, $discussion));
621         $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
623         $this->assertTrue($capabilitymanager->can_post_in_discussion($user, $discussion));
624     }
626     /**
627      * Test can_edit_post.
628      *
629      * @covers ::can_edit_post
630      */
631     public function test_can_edit_post() {
632         global $CFG;
634         $this->resetAfterTest();
636         $forum = $this->create_forum();
637         $discussion = $this->discussion;
638         // The generated post is created 100 seconds in the past.
639         $post = $this->post;
640         $user = $this->user;
641         $otheruser = $this->getDataGenerator()->create_user();
642         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
644         $this->prevent_capability('mod/forum:editanypost');
646         // 200 seconds to edit.
647         $CFG->maxeditingtime = 200;
648         $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
650         // 10 seconds to edit. No longer in editing time.
651         $CFG->maxeditingtime = 10;
652         $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
654         // Can edit outside of editing time with this capability.
655         $this->give_capability('mod/forum:editanypost');
656         $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
658         $CFG->maxeditingtime = 200;
659         $this->assertFalse($capabilitymanager->can_edit_post($otheruser, $discussion, $post));
661         $this->prevent_capability('mod/forum:editanypost');
663         // News forum.
664         $forum = $this->create_forum(['type' => 'news']);
665         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
666         // Discussion hasn't started yet.
667         $discussion = $this->entityfactory->get_discussion_from_stdclass(
668             (object) array_merge((array) $this->discussionrecord, ['timestart' => time() + 100])
669         );
671         $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
673         // Back to a discussion that has started.
674         $discussion = $this->discussion;
675         // Post is a reply.
676         $post = $this->entityfactory->get_post_from_stdclass(
677             (object) array_merge((array) $this->postrecord, ['parent' => 5])
678         );
680         $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
682         $post = $this->post;
683         // Discussion has started and post isn't a reply so we can edit it.
684         $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
686         // Single forum.
687         $forum = $this->create_forum(['type' => 'single']);
688         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
690         // Create a new post that definitely isn't the first post of the discussion.
691         // Only the author, and a user with editanypost can edit it.
692         $post = $this->entityfactory->get_post_from_stdclass(
693             (object) array_merge((array) $this->postrecord, ['id' => $post->get_id() + 100])
694         );
695         $this->give_capability('mod/forum:editanypost');
696         $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
697         $this->assertFalse($capabilitymanager->can_edit_post($otheruser, $discussion, $post));
699         $post = $this->post;
700         // Set the first post of the discussion to our post.
701         $discussion = $this->entityfactory->get_discussion_from_stdclass(
702             (object) array_merge((array) $this->discussionrecord, ['firstpost' => $post->get_id()])
703         );
705         $this->prevent_capability('moodle/course:manageactivities');
706         $this->assertFalse($capabilitymanager->can_edit_post($user, $discussion, $post));
708         $this->give_capability('moodle/course:manageactivities');
709         $this->assertTrue($capabilitymanager->can_edit_post($user, $discussion, $post));
710     }
712     /**
713      * Test can_delete_post.
714      *
715      * @covers ::can_delete_post
716      */
717     public function test_can_delete_post() {
718         global $CFG;
720         $this->resetAfterTest();
722         // Single forum.
723         $forum = $this->create_forum(['type' => 'single']);
724         // The generated post is created 100 seconds in the past.
725         $post = $this->post;
726         $user = $this->user;
727         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
729         // Set the first post of the discussion to our post.
730         $discussion = $this->entityfactory->get_discussion_from_stdclass(
731             (object) array_merge((array) $this->discussionrecord, ['firstpost' => $post->get_id()])
732         );
734         // Can't delete the first post of a single discussion forum.
735         $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
737         // Set the first post of the discussion to something else.
738         $discussion = $this->entityfactory->get_discussion_from_stdclass(
739             (object) array_merge((array) $this->discussionrecord, ['firstpost' => $post->get_id() - 1])
740         );
742         $this->assertTrue($capabilitymanager->can_delete_post($user, $discussion, $post));
744         // Back to a general forum.
745         $forum = $this->create_forum();
746         $this->prevent_capability('mod/forum:deleteanypost');
747         $this->give_capability('mod/forum:deleteownpost');
748         // 200 second editing time to make sure our post is still within it.
749         $CFG->maxeditingtime = 200;
751         // Make the post owned by someone else.
752         $post = $this->entityfactory->get_post_from_stdclass(
753             (object) array_merge((array) $this->postrecord, ['userid' => $user->id - 1])
754         );
756         // Can't delete someone else's post.
757         $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
758         // Back to our post.
759         $post = $this->post;
761         // Not in editing time.
762         $CFG->maxeditingtime = 10;
763         $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
765         $CFG->maxeditingtime = 200;
766         // Remove the capability to delete own post.
767         $this->prevent_capability('mod/forum:deleteownpost');
768         $this->assertFalse($capabilitymanager->can_delete_post($user, $discussion, $post));
770         $this->give_capability('mod/forum:deleteownpost');
771         $this->assertTrue($capabilitymanager->can_delete_post($user, $discussion, $post));
773         $this->give_capability('mod/forum:deleteanypost');
774         $CFG->maxeditingtime = 10;
775         $this->assertTrue($capabilitymanager->can_delete_post($user, $discussion, $post));
776     }
778     /**
779      * Test can_split_post.
780      *
781      * @covers ::can_split_post
782      */
783     public function test_can_split_post() {
784         $this->resetAfterTest();
786         $forum = $this->create_forum();
787         $user = $this->user;
788         $discussion = $this->discussion;
789         $post = $this->post;
790         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
792         // Make the post a reply.
793         $post = $this->entityfactory->get_post_from_stdclass(
794             (object) array_merge((array) $this->postrecord, ['parent' => 5])
795         );
797         $this->prevent_capability('mod/forum:splitdiscussions');
798         $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
800         $this->give_capability('mod/forum:splitdiscussions');
801         $this->assertTrue($capabilitymanager->can_split_post($user, $discussion, $post));
803         // Make the post have no parent.
804         $post = $this->entityfactory->get_post_from_stdclass(
805             (object) array_merge((array) $this->postrecord, ['parent' => 0])
806         );
808         $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
810         $forum = $this->create_forum(['type' => 'single']);
811         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
812         // Make the post a reply.
813         $post = $this->entityfactory->get_post_from_stdclass(
814             (object) array_merge((array) $this->postrecord, ['parent' => 5])
815         );
817         // Can't split a single discussion forum.
818         $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
820         // Make the post a private reply.
821         $post = $this->entityfactory->get_post_from_stdclass(
822             (object) array_merge((array) $this->postrecord, ['parent' => 5, 'privatereplyto' => $user->id])
823         );
825         // Can't split at a private reply.
826         $this->assertFalse($capabilitymanager->can_split_post($user, $discussion, $post));
827     }
829     /**
830      * Test can_reply_to_post.
831      *
832      * @covers ::can_reply_to_post
833      */
834     public function test_can_reply_to_post() {
835         $this->resetAfterTest();
837         $discussion = $this->discussion;
838         $user = $this->user;
839         $post = $this->post;
841         // Locked discussions.
842         $lockedforum = $this->create_forum(['lockdiscussionafter' => 1]);
843         $capabilitymanager = $this->managerfactory->get_capability_manager($lockedforum);
845         $this->give_capability('mod/forum:canoverridediscussionlock');
846         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
848         $this->prevent_capability('mod/forum:canoverridediscussionlock');
849         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
851         // News forum.
852         $newsforum = $this->create_forum(['type' => 'news']);
853         $capabilitymanager = $this->managerfactory->get_capability_manager($newsforum);
855         $this->give_capability('mod/forum:replynews');
856         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
858         $this->prevent_capability('mod/forum:replynews');
859         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
861         // General forum.
862         $forum = $this->create_forum();
863         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
865         $this->give_capability('mod/forum:replypost');
866         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
868         $this->prevent_capability('mod/forum:replypost');
869         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
871         // Forum in separate group mode.
872         $forumrecord = $this->getDataGenerator()->create_module(
873             'forum',
874             ['course' => $this->course->id, 'groupmode' => SEPARATEGROUPS]
875         );
876         $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
877         $context = context_module::instance($coursemodule->id);
878         $forum = $this->entityfactory->get_forum_from_stdclass(
879             $forumrecord,
880             $context,
881             $coursemodule,
882             $this->course
883         );
884         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
886         $this->give_capability('moodle/site:accessallgroups', $context);
887         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
889         $this->prevent_capability('moodle/site:accessallgroups', $context);
890         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
892         $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
893         $discussion = $this->entityfactory->get_discussion_from_stdclass(
894             (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
895         );
897         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
899         $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
901         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
903         // Forum in visible group mode.
904         $forumrecord = $this->getDataGenerator()->create_module(
905             'forum',
906             ['course' => $this->course->id, 'groupmode' => VISIBLEGROUPS]
907         );
908         $coursemodule = get_coursemodule_from_instance('forum', $forumrecord->id);
909         $context = context_module::instance($coursemodule->id);
910         $forum = $this->entityfactory->get_forum_from_stdclass(
911             $forumrecord,
912             $context,
913             $coursemodule,
914             $this->course
915         );
916         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
918         $this->give_capability('moodle/site:accessallgroups', $context);
919         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
921         $this->prevent_capability('moodle/site:accessallgroups', $context);
922         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
924         $group = $this->getDataGenerator()->create_group(['courseid' => $this->course->id]);
925         $discussion = $this->entityfactory->get_discussion_from_stdclass(
926             (object) array_merge((array) $this->discussionrecord, ['groupid' => $group->id])
927         );
929         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
931         $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]);
933         $this->assertTrue($capabilitymanager->can_reply_to_post($user, $discussion, $post));
935         // Make the post a private reply.
936         $post = $this->entityfactory->get_post_from_stdclass(
937             (object) array_merge((array) $this->postrecord, ['parent' => 5, 'privatereplyto' => $user->id])
938         );
940         // Can't reply to a a private reply.
941         $this->assertFalse($capabilitymanager->can_reply_to_post($user, $discussion, $post));
942     }
944     /**
945      * Ensure that can_reply_privately_to_post works as expected.
946      *
947      * @covers ::can_reply_privately_to_post
948      */
949     public function test_can_reply_privately_to_post() {
950         $this->resetAfterTest();
952         $forum = $this->create_forum();
953         $discussion = $this->discussion;
954         $user = $this->user;
955         $post = $this->post;
956         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
958         // Without the capability, and with a standard post, it is not possible to reply privately.
959         $this->prevent_capability('mod/forum:postprivatereply');
960         $this->assertFalse($capabilitymanager->can_reply_privately_to_post($this->user, $post));
962         // With the capability, and a standard post, it is possible to reply privately.
963         $this->give_capability('mod/forum:postprivatereply');
964         $this->assertTrue($capabilitymanager->can_reply_privately_to_post($this->user, $post));
966         // Make the post a private reply.
967         $post = $this->entityfactory->get_post_from_stdclass(
968             (object) array_merge((array) $this->postrecord, ['parent' => 5, 'privatereplyto' => $user->id])
969         );
971         // Can't ever reply to a a private reply.
972         $this->assertFalse($capabilitymanager->can_reply_privately_to_post($user, $post));
973     }
975     /**
976      * Ensure that can_view_post works as expected.
977      *
978      * @covers ::can_view_post
979      */
980     public function test_can_view_post() {
981         $this->resetAfterTest();
983         $forum = $this->create_forum();
984         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
986         $user = $this->user;
987         $otheruser = $this->getDataGenerator()->create_user();
989         $discussion = $this->discussion;
990         $post = $this->post;
992         $privatepost = $this->entityfactory->get_post_from_stdclass(
993             (object) array_merge((array) $this->postrecord, ['parent' => $post->get_id(), 'privatereplyto' => $otheruser->id])
994         );
996         $this->prevent_capability('mod/forum:readprivatereplies');
997         $this->assertFalse($capabilitymanager->can_view_post($user, $discussion, $privatepost));
998     }
1000     /**
1001      * Ensure that can_view_post_shell considers private replies correctly.
1002      *
1003      * @covers ::can_view_post_shell
1004      */
1005     public function test_can_view_post_shell() {
1006         $this->resetAfterTest();
1008         $forum = $this->create_forum();
1009         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1011         $user = $this->user;
1012         $otheruser = $this->getDataGenerator()->create_user();
1014         $discussion = $this->discussion;
1015         $post = $this->post;
1016         $privatepost = $this->entityfactory->get_post_from_stdclass(
1017             (object) array_merge((array) $this->postrecord, ['parent' => $post->get_id(), 'privatereplyto' => $otheruser->id])
1018         );
1019         $privateposttome = $this->entityfactory->get_post_from_stdclass(
1020             (object) array_merge((array) $this->postrecord, ['parent' => $post->get_id(), 'privatereplyto' => $user->id])
1021         );
1023         // Can always view public replies, and those to me.
1024         $this->prevent_capability('mod/forum:readprivatereplies');
1025         $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $post));
1026         $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privateposttome));
1027         $this->assertFalse($capabilitymanager->can_view_post_shell($this->user, $privatepost));
1029         $this->give_capability('mod/forum:readprivatereplies');
1030         $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $post));
1031         $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privateposttome));
1032         $this->assertTrue($capabilitymanager->can_view_post_shell($this->user, $privatepost));
1033     }
1035     /**
1036      * Test can_export_post.
1037      *
1038      * @covers ::can_export_post
1039      */
1040     public function test_can_export_post() {
1041         global $CFG;
1042         $this->resetAfterTest();
1044         $forum = $this->create_forum();
1045         $post = $this->post;
1046         $user = $this->user;
1047         $otheruser = $this->getDataGenerator()->create_user();
1048         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1050         $this->getDataGenerator()->enrol_user($otheruser->id, $this->course->id, 'teacher');
1052         $CFG->enableportfolios = true;
1053         $this->give_capability('mod/forum:exportpost');
1055         $this->assertTrue($capabilitymanager->can_export_post($otheruser, $post));
1057         $CFG->enableportfolios = false;
1058         $this->assertFalse($capabilitymanager->can_export_post($otheruser, $post));
1060         $CFG->enableportfolios = true;
1061         $this->prevent_capability('mod/forum:exportpost');
1062         // Can't export another user's post without the exportpost capavility.
1063         $this->assertFalse($capabilitymanager->can_export_post($otheruser, $post));
1065         $this->give_capability('mod/forum:exportownpost');
1066         // Can export own post with the exportownpost capability.
1067         $this->assertTrue($capabilitymanager->can_export_post($user, $post));
1069         $this->prevent_capability('mod/forum:exportownpost');
1070         $this->assertFalse($capabilitymanager->can_export_post($user, $post));
1071     }
1073     /**
1074      * Test can_view_participants.
1075      *
1076      * @covers ::can_view_participants
1077      */
1078     public function test_can_view_participants() {
1079         $this->resetAfterTest();
1081         $discussion = $this->discussion;
1082         $user = $this->user;
1083         $otheruser = $this->getDataGenerator()->create_user();
1085         $this->getDataGenerator()->enrol_user($otheruser->id, $this->course->id, 'teacher');
1087         $this->prevent_capability('moodle/course:viewparticipants');
1088         $this->prevent_capability('moodle/course:enrolreview');
1089         $this->prevent_capability('mod/forum:viewqandawithoutposting');
1091         $forum = $this->create_forum();
1092         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1094         $this->assertFalse($capabilitymanager->can_view_participants($otheruser, $discussion));
1096         $this->give_capability('moodle/course:viewparticipants');
1097         $this->assertTrue($capabilitymanager->can_view_participants($otheruser, $discussion));
1099         $this->prevent_capability('moodle/course:viewparticipants');
1100         $this->give_capability('moodle/course:enrolreview');
1101         $this->assertTrue($capabilitymanager->can_view_participants($otheruser, $discussion));
1103         $forum = $this->create_forum(['type' => 'qanda']);
1104         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1106         // Q and A forum requires the user to post before they can view it.
1107         $this->prevent_capability('mod/forum:viewqandawithoutposting');
1108         $this->assertFalse($capabilitymanager->can_view_participants($otheruser, $discussion));
1110         // This user has posted.
1111         $this->assertTrue($capabilitymanager->can_view_participants($user, $discussion));
1112     }
1114     /**
1115      * Test can_view_hidden_posts.
1116      *
1117      * @covers ::can_view_hidden_posts
1118      */
1119     public function test_can_view_hidden_posts() {
1120         $this->resetAfterTest();
1122         $forum = $this->create_forum();
1123         $user = $this->user;
1124         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1126         $this->prevent_capability('mod/forum:viewhiddentimedposts');
1127         $this->assertFalse($capabilitymanager->can_view_hidden_posts($user));
1129         $this->give_capability('mod/forum:viewhiddentimedposts');
1130         $this->assertTrue($capabilitymanager->can_view_hidden_posts($user));
1131     }
1133     /**
1134      * Test can_manage_forum.
1135      *
1136      * @covers ::can_manage_forum
1137      */
1138     public function test_can_manage_forum() {
1139         $this->resetAfterTest();
1141         $forum = $this->create_forum();
1142         $user = $this->user;
1143         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1145         $this->prevent_capability('moodle/course:manageactivities');
1146         $this->assertFalse($capabilitymanager->can_manage_forum($user));
1148         $this->give_capability('moodle/course:manageactivities');
1149         $this->assertTrue($capabilitymanager->can_manage_forum($user));
1150     }
1152     /**
1153      * Test can_manage_tags.
1154      *
1155      * @covers ::can_manage_tags
1156      */
1157     public function test_can_manage_tags() {
1158         global $DB;
1159         $this->resetAfterTest();
1161         $forum = $this->create_forum();
1162         $user = $this->user;
1163         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1164         $context = context_system::instance();
1165         $roleid = $DB->get_field('role', 'id', ['shortname' => 'user'], MUST_EXIST);
1167         assign_capability('moodle/tag:manage', CAP_PREVENT, $roleid, $context->id, true);
1168         $this->assertFalse($capabilitymanager->can_manage_tags($user));
1170         assign_capability('moodle/tag:manage', CAP_ALLOW, $roleid, $context->id, true);
1171         $this->assertTrue($capabilitymanager->can_manage_tags($user));
1172     }
1174     /**
1175      * Ensure that the can_view_any_private_reply works as expected.
1176      *
1177      * @covers ::can_view_any_private_reply
1178      */
1179     public function test_can_view_any_private_reply() {
1180         $this->resetAfterTest();
1182         $forum = $this->create_forum();
1183         $capabilitymanager = $this->managerfactory->get_capability_manager($forum);
1185         $this->give_capability('mod/forum:readprivatereplies');
1186         $this->assertTrue($capabilitymanager->can_view_any_private_reply($this->user));
1187         $this->prevent_capability('mod/forum:readprivatereplies');
1188         $this->assertFalse($capabilitymanager->can_view_any_private_reply($this->user));
1189     }
1192     /**
1193      * Test delete a post with ratings.
1194      */
1195     public function test_validate_delete_post_with_ratings() {
1196         global $DB;
1197         $this->resetAfterTest(true);
1199         // Setup test data.
1200         $course = $this->getDataGenerator()->create_course();
1201         $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
1202         $user = $this->getDataGenerator()->create_user();
1203         $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1204         self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
1206         // Add a discussion.
1207         $record = new stdClass();
1208         $record->course = $course->id;
1209         $record->userid = $user->id;
1210         $record->forum = $forum->id;
1211         $record->created =
1212         $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
1214         // Add rating.
1215         $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
1216         $post->totalscore = 80;
1217         $DB->update_record('forum_posts', $post);
1219         $vaultfactory = mod_forum\local\container::get_vault_factory();
1220         $forumvault = $vaultfactory->get_forum_vault();
1221         $discussionvault = $vaultfactory->get_discussion_vault();
1222         $postvault = $vaultfactory->get_post_vault();
1224         $postentity = $postvault->get_from_id($post->id);
1225         $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id());
1226         $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id());
1227         $capabilitymanager = $this->managerfactory->get_capability_manager($forumentity);
1229         $this->setUser($user);
1230         $this->expectExceptionMessage(get_string('couldnotdeleteratings', 'rating'));
1231         $capabilitymanager->validate_delete_post($user, $discussionentity, $postentity, false);
1232     }
1234     /**
1235      * Test delete a post with replies.
1236      */
1237     public function test_validate_delete_post_with_replies() {
1238         global $DB;
1239         $this->resetAfterTest(true);
1241         // Setup test data.
1242         $course = $this->getDataGenerator()->create_course();
1243         $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
1244         $user = $this->getDataGenerator()->create_user();
1245         $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1246         self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
1248         // Add a discussion.
1249         $record = new stdClass();
1250         $record->course = $course->id;
1251         $record->userid = $user->id;
1252         $record->forum = $forum->id;
1253         $record->created =
1254         $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
1256         $parentpost = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
1257         // Add a post.
1258         $record = new stdClass();
1259         $record->course = $course->id;
1260         $record->userid = $user->id;
1261         $record->forum = $forum->id;
1262         $record->discussion = $discussion->id;
1263         $record->parent = $parentpost->id;
1264         $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
1266         $vaultfactory = mod_forum\local\container::get_vault_factory();
1267         $forumvault = $vaultfactory->get_forum_vault();
1268         $discussionvault = $vaultfactory->get_discussion_vault();
1269         $postvault = $vaultfactory->get_post_vault();
1271         $postentity = $postvault->get_from_id($parentpost->id);
1272         $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id());
1273         $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id());
1274         $capabilitymanager = $this->managerfactory->get_capability_manager($forumentity);
1276         $this->setUser($user);
1277         // Get reply count.
1278         $replycount = $postvault->get_reply_count_for_post_id_in_discussion_id(
1279             $user, $postentity->get_id(), $discussionentity->get_id(), true);
1280         $this->expectExceptionMessage(get_string('couldnotdeletereplies', 'forum'));
1281         $capabilitymanager->validate_delete_post($user, $discussionentity, $postentity, $replycount);
1282     }