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