See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 * Forum post renderable. 19 * 20 * @package mod_forum 21 * @copyright 2015 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\output; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 /** 30 * Forum post renderable. 31 * 32 * @copyright 2015 Andrew Nicols <andrew@nicols.co.uk> 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 * 35 * @property boolean $viewfullnames Whether to override fullname() 36 */ 37 class forum_post implements \renderable, \templatable { 38 39 /** 40 * The course that the forum post is in. 41 * 42 * @var object $course 43 */ 44 protected $course = null; 45 46 /** 47 * The course module for the forum. 48 * 49 * @var object $cm 50 */ 51 protected $cm = null; 52 53 /** 54 * The forum that the post is in. 55 * 56 * @var object $forum 57 */ 58 protected $forum = null; 59 60 /** 61 * The discussion that the forum post is in. 62 * 63 * @var object $discussion 64 */ 65 protected $discussion = null; 66 67 /** 68 * The forum post being displayed. 69 * 70 * @var object $post 71 */ 72 protected $post = null; 73 74 /** 75 * Whether the user can reply to this post. 76 * 77 * @var boolean $canreply 78 */ 79 protected $canreply = false; 80 81 /** 82 * Whether to override forum display when displaying usernames. 83 * @var boolean $viewfullnames 84 */ 85 protected $viewfullnames = false; 86 87 /** 88 * The user that is reading the post. 89 * 90 * @var object $userto 91 */ 92 protected $userto = null; 93 94 /** 95 * The user that wrote the post. 96 * 97 * @var object $author 98 */ 99 protected $author = null; 100 101 /** 102 * An associative array indicating which keys on this object should be writeable. 103 * 104 * @var array $writablekeys 105 */ 106 protected $writablekeys = array( 107 'viewfullnames' => true, 108 ); 109 110 /** 111 * Builds a renderable forum post 112 * 113 * @param object $course Course of the forum 114 * @param object $cm Course Module of the forum 115 * @param object $forum The forum of the post 116 * @param object $discussion Discussion thread in which the post appears 117 * @param object $post The post 118 * @param object $author Author of the post 119 * @param object $recipient Recipient of the email 120 * @param bool $canreply True if the user can reply to the post 121 */ 122 public function __construct($course, $cm, $forum, $discussion, $post, $author, $recipient, $canreply) { 123 $this->course = $course; 124 $this->cm = $cm; 125 $this->forum = $forum; 126 $this->discussion = $discussion; 127 $this->post = $post; 128 $this->author = $author; 129 $this->userto = $recipient; 130 $this->canreply = $canreply; 131 } 132 133 /** 134 * Export this data so it can be used as the context for a mustache template. 135 * 136 * @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments 137 * @param bool $plaintext Whethe the target is a plaintext target 138 * @return array Data ready for use in a mustache template 139 */ 140 public function export_for_template(\renderer_base $renderer, $plaintext = false) { 141 if ($plaintext) { 142 return $this->export_for_template_text($renderer); 143 } else { 144 return $this->export_for_template_html($renderer); 145 } 146 } 147 148 /** 149 * Export this data so it can be used as the context for a mustache template. 150 * 151 * @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments 152 * @return array Data ready for use in a mustache template 153 */ 154 protected function export_for_template_text(\mod_forum_renderer $renderer) { 155 $data = $this->export_for_template_shared($renderer); 156 return $data + array( 157 'id' => html_entity_decode($this->post->id, ENT_COMPAT), 158 'coursename' => html_entity_decode($this->get_coursename(), ENT_COMPAT), 159 'courselink' => html_entity_decode($this->get_courselink(), ENT_COMPAT), 160 'forumname' => html_entity_decode($this->get_forumname(), ENT_COMPAT), 161 'showdiscussionname' => html_entity_decode($this->get_showdiscussionname(), ENT_COMPAT), 162 'discussionname' => html_entity_decode($this->get_discussionname(), ENT_COMPAT), 163 'subject' => html_entity_decode($this->get_subject(), ENT_COMPAT), 164 'authorfullname' => html_entity_decode($this->get_author_fullname(), ENT_COMPAT), 165 'postdate' => html_entity_decode($this->get_postdate(), ENT_COMPAT), 166 167 // Format some components according to the renderer. 168 'message' => html_entity_decode($renderer->format_message_text($this->cm, $this->post), ENT_COMPAT), 169 'attachments' => html_entity_decode($renderer->format_message_attachments($this->cm, $this->post), ENT_COMPAT), 170 171 'canreply' => $this->canreply, 172 'permalink' => $this->get_permalink(), 173 'firstpost' => $this->get_is_firstpost(), 174 'replylink' => $this->get_replylink(), 175 'unsubscribediscussionlink' => $this->get_unsubscribediscussionlink(), 176 'unsubscribeforumlink' => $this->get_unsubscribeforumlink(), 177 'parentpostlink' => $this->get_parentpostlink(), 178 179 'forumindexlink' => $this->get_forumindexlink(), 180 'forumviewlink' => $this->get_forumviewlink(), 181 'discussionlink' => $this->get_discussionlink(), 182 183 'authorlink' => $this->get_authorlink(), 184 'authorpicture' => $this->get_author_picture($renderer), 185 186 'grouppicture' => $this->get_group_picture($renderer), 187 ); 188 } 189 190 /** 191 * Export this data so it can be used as the context for a mustache template. 192 * 193 * @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments 194 * @return array Data ready for use in a mustache template 195 */ 196 protected function export_for_template_html(\mod_forum_renderer $renderer) { 197 $data = $this->export_for_template_shared($renderer); 198 return $data + array( 199 'id' => $this->post->id, 200 'coursename' => $this->get_coursename(), 201 'courselink' => $this->get_courselink(), 202 'forumname' => $this->get_forumname(), 203 'showdiscussionname' => $this->get_showdiscussionname(), 204 'discussionname' => $this->get_discussionname(), 205 'subject' => $this->get_subject(), 206 'authorfullname' => $this->get_author_fullname(), 207 'postdate' => $this->get_postdate(), 208 209 // Format some components according to the renderer. 210 'message' => $renderer->format_message_text($this->cm, $this->post), 211 'attachments' => $renderer->format_message_attachments($this->cm, $this->post), 212 ); 213 } 214 215 /** 216 * Export this data so it can be used as the context for a mustache template. 217 * 218 * @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments 219 * @return stdClass Data ready for use in a mustache template 220 */ 221 protected function export_for_template_shared(\mod_forum_renderer $renderer) { 222 return array( 223 'canreply' => $this->canreply, 224 'permalink' => $this->get_permalink(), 225 'firstpost' => $this->get_is_firstpost(), 226 'replylink' => $this->get_replylink(), 227 'unsubscribediscussionlink' => $this->get_unsubscribediscussionlink(), 228 'unsubscribeforumlink' => $this->get_unsubscribeforumlink(), 229 'parentpostlink' => $this->get_parentpostlink(), 230 231 'forumindexlink' => $this->get_forumindexlink(), 232 'forumviewlink' => $this->get_forumviewlink(), 233 'discussionlink' => $this->get_discussionlink(), 234 235 'authorlink' => $this->get_authorlink(), 236 'authorpicture' => $this->get_author_picture($renderer), 237 238 'grouppicture' => $this->get_group_picture($renderer), 239 240 'isprivatereply' => !empty($this->post->privatereplyto), 241 ); 242 } 243 244 /** 245 * Magically sets a property against this object. 246 * 247 * @param string $key 248 * @param mixed $value 249 */ 250 public function __set($key, $value) { 251 // First attempt to use the setter function. 252 $methodname = 'set_' . $key; 253 if (method_exists($this, $methodname)) { 254 return $this->{$methodname}($value); 255 } 256 257 // Fall back to the writable keys list. 258 if (isset($this->writablekeys[$key]) && $this->writablekeys[$key]) { 259 return $this->{$key} = $value; 260 } 261 262 // Throw an error rather than fail silently. 263 throw new \coding_exception('Tried to set unknown property "' . $key . '"'); 264 } 265 266 /** 267 * Whether this is the first post. 268 * 269 * @return boolean 270 */ 271 public function get_is_firstpost() { 272 return empty($this->post->parent); 273 } 274 275 /** 276 * Get the link to the course. 277 * 278 * @return string 279 */ 280 public function get_courselink() { 281 $link = new \moodle_url( 282 // Posts are viewed on the topic. 283 '/course/view.php', array( 284 'id' => $this->course->id, 285 ) 286 ); 287 288 return $link->out(false); 289 } 290 291 /** 292 * Get the link to the forum index for this course. 293 * 294 * @return string 295 */ 296 public function get_forumindexlink() { 297 $link = new \moodle_url( 298 // Posts are viewed on the topic. 299 '/mod/forum/index.php', array( 300 'id' => $this->course->id, 301 ) 302 ); 303 304 return $link->out(false); 305 } 306 307 /** 308 * Get the link to the view page for this forum. 309 * 310 * @return string 311 */ 312 public function get_forumviewlink() { 313 $link = new \moodle_url( 314 // Posts are viewed on the topic. 315 '/mod/forum/view.php', array( 316 'f' => $this->forum->id, 317 ) 318 ); 319 320 return $link->out(false); 321 } 322 323 /** 324 * Get the link to the current discussion. 325 * 326 * @return string 327 */ 328 protected function _get_discussionlink() { 329 return new \moodle_url( 330 // Posts are viewed on the topic. 331 '/mod/forum/discuss.php', array( 332 // Within a discussion. 333 'd' => $this->discussion->id, 334 ) 335 ); 336 } 337 338 /** 339 * Get the link to the current discussion. 340 * 341 * @return string 342 */ 343 public function get_discussionlink() { 344 $link = $this->_get_discussionlink(); 345 346 return $link->out(false); 347 } 348 349 /** 350 * Get the link to the current post, including post anchor. 351 * 352 * @return string 353 */ 354 public function get_permalink() { 355 $link = $this->_get_discussionlink(); 356 $link->set_anchor($this->get_postanchor()); 357 358 return $link->out(false); 359 } 360 361 /** 362 * Get the link to the parent post. 363 * 364 * @return string 365 */ 366 public function get_parentpostlink() { 367 $link = $this->_get_discussionlink(); 368 $link->param('parent', $this->post->parent); 369 370 return $link->out(false); 371 } 372 373 /** 374 * Get the link to the author's profile page. 375 * 376 * @return string 377 */ 378 public function get_authorlink() { 379 $link = new \moodle_url( 380 '/user/view.php', array( 381 'id' => $this->post->userid, 382 'course' => $this->course->id, 383 ) 384 ); 385 386 return $link->out(false); 387 } 388 389 /** 390 * Get the link to unsubscribe from the forum. 391 * 392 * @return string 393 */ 394 public function get_unsubscribeforumlink() { 395 if (!\mod_forum\subscriptions::is_subscribable($this->forum)) { 396 return null; 397 } 398 $link = new \moodle_url( 399 '/mod/forum/subscribe.php', array( 400 'id' => $this->forum->id, 401 ) 402 ); 403 404 return $link->out(false); 405 } 406 407 /** 408 * Get the link to unsubscribe from the discussion. 409 * 410 * @return string 411 */ 412 public function get_unsubscribediscussionlink() { 413 if (!\mod_forum\subscriptions::is_subscribable($this->forum)) { 414 return null; 415 } 416 $link = new \moodle_url( 417 '/mod/forum/subscribe.php', array( 418 'id' => $this->forum->id, 419 'd' => $this->discussion->id, 420 ) 421 ); 422 423 return $link->out(false); 424 } 425 426 /** 427 * Get the link to reply to the current post. 428 * 429 * @return string 430 */ 431 public function get_replylink() { 432 return new \moodle_url( 433 '/mod/forum/post.php', array( 434 'reply' => $this->post->id, 435 ) 436 ); 437 } 438 439 /** 440 * The formatted subject for the current post. 441 * 442 * @return string 443 */ 444 public function get_subject() { 445 return format_string($this->post->subject, true); 446 } 447 448 /** 449 * The plaintext anchor id for the current post. 450 * 451 * @return string 452 */ 453 public function get_postanchor() { 454 return 'p' . $this->post->id; 455 } 456 457 /** 458 * ID number of the course that the forum is in. 459 * 460 * @return string 461 */ 462 public function get_courseidnumber() { 463 return s($this->course->idnumber); 464 } 465 466 /** 467 * The full name of the course that the forum is in. 468 * 469 * @return string 470 */ 471 public function get_coursefullname() { 472 return format_string($this->course->fullname, true, array( 473 'context' => \context_course::instance($this->course->id), 474 )); 475 } 476 477 /** 478 * The name of the course that the forum is in. 479 * 480 * @return string 481 */ 482 public function get_coursename() { 483 return format_string($this->course->shortname, true, array( 484 'context' => \context_course::instance($this->course->id), 485 )); 486 } 487 488 /** 489 * The name of the forum. 490 * 491 * @return string 492 */ 493 public function get_forumname() { 494 return format_string($this->forum->name, true); 495 } 496 497 /** 498 * The name of the current discussion. 499 * 500 * @return string 501 */ 502 public function get_discussionname() { 503 return format_string($this->discussion->name, true); 504 } 505 506 /** 507 * Whether to show the discussion name. 508 * If the forum name matches the discussion name, the discussion name 509 * is not typically displayed. 510 * 511 * @return boolean 512 */ 513 public function get_showdiscussionname() { 514 return ($this->forum->name !== $this->discussion->name); 515 } 516 517 /** 518 * The fullname of the post author. 519 * 520 * @return string 521 */ 522 public function get_author_fullname() { 523 return fullname($this->author, $this->viewfullnames); 524 } 525 526 /** 527 * The recipient of the post. 528 * 529 * @return string 530 */ 531 protected function get_postto() { 532 global $USER; 533 if (null === $this->userto) { 534 return $USER; 535 } 536 537 return $this->userto; 538 } 539 540 /** 541 * The date of the post, formatted according to the postto user's 542 * preferences. 543 * 544 * @return string. 545 */ 546 public function get_postdate() { 547 global $CFG; 548 549 $postmodified = $this->post->modified; 550 if (!empty($CFG->forum_enabletimedposts) && ($this->discussion->timestart > $postmodified)) { 551 $postmodified = $this->discussion->timestart; 552 } 553 554 return userdate($postmodified, "", \core_date::get_user_timezone($this->get_postto())); 555 } 556 557 /** 558 * The HTML for the author's user picture. 559 * 560 * @param \renderer_base $renderer 561 * @return string 562 */ 563 public function get_author_picture(\renderer_base $renderer) { 564 return $renderer->user_picture($this->author, array('courseid' => $this->course->id)); 565 } 566 567 /** 568 * The HTML for a group picture. 569 * 570 * @param \renderer_base $renderer 571 * @return string 572 */ 573 public function get_group_picture(\renderer_base $renderer) { 574 if (isset($this->userfrom->groups)) { 575 $groups = $this->userfrom->groups[$this->forum->id]; 576 } else { 577 $groups = groups_get_all_groups($this->course->id, $this->author->id, $this->cm->groupingid); 578 } 579 580 if ($this->get_is_firstpost()) { 581 return print_group_picture($groups, $this->course->id, false, true, true, true); 582 } 583 } 584 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body