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