MDL-65069 mod_forum: Remove unused code and additional dev docs.
[moodle.git] / mod / forum / classes / local / renderers / discussion_list.php
CommitLineData
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 * Discussion list renderer.
19 *
20 * @package mod_forum
21 * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace mod_forum\local\renderers;
26
27defined('MOODLE_INTERNAL') || die();
28
29use mod_forum\local\entities\forum as forum_entity;
30use mod_forum\local\factories\legacy_data_mapper as legacy_data_mapper_factory;
31use mod_forum\local\factories\exporter as exporter_factory;
32use mod_forum\local\factories\vault as vault_factory;
33use mod_forum\local\factories\url as url_factory;
34use mod_forum\local\managers\capability as capability_manager;
35use mod_forum\local\vaults\discussion_list as discussion_list_vault;
36use renderer_base;
37use stdClass;
38use core\output\notification;
54d38a73 39use mod_forum\local\factories\builder as builder_factory;
47d38303
RW
40
41require_once($CFG->dirroot . '/mod/forum/lib.php');
42
43/**
44 * The discussion list renderer.
45 *
46 * @package mod_forum
47 * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
48 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
49 */
50class discussion_list {
51 /** @var forum_entity The forum being rendered */
52 private $forum;
53
54 /** @var stdClass The DB record for the forum being rendered */
55 private $forumrecord;
56
57 /** @var renderer_base The renderer used to render the view */
58 private $renderer;
59
60 /** @var legacy_data_mapper_factory $legacydatamapperfactory Legacy data mapper factory */
61 private $legacydatamapperfactory;
62
63 /** @var exporter_factory $exporterfactory Exporter factory */
64 private $exporterfactory;
65
66 /** @var vault_factory $vaultfactory Vault factory */
67 private $vaultfactory;
68
69 /** @var capability_manager $capabilitymanager Capability manager */
70 private $capabilitymanager;
71
72 /** @var url_factory $urlfactory URL factory */
73 private $urlfactory;
74
75 /** @var array $notifications List of notification HTML */
76 private $notifications;
77
54d38a73
MG
78 /** @var builder_factory $builderfactory Builder factory */
79 private $builderfactory;
80
81 /** @var callable $postprocessfortemplate Function to process exported posts before template rendering */
82 private $postprocessfortemplate;
83
c661a129
AN
84 /** @var string $template The template to use when displaying */
85 private $template;
86
47d38303
RW
87 /**
88 * Constructor for a new discussion list renderer.
89 *
90 * @param forum_entity $forum The forum entity to be rendered
91 * @param renderer_base $renderer The renderer used to render the view
92 * @param legacy_data_mapper_factory $legacydatamapperfactory The factory used to fetch a legacy record
93 * @param exporter_factory $exporterfactory The factory used to fetch exporter instances
94 * @param vault_factory $vaultfactory The factory used to fetch the vault instances
54d38a73 95 * @param builder_factory $builderfactory The factory used to fetch the builder instances
47d38303
RW
96 * @param capability_manager $capabilitymanager The managed used to check capabilities on the forum
97 * @param url_factory $urlfactory The factory used to create URLs in the forum
c661a129 98 * @param string $template
47d38303 99 * @param notification[] $notifications A list of any notifications to be displayed within the page
446ba046 100 * @param callable|null $postprocessfortemplate Callback function to process discussion lists for templates
47d38303
RW
101 */
102 public function __construct(
103 forum_entity $forum,
104 renderer_base $renderer,
105 legacy_data_mapper_factory $legacydatamapperfactory,
106 exporter_factory $exporterfactory,
107 vault_factory $vaultfactory,
54d38a73 108 builder_factory $builderfactory,
47d38303
RW
109 capability_manager $capabilitymanager,
110 url_factory $urlfactory,
c661a129 111 string $template,
54d38a73
MG
112 array $notifications = [],
113 callable $postprocessfortemplate = null
47d38303
RW
114 ) {
115 $this->forum = $forum;
116 $this->renderer = $renderer;
117 $this->legacydatamapperfactory = $legacydatamapperfactory;
118 $this->exporterfactory = $exporterfactory;
119 $this->vaultfactory = $vaultfactory;
54d38a73 120 $this->builderfactory = $builderfactory;
47d38303 121 $this->capabilitymanager = $capabilitymanager;
c661a129 122
47d38303
RW
123 $this->urlfactory = $urlfactory;
124 $this->notifications = $notifications;
54d38a73 125 $this->postprocessfortemplate = $postprocessfortemplate;
c661a129 126 $this->template = $template;
47d38303
RW
127
128 $forumdatamapper = $this->legacydatamapperfactory->get_forum_data_mapper();
129 $this->forumrecord = $forumdatamapper->to_legacy_object($forum);
130 }
131
132 /**
133 * Render for the specified user.
134 *
135 * @param stdClass $user The user to render for
136 * @param cm_info $cm The course module info for this discussion list
137 * @param int $groupid The group to render
138 * @param int $sortorder The sort order to use when selecting the discussions in the list
139 * @param int $pageno The zero-indexed page number to use
140 * @param int $pagesize The number of discussions to show on the page
141 * @return string The rendered content for display
142 */
143 public function render(stdClass $user, \cm_info $cm, ?int $groupid, ?int $sortorder, ?int $pageno, ?int $pagesize) : string {
54d38a73
MG
144 global $PAGE;
145
47d38303
RW
146 $forum = $this->forum;
147
148 $pagesize = $this->get_page_size($pagesize);
149 $pageno = $this->get_page_number($pageno);
150
151 $groupids = $this->get_groups_from_groupid($user, $groupid);
152 $forumexporter = $this->exporterfactory->get_forum_exporter(
153 $user,
154 $this->forum,
155 $groupid
156 );
157
54d38a73
MG
158 // Count all forum discussion posts.
159 $alldiscussionscount = $this->get_count_all_discussions($user, $groupids);
160
161 // Get all forum discussions posts.
162 $discussions = $this->get_discussions($user, $groupids, $sortorder, $pageno, $pagesize);
163
164 $forumview = [
15f7dbe5 165 'forum' => (array) $forumexporter->export($this->renderer),
97babbf7 166 'newdiscussionhtml' => $this->get_discussion_form($user, $cm, $groupid),
15f7dbe5
RW
167 'groupchangemenu' => groups_print_activity_menu(
168 $cm,
169 $this->urlfactory->get_forum_view_url_from_forum($forum),
170 true
171 ),
23f5e65e
AN
172 'hasmore' => ($alldiscussionscount > $pagesize),
173 'notifications' => $this->get_notifications($user, $groupid),
54d38a73
MG
174 ];
175
176 if (!$discussions) {
c661a129 177 return $this->renderer->render_from_template($this->template, $forumview);
54d38a73
MG
178 }
179
180 if ($this->postprocessfortemplate !== null) {
181 // We've got some post processing to do!
182 $exportedposts = ($this->postprocessfortemplate) ($discussions, $user, $forum);
183 }
184
47d38303 185 $forumview = array_merge(
54d38a73
MG
186 $forumview,
187 [
54d38a73
MG
188 'pagination' => $this->renderer->render(new \paging_bar($alldiscussionscount, $pageno, $pagesize, $PAGE->url, 'p')),
189 ],
190 $exportedposts
191 );
47d38303 192
c661a129 193 return $this->renderer->render_from_template($this->template, $forumview);
47d38303
RW
194 }
195
97babbf7
P
196 /**
197 * Get the mod_forum_post_form. This is the default boiler plate from mod_forum/post_form.php with the inpage flag caveat
198 *
199 * @param stdClass $user The user the form is being generated for
200 * @param \cm_info $cm
201 * @param int $groupid The groupid if any
202 *
203 * @return string The rendered html
204 */
9ff7cae7 205 private function get_discussion_form(stdClass $user, \cm_info $cm, ?int $groupid) {
9ff7cae7
P
206 $forum = $this->forum;
207 $forumrecord = $this->legacydatamapperfactory->get_forum_data_mapper()->to_legacy_object($forum);
208 $modcontext = \context_module::instance($cm->id);
97babbf7
P
209 $coursecontext = \context_course::instance($forum->get_course_id());
210 $post = (object) [
211 'course' => $forum->get_course_id(),
212 'forum' => $forum->get_id(),
213 'discussion' => 0, // Ie discussion # not defined yet.
214 'parent' => 0,
215 'subject' => '',
216 'userid' => $user->id,
217 'message' => '',
218 'messageformat' => editors_get_preferred_format(),
219 'messagetrust' => 0,
220 'groupid' => $groupid,
221 ];
cb28132d 222 $thresholdwarning = forum_check_throttling($forumrecord, $cm);
97babbf7 223
2aff2c19
P
224 $formparams = array(
225 'course' => $forum->get_course_record(),
9ff7cae7 226 'cm' => $cm,
97babbf7 227 'coursecontext' => $coursecontext,
9ff7cae7
P
228 'modcontext' => $modcontext,
229 'forum' => $forumrecord,
230 'post' => $post,
231 'subscribe' => \mod_forum\subscriptions::is_subscribed($user->id, $forumrecord,
232 null, $cm),
233 'thresholdwarning' => $thresholdwarning,
97babbf7 234 'inpagereply' => true,
2aff2c19
P
235 'edit' => 0
236 );
237 $mformpost = new \mod_forum_post_form('post.php', $formparams, 'post', '', array('id' => 'mformforum'));
cb28132d 238 $discussionsubscribe = \mod_forum\subscriptions::get_user_default_subscription($forumrecord, $coursecontext, $cm, null);
9ff7cae7
P
239
240 $params = array('reply' => 0, 'forum' => $forumrecord->id, 'edit' => 0) +
97babbf7
P
241 (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) +
242 array(
243 'userid' => $post->userid,
244 'parent' => $post->parent,
245 'discussion' => $post->discussion,
cb28132d
P
246 'course' => $forum->get_course_id(),
247 'discussionsubscribe' => $discussionsubscribe
97babbf7 248 );
9ff7cae7
P
249 $mformpost->set_data($params);
250
251 return $mformpost->render();
252 }
253
47d38303
RW
254 /**
255 * Get the list of groups to show based on the current user and requested groupid.
256 *
257 * @param stdClass $user The user viewing
258 * @param int $groupid The groupid requested
259 * @return array The list of groups to show
260 */
261 private function get_groups_from_groupid(stdClass $user, ?int $groupid) : ?array {
262 $forum = $this->forum;
263 $effectivegroupmode = $forum->get_effective_group_mode();
264 if (empty($effectivegroupmode)) {
265 // This forum is not in a group mode. Show all posts always.
266 return null;
267 }
268
269 if (null == $groupid) {
270 // No group was specified.
271 $showallgroups = (VISIBLEGROUPS == $effectivegroupmode);
272 $showallgroups = $showallgroups || $this->capabilitymanager->can_access_all_groups($user);
273 if ($showallgroups) {
274 // Return null to show all groups.
275 return null;
276 } else {
277 // No group was specified. Only show the users current groups.
278 return array_keys(
279 groups_get_all_groups(
280 $forum->get_course_id(),
281 $user->id,
282 $forum->get_course_module_record()->groupingid
283 )
284 );
285 }
286 } else {
287 // A group was specified. Just show that group.
288 return [$groupid];
289 }
290 }
291
292 /**
293 * Fetch the data used to display the discussions on the current page.
294 *
295 * @param stdClass $user The user to render for
296 * @param int[]|null $groupids The group ids for this list of discussions
297 * @param int|null $sortorder The sort order to use when selecting the discussions in the list
298 * @param int|null $pageno The zero-indexed page number to use
299 * @param int|null $pagesize The number of discussions to show on the page
300 * @return stdClass The data to use for display
301 */
54d38a73 302 private function get_discussions(stdClass $user, ?array $groupids, ?int $sortorder, ?int $pageno, ?int $pagesize) {
47d38303
RW
303 $forum = $this->forum;
304 $discussionvault = $this->vaultfactory->get_discussions_in_forum_vault();
305 if (null === $groupids) {
54d38a73 306 return $discussions = $discussionvault->get_from_forum_id(
47d38303
RW
307 $forum->get_id(),
308 $this->capabilitymanager->can_view_hidden_posts($user),
309 $user->id,
310 $sortorder,
311 $this->get_page_size($pagesize),
54d38a73 312 $this->get_page_number($pageno) * $this->get_page_size($pagesize));
47d38303 313 } else {
54d38a73 314 return $discussions = $discussionvault->get_from_forum_id_and_group_id(
47d38303
RW
315 $forum->get_id(),
316 $groupids,
317 $this->capabilitymanager->can_view_hidden_posts($user),
318 $user->id,
319 $sortorder,
320 $this->get_page_size($pagesize),
54d38a73 321 $this->get_page_number($pageno) * $this->get_page_size($pagesize));
47d38303 322 }
54d38a73 323 }
47d38303 324
54d38a73
MG
325 /**
326 * Get a count of all discussions in a forum.
327 *
328 * @param stdClass $user The user to render for
329 * @param array $groupids The array of groups to render
330 * @return int The number of discussions in a forum
331 */
332 public function get_count_all_discussions(stdClass $user, ?array $groupids) {
333 $discussionvault = $this->vaultfactory->get_discussions_in_forum_vault();
334 if (null === $groupids) {
335 return $discussionvault->get_total_discussion_count_from_forum_id(
336 $this->forum->get_id(),
337 $this->capabilitymanager->can_view_hidden_posts($user),
338 $user->id);
339 } else {
340 return $discussionvault->get_total_discussion_count_from_forum_id_and_group_id(
341 $this->forum->get_id(),
342 $groupids,
343 $this->capabilitymanager->can_view_hidden_posts($user),
344 $user->id);
47d38303 345 }
47d38303
RW
346 }
347
348 /**
349 * Fetch the page size to use when displaying the page.
350 *
351 * @param int $pagesize The number of discussions to show on the page
352 * @return int The normalised page size
353 */
354 private function get_page_size(?int $pagesize) : int {
355 if (null === $pagesize || $pagesize <= 0) {
356 $pagesize = discussion_list_vault::PAGESIZE_DEFAULT;
357 }
358
359 return $pagesize;
360 }
361
362 /**
363 * Fetch the current page number (zero-indexed).
364 *
365 * @param int $pageno The zero-indexed page number to use
366 * @return int The normalised page number
367 */
368 private function get_page_number(?int $pageno) : int {
369 if (null === $pageno || $pageno < 0) {
370 $pageno = 0;
371 }
372
373 return $pageno;
374 }
375
47d38303
RW
376 /**
377 * Get the list of notification for display.
378 *
379 * @param stdClass $user The viewing user
380 * @param int|null $groupid The forum's group id
381 * @return array
382 */
383 private function get_notifications(stdClass $user, ?int $groupid) : array {
384 $notifications = $this->notifications;
385 $forum = $this->forum;
386 $renderer = $this->renderer;
387 $capabilitymanager = $this->capabilitymanager;
388
cbf63d8e
SR
389 if ($forum->is_cutoff_date_reached()) {
390 $notifications[] = (new notification(
391 get_string('cutoffdatereached', 'forum'),
392 notification::NOTIFY_INFO
393 ))->set_show_closebutton();
82482e3d
SR
394 } else if ($forum->is_due_date_reached()) {
395 $notifications[] = (new notification(
396 get_string('thisforumisdue', 'forum', userdate($forum->get_due_date())),
397 notification::NOTIFY_INFO
398 ))->set_show_closebutton();
cbf63d8e
SR
399 } else if ($forum->has_due_date()) {
400 $notifications[] = (new notification(
401 get_string('thisforumhasduedate', 'forum', userdate($forum->get_due_date())),
402 notification::NOTIFY_INFO
403 ))->set_show_closebutton();
404 }
405
47d38303
RW
406 if ($forum->has_blocking_enabled()) {
407 $notifications[] = (new notification(
408 get_string('thisforumisthrottled', 'forum', [
409 'blockafter' => $forum->get_block_after(),
410 'blockperiod' => get_string('secondstotime' . $forum->get_block_period())
411 ])
412 ))->set_show_closebutton();
413 }
414
15f7dbe5
RW
415 if ($forum->is_in_group_mode() && !$capabilitymanager->can_access_all_groups($user)) {
416 if ($groupid === null) {
417 if (!$capabilitymanager->can_post_to_my_groups($user)) {
418 $notifications[] = (new notification(
419 get_string('cannotadddiscussiongroup', 'mod_forum'),
420 \core\output\notification::NOTIFY_WARNING
421 ))->set_show_closebutton();
422 } else {
423 $notifications[] = (new notification(
424 get_string('cannotadddiscussionall', 'mod_forum'),
425 \core\output\notification::NOTIFY_WARNING
426 ))->set_show_closebutton();
427 }
428 } else if (!$capabilitymanager->can_access_group($user, $groupid)) {
47d38303
RW
429 $notifications[] = (new notification(
430 get_string('cannotadddiscussion', 'mod_forum'),
431 \core\output\notification::NOTIFY_WARNING
432 ))->set_show_closebutton();
433 }
434 }
435
436 if ('qanda' === $forum->get_type() && !$capabilitymanager->can_manage_forum($user)) {
437 $notifications[] = (new notification(
438 get_string('qandanotify', 'forum'),
439 notification::NOTIFY_INFO
440 ))->set_show_closebutton();
441 }
442
443 if ('eachuser' === $forum->get_type()) {
444 $notifications[] = (new notification(
445 get_string('allowsdiscussions', 'forum'),
446 notification::NOTIFY_INFO)
447 )->set_show_closebutton();
448 }
449
450 return array_map(function($notification) {
451 return $notification->export_for_template($this->renderer);
452 }, $notifications);
453 }
454}