Commit | Line | Data |
---|---|---|
47d38303 RW |
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 | /** | |
18 | * Capability manager for the forum. | |
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 | */ | |
24 | ||
25 | namespace mod_forum\local\managers; | |
26 | ||
27 | defined('MOODLE_INTERNAL') || die(); | |
28 | ||
29 | use mod_forum\local\data_mappers\legacy\forum as legacy_forum_data_mapper; | |
30 | use mod_forum\local\data_mappers\legacy\discussion as legacy_discussion_data_mapper; | |
31 | use mod_forum\local\data_mappers\legacy\post as legacy_post_data_mapper; | |
32 | use mod_forum\local\entities\discussion as discussion_entity; | |
33 | use mod_forum\local\entities\forum as forum_entity; | |
34 | use mod_forum\local\entities\post as post_entity; | |
35 | use mod_forum\subscriptions; | |
36 | use context; | |
37 | use context_system; | |
38 | use stdClass; | |
b12dbcd4 | 39 | use moodle_exception; |
47d38303 RW |
40 | |
41 | require_once($CFG->dirroot . '/mod/forum/lib.php'); | |
42 | ||
43 | /** | |
44 | * Capability manager for the forum. | |
45 | * | |
46 | * Defines all the business rules for what a user can and can't do in the forum. | |
47 | * | |
48 | * @copyright 2019 Ryan Wyllie <ryan@moodle.com> | |
49 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
50 | */ | |
51 | class capability { | |
52 | /** @var legacy_forum_data_mapper $forumdatamapper Legacy forum data mapper */ | |
53 | private $forumdatamapper; | |
54 | /** @var legacy_discussion_data_mapper $discussiondatamapper Legacy discussion data mapper */ | |
55 | private $discussiondatamapper; | |
56 | /** @var legacy_post_data_mapper $postdatamapper Legacy post data mapper */ | |
57 | private $postdatamapper; | |
58 | /** @var forum_entity $forum Forum entity */ | |
59 | private $forum; | |
60 | /** @var stdClass $forumrecord Legacy forum record */ | |
61 | private $forumrecord; | |
62 | /** @var context $context Module context for the forum */ | |
63 | private $context; | |
64 | ||
65 | /** | |
66 | * Constructor. | |
67 | * | |
68 | * @param forum_entity $forum The forum entity to manage capabilities for. | |
69 | * @param legacy_forum_data_mapper $forumdatamapper Legacy forum data mapper | |
70 | * @param legacy_discussion_data_mapper $discussiondatamapper Legacy discussion data mapper | |
71 | * @param legacy_post_data_mapper $postdatamapper Legacy post data mapper | |
72 | */ | |
73 | public function __construct( | |
74 | forum_entity $forum, | |
75 | legacy_forum_data_mapper $forumdatamapper, | |
76 | legacy_discussion_data_mapper $discussiondatamapper, | |
77 | legacy_post_data_mapper $postdatamapper | |
78 | ) { | |
79 | $this->forumdatamapper = $forumdatamapper; | |
80 | $this->discussiondatamapper = $discussiondatamapper; | |
81 | $this->postdatamapper = $postdatamapper; | |
82 | $this->forum = $forum; | |
83 | $this->forumrecord = $forumdatamapper->to_legacy_object($forum); | |
84 | $this->context = $forum->get_context(); | |
85 | } | |
86 | ||
87 | /** | |
88 | * Can the user subscribe to this forum? | |
89 | * | |
90 | * @param stdClass $user The user to check | |
91 | * @return bool | |
92 | */ | |
93 | public function can_subscribe_to_forum(stdClass $user) : bool { | |
54d38a73 | 94 | if ($this->forum->get_type() == 'single') { |
446ba046 | 95 | return false; |
54d38a73 MG |
96 | } |
97 | ||
47d38303 RW |
98 | return !is_guest($this->get_context(), $user) && |
99 | subscriptions::is_subscribable($this->get_forum_record()); | |
100 | } | |
101 | ||
102 | /** | |
103 | * Can the user create discussions in this forum? | |
104 | * | |
105 | * @param stdClass $user The user to check | |
106 | * @param int|null $groupid The current activity group id | |
107 | * @return bool | |
108 | */ | |
109 | public function can_create_discussions(stdClass $user, int $groupid = null) : bool { | |
110 | if (isguestuser($user) or !isloggedin()) { | |
111 | return false; | |
112 | } | |
113 | ||
cbf63d8e SR |
114 | if ($this->forum->is_cutoff_date_reached()) { |
115 | if (!has_capability('mod/forum:canoverridecutoff', $this->get_context())) { | |
116 | return false; | |
117 | } | |
118 | } | |
119 | ||
47d38303 RW |
120 | switch ($this->forum->get_type()) { |
121 | case 'news': | |
122 | $capability = 'mod/forum:addnews'; | |
123 | break; | |
124 | case 'qanda': | |
125 | $capability = 'mod/forum:addquestion'; | |
126 | break; | |
127 | default: | |
128 | $capability = 'mod/forum:startdiscussion'; | |
129 | } | |
130 | ||
131 | if (!has_capability($capability, $this->forum->get_context(), $user)) { | |
132 | return false; | |
133 | } | |
134 | ||
54d38a73 MG |
135 | if ($this->forum->get_type() == 'eachuser') { |
136 | if (forum_user_has_posted_discussion($this->forum->get_id(), $user->id, $groupid)) { | |
137 | return false; | |
138 | } | |
139 | } | |
140 | ||
47d38303 RW |
141 | if ($this->forum->is_in_group_mode()) { |
142 | return $groupid ? $this->can_access_group($user, $groupid) : $this->can_access_all_groups($user); | |
143 | } else { | |
144 | return true; | |
145 | } | |
146 | } | |
147 | ||
148 | /** | |
149 | * Can the user access all groups? | |
150 | * | |
151 | * @param stdClass $user The user to check | |
152 | * @return bool | |
153 | */ | |
15f7dbe5 | 154 | public function can_access_all_groups(stdClass $user) : bool { |
47d38303 RW |
155 | return has_capability('moodle/site:accessallgroups', $this->get_context(), $user); |
156 | } | |
157 | ||
158 | /** | |
159 | * Can the user access the given group? | |
160 | * | |
161 | * @param stdClass $user The user to check | |
162 | * @param int $groupid The id of the group that the forum is set to | |
163 | * @return bool | |
164 | */ | |
15f7dbe5 | 165 | public function can_access_group(stdClass $user, int $groupid) : bool { |
47d38303 RW |
166 | if ($this->can_access_all_groups($user)) { |
167 | // This user has access to all groups. | |
168 | return true; | |
169 | } | |
170 | ||
171 | // This is a group discussion for a forum in separate groups mode. | |
172 | // Check if the user is a member. | |
173 | // This is the most expensive check. | |
174 | return groups_is_member($groupid, $user->id); | |
175 | } | |
176 | ||
15f7dbe5 RW |
177 | /** |
178 | * Can the user post to their groups? | |
179 | * | |
180 | * @param stdClass $user The user to check | |
181 | * @return bool | |
182 | */ | |
183 | public function can_post_to_my_groups(stdClass $user) : bool { | |
184 | return has_capability('mod/forum:canposttomygroups', $this->get_context(), $user); | |
185 | } | |
186 | ||
47d38303 RW |
187 | /** |
188 | * Can the user view discussions in this forum? | |
189 | * | |
190 | * @param stdClass $user The user to check | |
191 | * @return bool | |
192 | */ | |
193 | public function can_view_discussions(stdClass $user) : bool { | |
194 | return has_capability('mod/forum:viewdiscussion', $this->get_context(), $user); | |
195 | } | |
196 | ||
197 | /** | |
198 | * Can the user move discussions in this forum? | |
199 | * | |
200 | * @param stdClass $user The user to check | |
201 | * @return bool | |
202 | */ | |
203 | public function can_move_discussions(stdClass $user) : bool { | |
204 | $forum = $this->get_forum(); | |
54d38a73 MG |
205 | return $forum->get_type() !== 'single' && |
206 | has_capability('mod/forum:movediscussions', $this->get_context(), $user); | |
47d38303 RW |
207 | } |
208 | ||
209 | /** | |
210 | * Can the user pin discussions in this forum? | |
211 | * | |
212 | * @param stdClass $user The user to check | |
213 | * @return bool | |
214 | */ | |
215 | public function can_pin_discussions(stdClass $user) : bool { | |
54d38a73 MG |
216 | return $this->forum->get_type() !== 'single' && |
217 | has_capability('mod/forum:pindiscussions', $this->get_context(), $user); | |
47d38303 RW |
218 | } |
219 | ||
220 | /** | |
221 | * Can the user split discussions in this forum? | |
222 | * | |
223 | * @param stdClass $user The user to check | |
224 | * @return bool | |
225 | */ | |
226 | public function can_split_discussions(stdClass $user) : bool { | |
227 | $forum = $this->get_forum(); | |
228 | return $forum->get_type() !== 'single' && has_capability('mod/forum:splitdiscussions', $this->get_context(), $user); | |
229 | } | |
230 | ||
231 | /** | |
232 | * Can the user export (see portfolios) discussions in this forum? | |
233 | * | |
234 | * @param stdClass $user The user to check | |
235 | * @return bool | |
236 | */ | |
237 | public function can_export_discussions(stdClass $user) : bool { | |
238 | global $CFG; | |
239 | return $CFG->enableportfolios && has_capability('mod/forum:exportdiscussion', $this->get_context(), $user); | |
240 | } | |
241 | ||
242 | /** | |
243 | * Can the user manually mark posts as read/unread in this forum? | |
244 | * | |
245 | * @param stdClass $user The user to check | |
246 | * @return bool | |
247 | */ | |
248 | public function can_manually_control_post_read_status(stdClass $user) : bool { | |
249 | global $CFG; | |
250 | return $CFG->forum_usermarksread && isloggedin() && forum_tp_is_tracked($this->get_forum_record(), $user); | |
251 | } | |
252 | ||
253 | /** | |
254 | * Is the user required to post in the discussion before they can view it? | |
255 | * | |
256 | * @param stdClass $user The user to check | |
257 | * @param discussion_entity $discussion The discussion to check | |
258 | * @return bool | |
259 | */ | |
260 | public function must_post_before_viewing_discussion(stdClass $user, discussion_entity $discussion) : bool { | |
261 | $forum = $this->get_forum(); | |
262 | ||
263 | if ($forum->get_type() === 'qanda') { | |
264 | // If it's a Q and A forum then the user must either have the capability to view without | |
265 | // posting or the user must have posted before they can view the discussion. | |
266 | return !has_capability('mod/forum:viewqandawithoutposting', $this->get_context(), $user) && | |
267 | !forum_user_has_posted($forum->get_id(), $discussion->get_id(), $user->id); | |
268 | } else { | |
269 | // No other forum types require posting before viewing. | |
270 | return false; | |
271 | } | |
272 | } | |
273 | ||
274 | /** | |
275 | * Can the user subscribe to the give discussion? | |
276 | * | |
277 | * @param stdClass $user The user to check | |
278 | * @param discussion_entity $discussion The discussion to check | |
279 | * @return bool | |
280 | */ | |
281 | public function can_subscribe_to_discussion(stdClass $user, discussion_entity $discussion) : bool { | |
282 | return $this->can_subscribe_to_forum($user); | |
283 | } | |
284 | ||
285 | /** | |
286 | * Can the user move the discussion in this forum? | |
287 | * | |
288 | * @param stdClass $user The user to check | |
289 | * @param discussion_entity $discussion The discussion to check | |
290 | * @return bool | |
291 | */ | |
292 | public function can_move_discussion(stdClass $user, discussion_entity $discussion) : bool { | |
293 | return $this->can_move_discussions($user); | |
294 | } | |
295 | ||
296 | /** | |
297 | * Is the user pin the discussion? | |
298 | * | |
299 | * @param stdClass $user The user to check | |
300 | * @param discussion_entity $discussion The discussion to check | |
301 | * @return bool | |
302 | */ | |
303 | public function can_pin_discussion(stdClass $user, discussion_entity $discussion) : bool { | |
304 | return $this->can_pin_discussions($user); | |
305 | } | |
306 | ||
307 | /** | |
308 | * Can the user post in this discussion? | |
309 | * | |
310 | * @param stdClass $user The user to check | |
311 | * @param discussion_entity $discussion The discussion to check | |
312 | * @return bool | |
313 | */ | |
314 | public function can_post_in_discussion(stdClass $user, discussion_entity $discussion) : bool { | |
315 | $forum = $this->get_forum(); | |
316 | $forumrecord = $this->get_forum_record(); | |
317 | $discussionrecord = $this->get_discussion_record($discussion); | |
318 | $context = $this->get_context(); | |
319 | $coursemodule = $forum->get_course_module_record(); | |
320 | $course = $forum->get_course_record(); | |
321 | ||
322 | return forum_user_can_post($forumrecord, $discussionrecord, $user, $coursemodule, $course, $context); | |
323 | } | |
324 | ||
99bda8a7 P |
325 | /** |
326 | * Can the user favourite the discussion | |
327 | * | |
328 | * @param stdClass $user The user to check | |
99bda8a7 P |
329 | * @return bool |
330 | */ | |
b4a1bbbb | 331 | public function can_favourite_discussion(stdClass $user) : bool { |
99bda8a7 | 332 | $context = $this->get_context(); |
24962ee1 | 333 | return has_capability('mod/forum:cantogglefavourite', $context, $user); |
99bda8a7 P |
334 | } |
335 | ||
1a9c60e9 MG |
336 | /** |
337 | * Can the user view the content of a discussion? | |
338 | * | |
339 | * @param stdClass $user The user to check | |
340 | * @param discussion_entity $discussion The discussion to check | |
341 | * @return bool | |
342 | */ | |
343 | public function can_view_discussion(stdClass $user, discussion_entity $discussion) : bool { | |
344 | $forumrecord = $this->get_forum_record(); | |
345 | $discussionrecord = $this->get_discussion_record($discussion); | |
346 | $context = $this->get_context(); | |
347 | ||
348 | return forum_user_can_see_discussion($forumrecord, $discussionrecord, $context, $user); | |
349 | } | |
350 | ||
47d38303 | 351 | /** |
bc4c7337 | 352 | * Can the user view the content of the post in this discussion? |
47d38303 RW |
353 | * |
354 | * @param stdClass $user The user to check | |
355 | * @param discussion_entity $discussion The discussion to check | |
356 | * @param post_entity $post The post the user wants to view | |
357 | * @return bool | |
358 | */ | |
359 | public function can_view_post(stdClass $user, discussion_entity $discussion, post_entity $post) : bool { | |
bc4c7337 AN |
360 | if (!$this->can_view_post_shell($user, $post)) { |
361 | return false; | |
362 | } | |
363 | ||
47d38303 RW |
364 | $forum = $this->get_forum(); |
365 | $forumrecord = $this->get_forum_record(); | |
366 | $discussionrecord = $this->get_discussion_record($discussion); | |
367 | $postrecord = $this->get_post_record($post); | |
368 | $coursemodule = $forum->get_course_module_record(); | |
369 | return forum_user_can_see_post($forumrecord, $discussionrecord, $postrecord, $user, $coursemodule, false); | |
370 | } | |
371 | ||
bc4c7337 AN |
372 | /** |
373 | * Can the user view the post at all? | |
374 | * In some situations the user can view the shell of a post without being able to view its content. | |
375 | * | |
376 | * @param stdClass $user The user to check | |
377 | * @param post_entity $post The post the user wants to view | |
378 | * @return bool | |
379 | * | |
380 | */ | |
381 | public function can_view_post_shell(stdClass $user, post_entity $post) : bool { | |
15dc885a | 382 | if (!$post->is_private_reply()) { |
bc4c7337 AN |
383 | return true; |
384 | } | |
385 | ||
386 | if ($post->is_private_reply_intended_for_user($user)) { | |
387 | return true; | |
388 | } | |
389 | ||
390 | return $this->can_view_any_private_reply($user); | |
391 | } | |
392 | ||
393 | /** | |
394 | * Whether the user can view any private reply in the forum. | |
395 | * | |
396 | * @param stdClass $user The user to check | |
397 | * @return bool | |
398 | */ | |
399 | public function can_view_any_private_reply(stdClass $user) : bool { | |
400 | return has_capability('mod/forum:readprivatereplies', $this->get_context(), $user); | |
401 | } | |
402 | ||
47d38303 RW |
403 | /** |
404 | * Can the user edit the post in this discussion? | |
405 | * | |
406 | * @param stdClass $user The user to check | |
407 | * @param discussion_entity $discussion The discussion to check | |
408 | * @param post_entity $post The post the user wants to edit | |
409 | * @return bool | |
410 | */ | |
411 | public function can_edit_post(stdClass $user, discussion_entity $discussion, post_entity $post) : bool { | |
412 | global $CFG; | |
413 | ||
414 | $context = $this->get_context(); | |
415 | $ownpost = $post->is_owned_by_user($user); | |
416 | $ineditingtime = $post->get_age() < $CFG->maxeditingtime; | |
417 | ||
418 | switch ($this->forum->get_type()) { | |
419 | case 'news': | |
420 | // Allow editing of news posts once the discussion has started. | |
421 | $ineditingtime = !$post->has_parent() && $discussion->has_started(); | |
422 | break; | |
423 | case 'single': | |
50b52ef4 AN |
424 | if ($discussion->is_first_post($post)) { |
425 | return has_capability('moodle/course:manageactivities', $context, $user); | |
426 | } | |
427 | break; | |
47d38303 RW |
428 | } |
429 | ||
430 | return ($ownpost && $ineditingtime) || has_capability('mod/forum:editanypost', $context, $user); | |
431 | } | |
432 | ||
433 | /** | |
b12dbcd4 | 434 | * Verifies is the given user can delete a post. |
47d38303 RW |
435 | * |
436 | * @param stdClass $user The user to check | |
437 | * @param discussion_entity $discussion The discussion to check | |
438 | * @param post_entity $post The post the user wants to delete | |
b12dbcd4 | 439 | * @param bool $hasreplies Whether the post has replies |
47d38303 | 440 | * @return bool |
b12dbcd4 | 441 | * @throws moodle_exception |
47d38303 | 442 | */ |
b12dbcd4 JL |
443 | public function validate_delete_post(stdClass $user, discussion_entity $discussion, post_entity $post, |
444 | bool $hasreplies = false) : void { | |
47d38303 RW |
445 | global $CFG; |
446 | ||
447 | $forum = $this->get_forum(); | |
448 | ||
449 | if ($forum->get_type() == 'single' && $discussion->is_first_post($post)) { | |
450 | // Do not allow deleting of first post in single simple type. | |
b12dbcd4 JL |
451 | throw new moodle_exception('cannotdeletepost', 'forum'); |
452 | } | |
453 | ||
454 | $context = $this->get_context(); | |
455 | $ownpost = $post->is_owned_by_user($user); | |
456 | $ineditingtime = $post->get_age() < $CFG->maxeditingtime; | |
457 | ||
458 | if (!($ownpost && $ineditingtime && has_capability('mod/forum:deleteownpost', $context, $user) || | |
459 | has_capability('mod/forum:deleteanypost', $context, $user))) { | |
460 | ||
461 | throw new moodle_exception('cannotdeletepost', 'forum'); | |
462 | } | |
463 | ||
464 | if ($post->get_total_score()) { | |
465 | throw new moodle_exception('couldnotdeleteratings', 'rating'); | |
466 | } | |
467 | ||
468 | if ($hasreplies && !has_capability('mod/forum:deleteanypost', $context, $user)) { | |
469 | throw new moodle_exception('couldnotdeletereplies', 'forum'); | |
470 | } | |
471 | } | |
472 | ||
473 | ||
474 | /** | |
475 | * Can the user delete the post in this discussion? | |
476 | * | |
477 | * @param stdClass $user The user to check | |
478 | * @param discussion_entity $discussion The discussion to check | |
479 | * @param post_entity $post The post the user wants to delete | |
480 | * @param bool $hasreplies Whether the post has replies | |
481 | * @return bool | |
482 | */ | |
483 | public function can_delete_post(stdClass $user, discussion_entity $discussion, post_entity $post, | |
484 | bool $hasreplies = false) : bool { | |
47d38303 | 485 | |
b12dbcd4 JL |
486 | try { |
487 | $this->validate_delete_post($user, $discussion, $post, $hasreplies); | |
488 | return true; | |
489 | } catch (moodle_exception $e) { | |
490 | return false; | |
47d38303 RW |
491 | } |
492 | } | |
493 | ||
494 | /** | |
495 | * Can the user split the post in this discussion? | |
496 | * | |
497 | * @param stdClass $user The user to check | |
498 | * @param discussion_entity $discussion The discussion to check | |
499 | * @param post_entity $post The post the user wants to split | |
500 | * @return bool | |
501 | */ | |
502 | public function can_split_post(stdClass $user, discussion_entity $discussion, post_entity $post) : bool { | |
bc4c7337 AN |
503 | if ($post->is_private_reply()) { |
504 | // It is not possible to create a private discussion. | |
505 | return false; | |
506 | } | |
507 | ||
47d38303 RW |
508 | return $this->can_split_discussions($user) && $post->has_parent(); |
509 | } | |
510 | ||
511 | /** | |
512 | * Can the user reply to the post in this discussion? | |
513 | * | |
514 | * @param stdClass $user The user to check | |
515 | * @param discussion_entity $discussion The discussion to check | |
516 | * @param post_entity $post The post the user wants to reply to | |
517 | * @return bool | |
518 | */ | |
519 | public function can_reply_to_post(stdClass $user, discussion_entity $discussion, post_entity $post) : bool { | |
bc4c7337 AN |
520 | if ($post->is_private_reply()) { |
521 | // It is not possible to reply to a private reply. | |
522 | return false; | |
523 | } | |
524 | ||
47d38303 RW |
525 | return $this->can_post_in_discussion($user, $discussion); |
526 | } | |
527 | ||
bc4c7337 AN |
528 | /** |
529 | * Can the user reply privately to the specified post? | |
530 | * | |
531 | * @param stdClass $user The user to check | |
532 | * @param post_entity $post The post the user wants to reply to | |
533 | * @return bool | |
534 | */ | |
535 | public function can_reply_privately_to_post(stdClass $user, post_entity $post) : bool { | |
536 | if ($post->is_private_reply()) { | |
537 | // You cannot reply privately to a post which is, itself, a private reply. | |
538 | return false; | |
539 | } | |
540 | ||
541 | return has_capability('mod/forum:postprivatereply', $this->get_context(), $user); | |
542 | } | |
543 | ||
47d38303 RW |
544 | /** |
545 | * Can the user export (see portfolios) the post in this discussion? | |
546 | * | |
547 | * @param stdClass $user The user to check | |
548 | * @param post_entity $post The post the user wants to export | |
549 | * @return bool | |
550 | */ | |
551 | public function can_export_post(stdClass $user, post_entity $post) : bool { | |
552 | global $CFG; | |
553 | $context = $this->get_context(); | |
554 | return $CFG->enableportfolios && (has_capability('mod/forum:exportpost', $context, $user) || | |
555 | ($post->is_owned_by_user($user) && has_capability('mod/forum:exportownpost', $context, $user))); | |
556 | } | |
557 | ||
558 | /** | |
559 | * Get the forum entity for this capability manager. | |
560 | * | |
561 | * @return forum_entity | |
562 | */ | |
563 | protected function get_forum() : forum_entity { | |
564 | return $this->forum; | |
565 | } | |
566 | ||
567 | /** | |
568 | * Get the legacy forum record for this forum. | |
569 | * | |
570 | * @return stdClass | |
571 | */ | |
572 | protected function get_forum_record() : stdClass { | |
573 | return $this->forumrecord; | |
574 | } | |
575 | ||
576 | /** | |
577 | * Get the context for this capability manager. | |
578 | * | |
579 | * @return context | |
580 | */ | |
581 | protected function get_context() : context { | |
582 | return $this->context; | |
583 | } | |
584 | ||
585 | /** | |
586 | * Get the legacy discussion record for the given discussion entity. | |
587 | * | |
588 | * @param discussion_entity $discussion The discussion to convert | |
589 | * @return stdClass | |
590 | */ | |
591 | protected function get_discussion_record(discussion_entity $discussion) : stdClass { | |
592 | return $this->discussiondatamapper->to_legacy_object($discussion); | |
593 | } | |
594 | ||
595 | /** | |
596 | * Get the legacy post record for the given post entity. | |
597 | * | |
598 | * @param post_entity $post The post to convert | |
599 | * @return stdClass | |
600 | */ | |
601 | protected function get_post_record(post_entity $post) : stdClass { | |
602 | return $this->postdatamapper->to_legacy_object($post); | |
603 | } | |
604 | ||
605 | /** | |
606 | * Can the user view the participants of this discussion? | |
607 | * | |
608 | * @param stdClass $user The user to check | |
609 | * @param discussion_entity $discussion The discussion to check | |
610 | * @return bool | |
611 | */ | |
612 | public function can_view_participants(stdClass $user, discussion_entity $discussion) : bool { | |
613 | return course_can_view_participants($this->get_context()) && | |
614 | !$this->must_post_before_viewing_discussion($user, $discussion); | |
615 | } | |
616 | ||
617 | /** | |
618 | * Can the user view hidden posts in this forum? | |
619 | * | |
620 | * @param stdClass $user The user to check | |
621 | * @return bool | |
622 | */ | |
623 | public function can_view_hidden_posts(stdClass $user) : bool { | |
624 | return has_capability('mod/forum:viewhiddentimedposts', $this->get_context(), $user); | |
625 | } | |
626 | ||
627 | /** | |
628 | * Can the user manage this forum? | |
629 | * | |
630 | * @param stdClass $user The user to check | |
631 | * @return bool | |
632 | */ | |
633 | public function can_manage_forum(stdClass $user) { | |
634 | return has_capability('moodle/course:manageactivities', $this->get_context(), $user); | |
635 | } | |
636 | ||
637 | /** | |
638 | * Can the user manage tags on the site? | |
639 | * | |
640 | * @param stdClass $user The user to check | |
641 | * @return bool | |
642 | */ | |
643 | public function can_manage_tags(stdClass $user) : bool { | |
644 | return has_capability('moodle/tag:manage', context_system::instance(), $user); | |
645 | } | |
92ba55ee P |
646 | |
647 | /** | |
648 | * Checks whether the user can self enrol into the course. | |
649 | * Mimics the checks on the add button in deprecatedlib/forum_print_latest_discussions | |
650 | * | |
651 | * @param stdClass $user | |
652 | * @return bool | |
653 | */ | |
654 | public function can_self_enrol(stdClass $user) : bool { | |
655 | $canstart = false; | |
656 | ||
657 | if ($this->forum->get_type() != 'news') { | |
658 | if (isguestuser($user) or !isloggedin()) { | |
659 | $canstart = true; | |
660 | } | |
661 | ||
662 | if (!is_enrolled($this->context) and !is_viewing($this->context)) { | |
663 | // Allow guests and not-logged-in to see the button - they are prompted to log in after clicking the link, | |
664 | // Normal users with temporary guest access see this button too, they are asked to enrol instead, | |
665 | // Do not show the button to users with suspended enrolments here. | |
666 | $canstart = enrol_selfenrol_available($this->forum->get_course_id()); | |
667 | } | |
668 | } | |
669 | ||
670 | return $canstart; | |
671 | } | |
75af28c7 SL |
672 | |
673 | /** | |
674 | * Checks whether the user can export the whole forum (discussions and posts). | |
675 | * | |
676 | * @param stdClass $user The user object. | |
677 | * @return bool True if the user can export the forum or false otherwise. | |
678 | */ | |
679 | public function can_export_forum(stdClass $user) : bool { | |
680 | return has_capability('mod/forum:exportforum', $this->get_context(), $user); | |
681 | } | |
47d38303 | 682 | } |