Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 * Edit and save a new post to a discussion 19 * 20 * @package mod_forum 21 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 require_once('../../config.php'); 26 require_once ('lib.php'); 27 require_once($CFG->libdir.'/completionlib.php'); 28 29 $reply = optional_param('reply', 0, PARAM_INT); 30 $forum = optional_param('forum', 0, PARAM_INT); 31 $edit = optional_param('edit', 0, PARAM_INT); 32 $delete = optional_param('delete', 0, PARAM_INT); 33 $prune = optional_param('prune', 0, PARAM_INT); 34 $name = optional_param('name', '', PARAM_CLEAN); 35 $confirm = optional_param('confirm', 0, PARAM_INT); 36 $groupid = optional_param('groupid', null, PARAM_INT); 37 $subject = optional_param('subject', '', PARAM_TEXT); 38 39 // Values posted via the inpage reply form. 40 $prefilledpost = optional_param('post', '', PARAM_TEXT); 41 $prefilledpostformat = optional_param('postformat', FORMAT_MOODLE, PARAM_INT); 42 $prefilledprivatereply = optional_param('privatereply', false, PARAM_BOOL); 43 44 $PAGE->set_url('/mod/forum/post.php', array( 45 'reply' => $reply, 46 'forum' => $forum, 47 'edit' => $edit, 48 'delete' => $delete, 49 'prune' => $prune, 50 'name' => $name, 51 'confirm' => $confirm, 52 'groupid' => $groupid, 53 )); 54 // These page_params will be passed as hidden variables later in the form. 55 $pageparams = array('reply' => $reply, 'forum' => $forum, 'edit' => $edit); 56 57 $sitecontext = context_system::instance(); 58 59 $entityfactory = mod_forum\local\container::get_entity_factory(); 60 $vaultfactory = mod_forum\local\container::get_vault_factory(); 61 $managerfactory = mod_forum\local\container::get_manager_factory(); 62 $legacydatamapperfactory = mod_forum\local\container::get_legacy_data_mapper_factory(); 63 $urlfactory = mod_forum\local\container::get_url_factory(); 64 65 $forumvault = $vaultfactory->get_forum_vault(); 66 $forumdatamapper = $legacydatamapperfactory->get_forum_data_mapper(); 67 68 $discussionvault = $vaultfactory->get_discussion_vault(); 69 $discussiondatamapper = $legacydatamapperfactory->get_discussion_data_mapper(); 70 71 $postvault = $vaultfactory->get_post_vault(); 72 $postdatamapper = $legacydatamapperfactory->get_post_data_mapper(); 73 74 if (!isloggedin() or isguestuser()) { 75 if (!isloggedin() and !get_local_referer()) { 76 // No referer+not logged in - probably coming in via email See MDL-9052. 77 require_login(); 78 } 79 80 if (!empty($forum)) { 81 // User is starting a new discussion in a forum. 82 $forumentity = $forumvault->get_from_id($forum); 83 if (empty($forumentity)) { 84 print_error('invalidforumid', 'forum'); 85 } 86 } else if (!empty($reply)) { 87 // User is writing a new reply. 88 $forumentity = $forumvault->get_from_post_id($reply); 89 if (empty($forumentity)) { 90 print_error('invalidparentpostid', 'forum'); 91 } 92 } 93 94 $forum = $forumdatamapper->to_legacy_object($forumentity); 95 $modcontext = $forumentity->get_context(); 96 $course = $forumentity->get_course_record(); 97 if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) { 98 print_error("invalidcoursemodule"); 99 } 100 101 $PAGE->set_cm($cm, $course, $forum); 102 $PAGE->set_context($modcontext); 103 $PAGE->set_title($course->shortname); 104 $PAGE->set_heading($course->fullname); 105 $referer = get_local_referer(false); 106 107 echo $OUTPUT->header(); 108 echo $OUTPUT->confirm(get_string('noguestpost', 'forum').'<br /><br />'.get_string('liketologin'), get_login_url(), $referer); 109 echo $OUTPUT->footer(); 110 exit; 111 } 112 113 require_login(0, false); // Script is useless unless they're logged in. 114 115 $canreplyprivately = false; 116 117 if (!empty($forum)) { 118 // User is starting a new discussion in a forum. 119 $forumentity = $forumvault->get_from_id($forum); 120 if (empty($forumentity)) { 121 print_error('invalidforumid', 'forum'); 122 } 123 124 $capabilitymanager = $managerfactory->get_capability_manager($forumentity); 125 $forum = $forumdatamapper->to_legacy_object($forumentity); 126 $course = $forumentity->get_course_record(); 127 if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) { 128 print_error("invalidcoursemodule"); 129 } 130 131 // Retrieve the contexts. 132 $modcontext = $forumentity->get_context(); 133 $coursecontext = context_course::instance($course->id); 134 135 if ($forumentity->is_in_group_mode() && null === $groupid) { 136 $groupid = groups_get_activity_group($cm); 137 } 138 139 if (!$capabilitymanager->can_create_discussions($USER, $groupid)) { 140 if (!isguestuser()) { 141 if (!is_enrolled($coursecontext)) { 142 if (enrol_selfenrol_available($course->id)) { 143 $SESSION->wantsurl = qualified_me(); 144 $SESSION->enrolcancel = get_local_referer(false); 145 redirect(new moodle_url('/enrol/index.php', array('id' => $course->id, 146 'returnurl' => '/mod/forum/view.php?f=' . $forum->id)), 147 get_string('youneedtoenrol')); 148 } 149 } 150 } 151 print_error('nopostforum', 'forum'); 152 } 153 154 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $modcontext)) { 155 redirect( 156 $urlfactory->get_course_url_from_forum($forumentity), 157 get_string('activityiscurrentlyhidden'), 158 null, 159 \core\output\notification::NOTIFY_ERROR 160 ); 161 } 162 163 // Load up the $post variable. 164 165 $post = new stdClass(); 166 $post->course = $course->id; 167 $post->forum = $forum->id; 168 $post->discussion = 0; // Ie discussion # not defined yet. 169 $post->parent = 0; 170 $post->subject = $subject; 171 $post->userid = $USER->id; 172 $post->message = $prefilledpost; 173 $post->messageformat = editors_get_preferred_format(); 174 $post->messagetrust = 0; 175 $post->groupid = $groupid; 176 177 // Unsetting this will allow the correct return URL to be calculated later. 178 unset($SESSION->fromdiscussion); 179 180 } else if (!empty($reply)) { 181 // User is writing a new reply. 182 183 $parententity = $postvault->get_from_id($reply); 184 if (empty($parententity)) { 185 print_error('invalidparentpostid', 'forum'); 186 } 187 188 $discussionentity = $discussionvault->get_from_id($parententity->get_discussion_id()); 189 if (empty($discussionentity)) { 190 print_error('notpartofdiscussion', 'forum'); 191 } 192 193 $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id()); 194 if (empty($forumentity)) { 195 print_error('invalidforumid', 'forum'); 196 } 197 198 $capabilitymanager = $managerfactory->get_capability_manager($forumentity); 199 $parent = $postdatamapper->to_legacy_object($parententity); 200 $discussion = $discussiondatamapper->to_legacy_object($discussionentity); 201 $forum = $forumdatamapper->to_legacy_object($forumentity); 202 $course = $forumentity->get_course_record(); 203 $modcontext = $forumentity->get_context(); 204 $coursecontext = context_course::instance($course->id); 205 206 if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) { 207 print_error('invalidcoursemodule'); 208 } 209 210 // Ensure lang, theme, etc. is set up properly. MDL-6926. 211 $PAGE->set_cm($cm, $course, $forum); 212 213 if (!$capabilitymanager->can_reply_to_post($USER, $discussionentity, $parententity)) { 214 if (!isguestuser()) { 215 if (!is_enrolled($coursecontext)) { // User is a guest here! 216 $SESSION->wantsurl = qualified_me(); 217 $SESSION->enrolcancel = get_local_referer(false); 218 redirect(new moodle_url('/enrol/index.php', array('id' => $course->id, 219 'returnurl' => '/mod/forum/view.php?f=' . $forum->id)), 220 get_string('youneedtoenrol')); 221 } 222 223 // The forum has been locked. Just redirect back to the discussion page. 224 if (forum_discussion_is_locked($forum, $discussion)) { 225 redirect(new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id))); 226 } 227 } 228 print_error('nopostforum', 'forum'); 229 } 230 231 // Make sure user can post here. 232 if (isset($cm->groupmode) && empty($course->groupmodeforce)) { 233 $groupmode = $cm->groupmode; 234 } else { 235 $groupmode = $course->groupmode; 236 } 237 if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $modcontext)) { 238 if ($discussion->groupid == -1) { 239 print_error('nopostforum', 'forum'); 240 } else { 241 if (!groups_is_member($discussion->groupid)) { 242 print_error('nopostforum', 'forum'); 243 } 244 } 245 } 246 247 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $modcontext)) { 248 print_error("activityiscurrentlyhidden"); 249 } 250 251 if ($parententity->is_private_reply()) { 252 print_error('cannotreplytoprivatereply', 'forum'); 253 } 254 255 // We always are going to honor the preferred format. We are creating a new post. 256 $preferredformat = editors_get_preferred_format(); 257 258 // Only if there are prefilled contents coming. 259 if (!empty($prefilledpost)) { 260 // If the prefilled post is not HTML and the preferred format is HTML, convert to it. 261 if ($prefilledpostformat != FORMAT_HTML and $preferredformat == FORMAT_HTML) { 262 $prefilledpost = format_text($prefilledpost, $prefilledpostformat, ['context' => $modcontext]); 263 } 264 } 265 266 // Load up the $post variable. 267 $post = new stdClass(); 268 $post->course = $course->id; 269 $post->forum = $forum->id; 270 $post->discussion = $parent->discussion; 271 $post->parent = $parent->id; 272 $post->subject = $subject ? $subject : $parent->subject; 273 $post->userid = $USER->id; 274 $post->parentpostauthor = $parent->userid; 275 $post->message = $prefilledpost; 276 $post->messageformat = $preferredformat; 277 $post->isprivatereply = $prefilledprivatereply; 278 $canreplyprivately = $capabilitymanager->can_reply_privately_to_post($USER, $parententity); 279 280 $post->groupid = ($discussion->groupid == -1) ? 0 : $discussion->groupid; 281 282 $strre = get_string('re', 'forum'); 283 if (!(substr($post->subject, 0, strlen($strre)) == $strre)) { 284 $post->subject = $strre.' '.$post->subject; 285 } 286 287 // Unsetting this will allow the correct return URL to be calculated later. 288 unset($SESSION->fromdiscussion); 289 290 } else if (!empty($edit)) { 291 // User is editing their own post. 292 293 $postentity = $postvault->get_from_id($edit); 294 if (empty($postentity)) { 295 print_error('invalidpostid', 'forum'); 296 } 297 if ($postentity->has_parent()) { 298 $parententity = $postvault->get_from_id($postentity->get_parent_id()); 299 $parent = $postdatamapper->to_legacy_object($parententity); 300 } 301 302 $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id()); 303 if (empty($discussionentity)) { 304 print_error('notpartofdiscussion', 'forum'); 305 } 306 307 $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id()); 308 if (empty($forumentity)) { 309 print_error('invalidforumid', 'forum'); 310 } 311 312 $capabilitymanager = $managerfactory->get_capability_manager($forumentity); 313 $post = $postdatamapper->to_legacy_object($postentity); 314 $discussion = $discussiondatamapper->to_legacy_object($discussionentity); 315 $forum = $forumdatamapper->to_legacy_object($forumentity); 316 $course = $forumentity->get_course_record(); 317 $modcontext = $forumentity->get_context(); 318 $coursecontext = context_course::instance($course->id); 319 320 if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) { 321 print_error('invalidcoursemodule'); 322 } 323 324 $PAGE->set_cm($cm, $course, $forum); 325 326 if (!($forum->type == 'news' && !$post->parent && $discussion->timestart > time())) { 327 if (((time() - $post->created) > $CFG->maxeditingtime) and 328 !has_capability('mod/forum:editanypost', $modcontext)) { 329 print_error('maxtimehaspassed', 'forum', '', format_time($CFG->maxeditingtime)); 330 } 331 } 332 if (($post->userid <> $USER->id) and 333 !has_capability('mod/forum:editanypost', $modcontext)) { 334 print_error('cannoteditposts', 'forum'); 335 } 336 337 // Load up the $post variable. 338 $post->edit = $edit; 339 $post->course = $course->id; 340 $post->forum = $forum->id; 341 $post->groupid = ($discussion->groupid == -1) ? 0 : $discussion->groupid; 342 if ($postentity->has_parent()) { 343 $canreplyprivately = forum_user_can_reply_privately($modcontext, $parent); 344 } 345 346 $post = trusttext_pre_edit($post, 'message', $modcontext); 347 348 // Unsetting this will allow the correct return URL to be calculated later. 349 unset($SESSION->fromdiscussion); 350 351 } else if (!empty($delete)) { 352 // User is deleting a post. 353 354 $postentity = $postvault->get_from_id($delete); 355 if (empty($postentity)) { 356 print_error('invalidpostid', 'forum'); 357 } 358 359 $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id()); 360 if (empty($discussionentity)) { 361 print_error('notpartofdiscussion', 'forum'); 362 } 363 364 $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id()); 365 if (empty($forumentity)) { 366 print_error('invalidforumid', 'forum'); 367 } 368 369 $capabilitymanager = $managerfactory->get_capability_manager($forumentity); 370 $course = $forumentity->get_course_record(); 371 $cm = $forumentity->get_course_module_record(); 372 $modcontext = $forumentity->get_context(); 373 374 require_login($course, false, $cm); 375 376 $replycount = $postvault->get_reply_count_for_post_id_in_discussion_id( 377 $USER, $postentity->get_id(), $discussionentity->get_id(), true); 378 379 if (!empty($confirm) && confirm_sesskey()) { 380 // Do further checks and delete the post. 381 $hasreplies = $replycount > 0; 382 383 try { 384 $capabilitymanager->validate_delete_post($USER, $discussionentity, $postentity, $hasreplies); 385 386 if (!$postentity->has_parent()) { 387 forum_delete_discussion( 388 $discussiondatamapper->to_legacy_object($discussionentity), 389 false, 390 $forumentity->get_course_record(), 391 $forumentity->get_course_module_record(), 392 $forumdatamapper->to_legacy_object($forumentity) 393 ); 394 395 redirect( 396 $urlfactory->get_forum_view_url_from_forum($forumentity), 397 get_string('eventdiscussiondeleted', 'forum'), 398 null, 399 \core\output\notification::NOTIFY_SUCCESS 400 ); 401 } else { 402 forum_delete_post( 403 $postdatamapper->to_legacy_object($postentity), 404 has_capability('mod/forum:deleteanypost', $modcontext), 405 $forumentity->get_course_record(), 406 $forumentity->get_course_module_record(), 407 $forumdatamapper->to_legacy_object($forumentity) 408 ); 409 410 if ($forumentity->get_type() == 'single') { 411 // Single discussion forums are an exception. 412 // We show the forum itself since it only has one discussion thread. 413 $discussionurl = $urlfactory->get_forum_view_url_from_forum($forumentity); 414 } else { 415 $discussionurl = $urlfactory->get_discussion_view_url_from_discussion($discussionentity); 416 } 417 418 redirect( 419 forum_go_back_to($discussionurl), 420 get_string('eventpostdeleted', 'forum'), 421 null, 422 \core\output\notification::NOTIFY_SUCCESS 423 ); 424 } 425 } catch (Exception $e) { 426 redirect( 427 $urlfactory->get_discussion_view_url_from_discussion($discussionentity), 428 $e->getMessage(), 429 null, 430 \core\output\notification::NOTIFY_ERROR 431 ); 432 } 433 434 } else { 435 436 if (!$capabilitymanager->can_delete_post($USER, $discussionentity, $postentity)) { 437 redirect( 438 $urlfactory->get_discussion_view_url_from_discussion($discussionentity), 439 get_string('cannotdeletepost', 'forum'), 440 null, 441 \core\output\notification::NOTIFY_ERROR 442 ); 443 } 444 445 $post = $postdatamapper->to_legacy_object($postentity); 446 $forum = $forumdatamapper->to_legacy_object($forumentity); 447 448 // User just asked to delete something. 449 forum_set_return(); 450 $PAGE->navbar->add(get_string('delete', 'forum')); 451 $PAGE->set_title($course->shortname); 452 $PAGE->set_heading($course->fullname); 453 454 if ($replycount) { 455 if (!has_capability('mod/forum:deleteanypost', $modcontext)) { 456 redirect( 457 forum_go_back_to($urlfactory->get_view_post_url_from_post($postentity)), 458 get_string('couldnotdeletereplies', 'forum'), 459 null, 460 \core\output\notification::NOTIFY_ERROR 461 ); 462 } 463 464 echo $OUTPUT->header(); 465 echo $OUTPUT->heading(format_string($forum->name), 2); 466 echo $OUTPUT->confirm(get_string("deletesureplural", "forum", $replycount + 1), 467 "post.php?delete=$delete&confirm=$delete", 468 $CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#p'.$post->id); 469 470 $postentities = [$postentity]; 471 if (empty($post->edit)) { 472 $postvault = $vaultfactory->get_post_vault(); 473 $replies = $postvault->get_replies_to_post( 474 $USER, 475 $postentity, 476 // Note: All replies are fetched here as the user has deleteanypost. 477 true, 478 'created ASC' 479 ); 480 $postentities = array_merge($postentities, $replies); 481 } 482 483 $rendererfactory = mod_forum\local\container::get_renderer_factory(); 484 $postsrenderer = $rendererfactory->get_single_discussion_posts_renderer(FORUM_MODE_NESTED, true); 485 echo $postsrenderer->render($USER, [$forumentity], [$discussionentity], $postentities); 486 } else { 487 echo $OUTPUT->header(); 488 echo $OUTPUT->heading(format_string($forum->name), 2); 489 echo $OUTPUT->confirm(get_string("deletesure", "forum", $replycount), 490 "post.php?delete=$delete&confirm=$delete", 491 $CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#p'.$post->id); 492 493 $rendererfactory = mod_forum\local\container::get_renderer_factory(); 494 $postsrenderer = $rendererfactory->get_single_discussion_posts_renderer(null, true); 495 echo $postsrenderer->render($USER, [$forumentity], [$discussionentity], [$postentity]); 496 } 497 498 } 499 echo $OUTPUT->footer(); 500 die; 501 502 } else if (!empty($prune)) { 503 // Pruning. 504 505 $postentity = $postvault->get_from_id($prune); 506 if (empty($postentity)) { 507 print_error('invalidpostid', 'forum'); 508 } 509 510 $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id()); 511 if (empty($discussionentity)) { 512 print_error('notpartofdiscussion', 'forum'); 513 } 514 515 $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id()); 516 if (empty($forumentity)) { 517 print_error('invalidforumid', 'forum'); 518 } 519 520 $capabilitymanager = $managerfactory->get_capability_manager($forumentity); 521 $post = $postdatamapper->to_legacy_object($postentity); 522 $discussion = $discussiondatamapper->to_legacy_object($discussionentity); 523 $forum = $forumdatamapper->to_legacy_object($forumentity); 524 $course = $forumentity->get_course_record(); 525 $modcontext = $forumentity->get_context(); 526 $coursecontext = context_course::instance($course->id); 527 528 if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) { 529 print_error('invalidcoursemodule'); 530 } 531 532 if (!$postentity->has_parent()) { 533 redirect( 534 $urlfactory->get_discussion_view_url_from_discussion($discussionentity), 535 get_string('alreadyfirstpost', 'forum'), 536 null, 537 \core\output\notification::NOTIFY_ERROR 538 ); 539 } 540 if (!$capabilitymanager->can_split_post($USER, $discussionentity, $postentity)) { 541 redirect( 542 $urlfactory->get_discussion_view_url_from_discussion($discussionentity), 543 get_string('cannotsplit', 'forum'), 544 null, 545 \core\output\notification::NOTIFY_ERROR 546 ); 547 } 548 549 $PAGE->set_cm($cm); 550 $PAGE->set_context($modcontext); 551 552 $prunemform = new mod_forum_prune_form(null, array('prune' => $prune, 'confirm' => $prune)); 553 554 if ($prunemform->is_cancelled()) { 555 redirect(forum_go_back_to($urlfactory->get_discussion_view_url_from_discussion($discussionentity))); 556 } else if ($fromform = $prunemform->get_data()) { 557 // User submits the data. 558 $newdiscussion = new stdClass(); 559 $newdiscussion->course = $discussion->course; 560 $newdiscussion->forum = $discussion->forum; 561 $newdiscussion->name = $name; 562 $newdiscussion->firstpost = $post->id; 563 $newdiscussion->userid = $post->userid; 564 $newdiscussion->groupid = $discussion->groupid; 565 $newdiscussion->assessed = $discussion->assessed; 566 $newdiscussion->usermodified = $post->userid; 567 $newdiscussion->timestart = $discussion->timestart; 568 $newdiscussion->timeend = $discussion->timeend; 569 570 $newid = $DB->insert_record('forum_discussions', $newdiscussion); 571 572 $newpost = new stdClass(); 573 $newpost->id = $post->id; 574 $newpost->parent = 0; 575 $newpost->subject = $name; 576 577 $DB->update_record("forum_posts", $newpost); 578 $postentity = $postvault->get_from_id($postentity->get_id()); 579 580 forum_change_discussionid($post->id, $newid); 581 582 // Update last post in each discussion. 583 forum_discussion_update_last_post($discussion->id); 584 forum_discussion_update_last_post($newid); 585 586 // Fire events to reflect the split.. 587 $params = array( 588 'context' => $modcontext, 589 'objectid' => $discussion->id, 590 'other' => array( 591 'forumid' => $forum->id, 592 ) 593 ); 594 $event = \mod_forum\event\discussion_updated::create($params); 595 $event->trigger(); 596 597 $params = array( 598 'context' => $modcontext, 599 'objectid' => $newid, 600 'other' => array( 601 'forumid' => $forum->id, 602 ) 603 ); 604 $event = \mod_forum\event\discussion_created::create($params); 605 $event->trigger(); 606 607 $params = array( 608 'context' => $modcontext, 609 'objectid' => $post->id, 610 'other' => array( 611 'discussionid' => $newid, 612 'forumid' => $forum->id, 613 'forumtype' => $forum->type, 614 ) 615 ); 616 $event = \mod_forum\event\post_updated::create($params); 617 $event->add_record_snapshot('forum_discussions', $discussion); 618 $event->trigger(); 619 620 redirect( 621 forum_go_back_to($urlfactory->get_discussion_view_url_from_post($postentity)), 622 get_string('discussionsplit', 'forum'), 623 null, 624 \core\output\notification::NOTIFY_SUCCESS 625 ); 626 } else { 627 // Display the prune form. 628 $course = $DB->get_record('course', array('id' => $forum->course)); 629 $subjectstr = format_string($post->subject, true); 630 $PAGE->navbar->add($subjectstr, new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id))); 631 $PAGE->navbar->add(get_string("prune", "forum")); 632 $PAGE->set_title(format_string($discussion->name).": ".format_string($post->subject)); 633 $PAGE->set_heading($course->fullname); 634 echo $OUTPUT->header(); 635 echo $OUTPUT->heading(format_string($forum->name), 2); 636 echo $OUTPUT->heading(get_string('pruneheading', 'forum'), 3); 637 638 $prunemform->display(); 639 640 $postentity = $entityfactory->get_post_from_stdclass($post); 641 $discussionentity = $entityfactory->get_discussion_from_stdclass($discussion); 642 $forumentity = $entityfactory->get_forum_from_stdclass($forum, $modcontext, $cm, $course); 643 $rendererfactory = mod_forum\local\container::get_renderer_factory(); 644 $postsrenderer = $rendererfactory->get_single_discussion_posts_renderer(null, true); 645 echo $postsrenderer->render($USER, [$forumentity], [$discussionentity], [$postentity]); 646 } 647 648 echo $OUTPUT->footer(); 649 die; 650 } else { 651 print_error('unknowaction'); 652 653 } 654 655 // From now on user must be logged on properly. 656 657 require_login($course, false, $cm); 658 659 if (isguestuser()) { 660 // Just in case. 661 print_error('noguest'); 662 } 663 664 $thresholdwarning = forum_check_throttling($forum, $cm); 665 $mformpost = new mod_forum_post_form('post.php', [ 666 'course' => $course, 667 'cm' => $cm, 668 'coursecontext' => $coursecontext, 669 'modcontext' => $modcontext, 670 'forum' => $forum, 671 'post' => $post, 672 'subscribe' => \mod_forum\subscriptions::is_subscribed($USER->id, $forum, null, $cm), 673 'thresholdwarning' => $thresholdwarning, 674 'edit' => $edit, 675 'canreplyprivately' => $canreplyprivately, 676 ], 'post', '', array('id' => 'mformforum')); 677 678 $draftitemid = file_get_submitted_draft_itemid('attachments'); 679 $postid = empty($post->id) ? null : $post->id; 680 $attachoptions = mod_forum_post_form::attachment_options($forum); 681 file_prepare_draft_area($draftitemid, $modcontext->id, 'mod_forum', 'attachment', $postid, $attachoptions); 682 683 // Load data into form NOW! 684 685 if ($USER->id != $post->userid) { // Not the original author, so add a message to the end. 686 $data = new stdClass(); 687 $data->date = userdate($post->created); 688 if ($post->messageformat == FORMAT_HTML) { 689 $data->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$USER->id.'&course='.$post->course.'">'. 690 fullname($USER).'</a>'; 691 $post->message .= '<p><span class="edited">('.get_string('editedby', 'forum', $data).')</span></p>'; 692 } else { 693 $data->name = fullname($USER); 694 $post->message .= "\n\n(".get_string('editedby', 'forum', $data).')'; 695 } 696 unset($data); 697 } 698 699 $formheading = ''; 700 if (!empty($parent)) { 701 $heading = get_string("yourreply", "forum"); 702 $formheading = get_string('reply', 'forum'); 703 } else { 704 if ($forum->type == 'qanda') { 705 $heading = get_string('yournewquestion', 'forum'); 706 } else { 707 $heading = get_string('yournewtopic', 'forum'); 708 } 709 } 710 711 $postid = empty($post->id) ? null : $post->id; 712 $draftideditor = file_get_submitted_draft_itemid('message'); 713 $editoropts = mod_forum_post_form::editor_options($modcontext, $postid); 714 $currenttext = file_prepare_draft_area($draftideditor, $modcontext->id, 'mod_forum', 'post', $postid, $editoropts, $post->message); 715 $discussionid = isset($discussion) ? $discussion->id : null; 716 $discussionsubscribe = \mod_forum\subscriptions::get_user_default_subscription($forum, $coursecontext, $cm, $discussionid); 717 718 $mformpost->set_data( 719 array( 720 'attachments' => $draftitemid, 721 'general' => $heading, 722 'subject' => $post->subject, 723 'message' => array( 724 'text' => $currenttext, 725 'format' => !isset($post->messageformat) || !is_numeric($post->messageformat) ? 726 editors_get_preferred_format() : $post->messageformat, 727 'itemid' => $draftideditor 728 ), 729 'discussionsubscribe' => $discussionsubscribe, 730 'mailnow' => !empty($post->mailnow), 731 'userid' => $post->userid, 732 'parent' => $post->parent, 733 'discussion' => $post->discussion, 734 'course' => $course->id, 735 'isprivatereply' => $post->isprivatereply ?? false 736 ) + 737 738 $pageparams + 739 740 (isset($post->format) ? array('format' => $post->format) : array()) + 741 742 (isset($discussion->timestart) ? array('timestart' => $discussion->timestart) : array()) + 743 744 (isset($discussion->timeend) ? array('timeend' => $discussion->timeend) : array()) + 745 746 (isset($discussion->pinned) ? array('pinned' => $discussion->pinned) : array()) + 747 748 (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) + 749 750 (isset($discussion->id) ? array('discussion' => $discussion->id) : array()) 751 ); 752 753 // If we are being redirected via a no_submit_button press OR if the message is being prefilled. 754 // then set the initial 'dirty' state. 755 // - A prefilled post will exist when being redirected from the inpage reply form. 756 // - A no_submit_button press occurs when being redirected from the inpage add new discussion post form. 757 $dirty = $prefilledpost ? true : false; 758 if ($mformpost->no_submit_button_pressed()) { 759 $data = $mformpost->get_submitted_data(); 760 761 // If a no submit button has been pressed but the default values haven't been then reset the form change. 762 if (!$dirty && isset($data->message['text']) && !empty(trim($data->message['text']))) { 763 $dirty = true; 764 } 765 766 if (!$dirty && isset($data->message['message']) && !empty(trim($data->message['message']))) { 767 $dirty = true; 768 } 769 } 770 $mformpost->set_initial_dirty_state($dirty); 771 772 if ($mformpost->is_cancelled()) { 773 if (!isset($discussion->id) || $forum->type === 'single') { 774 // Single forums don't have a discussion page. 775 redirect($urlfactory->get_forum_view_url_from_forum($forumentity)); 776 } else { 777 redirect($urlfactory->get_discussion_view_url_from_discussion($discussionentity)); 778 } 779 } else if ($mformpost->is_submitted() && !$mformpost->no_submit_button_pressed() && $fromform = $mformpost->get_data()) { 780 781 $errordestination = get_local_referer(false) ?: $urlfactory->get_forum_view_url_from_forum($forumentity); 782 783 $fromform->itemid = $fromform->message['itemid']; 784 $fromform->messageformat = $fromform->message['format']; 785 $fromform->message = $fromform->message['text']; 786 // WARNING: the $fromform->message array has been overwritten, do not use it anymore! 787 $fromform->messagetrust = trusttext_trusted($modcontext); 788 789 // Clean message text. 790 $fromform = trusttext_pre_edit($fromform, 'message', $modcontext); 791 792 if ($fromform->edit) { 793 // Updating a post. 794 unset($fromform->groupid); 795 $fromform->id = $fromform->edit; 796 $message = ''; 797 798 if (!$capabilitymanager->can_edit_post($USER, $discussionentity, $postentity)) { 799 redirect( 800 $urlfactory->get_view_post_url_from_post($postentity), 801 get_string('cannotupdatepost', 'forum'), 802 null, 803 \core\output\notification::ERROR 804 ); 805 } 806 807 if (isset($fromform->groupinfo) && $capabilitymanager->can_move_discussions($USER)) { 808 // If the user has access to all groups and they are changing the group, then update the post. 809 if (empty($fromform->groupinfo)) { 810 $fromform->groupinfo = -1; 811 } 812 813 if (!$capabilitymanager->can_create_discussions($USER, $fromform->groupinfo)) { 814 redirect( 815 $urlfactory->get_view_post_url_from_post($postentity), 816 get_string('cannotupdatepost', 'forum'), 817 null, 818 \core\output\notification::ERROR 819 ); 820 } 821 822 if ($discussionentity->get_group_id() != $fromform->groupinfo) { 823 $DB->set_field('forum_discussions', 'groupid', $fromform->groupinfo, array('firstpost' => $fromform->id)); 824 } 825 } 826 827 // When editing first post/discussion. 828 if (!$postentity->has_parent()) { 829 if ($capabilitymanager->can_pin_discussions($USER)) { 830 // Can change pinned if we have capability. 831 $fromform->pinned = !empty($fromform->pinned) ? FORUM_DISCUSSION_PINNED : FORUM_DISCUSSION_UNPINNED; 832 } else { 833 // We don't have the capability to change so keep to previous value. 834 unset($fromform->pinned); 835 } 836 } 837 $updatepost = $fromform; 838 $updatepost->forum = $forum->id; 839 if (!forum_update_post($updatepost, $mformpost)) { 840 print_error("couldnotupdate", "forum", $errordestination); 841 } 842 843 forum_trigger_post_updated_event($post, $discussion, $modcontext, $forum); 844 845 if ($USER->id === $postentity->get_author_id()) { 846 $message .= get_string("postupdated", "forum"); 847 } else { 848 $realuser = \core_user::get_user($postentity->get_author_id()); 849 $message .= get_string("editedpostupdated", "forum", fullname($realuser)); 850 } 851 852 $subscribemessage = forum_post_subscription($fromform, $forum, $discussion); 853 if ('single' == $forumentity->get_type()) { 854 // Single discussion forums are an exception. 855 // We show the forum itself since it only has one discussion thread. 856 $discussionurl = $urlfactory->get_forum_view_url_from_forum($forumentity); 857 } else { 858 $discussionurl = $urlfactory->get_view_post_url_from_post($postentity); 859 } 860 861 redirect( 862 forum_go_back_to($discussionurl), 863 $message . $subscribemessage, 864 null, 865 \core\output\notification::NOTIFY_SUCCESS 866 ); 867 868 } else if ($fromform->discussion) { 869 // Adding a new post to an existing discussion 870 // Before we add this we must check that the user will not exceed the blocking threshold. 871 forum_check_blocking_threshold($thresholdwarning); 872 873 unset($fromform->groupid); 874 $message = ''; 875 $addpost = $fromform; 876 $addpost->forum = $forum->id; 877 if ($fromform->id = forum_add_new_post($addpost, $mformpost)) { 878 $postentity = $postvault->get_from_id($fromform->id); 879 $fromform->deleted = 0; 880 $subscribemessage = forum_post_subscription($fromform, $forum, $discussion); 881 882 if (!empty($fromform->mailnow)) { 883 $message .= get_string("postmailnow", "forum"); 884 } else { 885 $message .= '<p>'.get_string("postaddedsuccess", "forum") . '</p>'; 886 $message .= '<p>'.get_string("postaddedtimeleft", "forum", format_time($CFG->maxeditingtime)) . '</p>'; 887 } 888 889 if ($forum->type == 'single') { 890 // Single discussion forums are an exception. 891 // We show the forum itself since it only has one discussion thread. 892 $discussionurl = $urlfactory->get_forum_view_url_from_forum($forumentity); 893 } else { 894 $discussionurl = $urlfactory->get_view_post_url_from_post($postentity); 895 } 896 897 $params = array( 898 'context' => $modcontext, 899 'objectid' => $fromform->id, 900 'other' => array( 901 'discussionid' => $discussion->id, 902 'forumid' => $forum->id, 903 'forumtype' => $forum->type, 904 ) 905 ); 906 $event = \mod_forum\event\post_created::create($params); 907 $event->add_record_snapshot('forum_posts', $fromform); 908 $event->add_record_snapshot('forum_discussions', $discussion); 909 $event->trigger(); 910 911 // Update completion state. 912 $completion = new completion_info($course); 913 if ($completion->is_enabled($cm) && 914 ($forum->completionreplies || $forum->completionposts)) { 915 $completion->update_state($cm, COMPLETION_COMPLETE); 916 } 917 918 redirect( 919 forum_go_back_to($discussionurl), 920 $message . $subscribemessage, 921 null, 922 \core\output\notification::NOTIFY_SUCCESS 923 ); 924 925 } else { 926 print_error("couldnotadd", "forum", $errordestination); 927 } 928 exit; 929 930 } else { 931 // Adding a new discussion. 932 // The location to redirect to after successfully posting. 933 $redirectto = new moodle_url('/mod/forum/view.php', array('f' => $fromform->forum)); 934 935 $fromform->mailnow = empty($fromform->mailnow) ? 0 : 1; 936 937 $discussion = $fromform; 938 $discussion->name = $fromform->subject; 939 $discussion->timelocked = 0; 940 941 $newstopic = false; 942 if ($forum->type == 'news' && !$fromform->parent) { 943 $newstopic = true; 944 } 945 946 if (!empty($fromform->pinned) && $capabilitymanager->can_pin_discussions($USER)) { 947 $discussion->pinned = FORUM_DISCUSSION_PINNED; 948 } else { 949 $discussion->pinned = FORUM_DISCUSSION_UNPINNED; 950 } 951 952 $allowedgroups = array(); 953 $groupstopostto = array(); 954 955 // If we are posting a copy to all groups the user has access to. 956 if (isset($fromform->posttomygroups)) { 957 // Post to each of my groups. 958 require_capability('mod/forum:canposttomygroups', $modcontext); 959 960 // Fetch all of this user's groups. 961 // Note: all groups are returned when in visible groups mode so we must manually filter. 962 $allowedgroups = groups_get_activity_allowed_groups($cm); 963 foreach ($allowedgroups as $groupid => $group) { 964 if ($capabilitymanager->can_create_discussions($USER, $groupid)) { 965 $groupstopostto[] = $groupid; 966 } 967 } 968 } else if (isset($fromform->groupinfo)) { 969 // Use the value provided in the dropdown group selection. 970 $groupstopostto[] = $fromform->groupinfo; 971 $redirectto->param('group', $fromform->groupinfo); 972 } else if (isset($fromform->groupid) && !empty($fromform->groupid)) { 973 // Use the value provided in the hidden form element instead. 974 $groupstopostto[] = $fromform->groupid; 975 $redirectto->param('group', $fromform->groupid); 976 } else { 977 // Use the value for all participants instead. 978 $groupstopostto[] = -1; 979 } 980 981 // Before we post this we must check that the user will not exceed the blocking threshold. 982 forum_check_blocking_threshold($thresholdwarning); 983 984 foreach ($groupstopostto as $group) { 985 if (!$capabilitymanager->can_create_discussions($USER, $groupid)) { 986 print_error('cannotcreatediscussion', 'forum'); 987 } 988 989 $discussion->groupid = $group; 990 $message = ''; 991 if ($discussion->id = forum_add_discussion($discussion, $mformpost)) { 992 993 $params = array( 994 'context' => $modcontext, 995 'objectid' => $discussion->id, 996 'other' => array( 997 'forumid' => $forum->id, 998 ) 999 ); 1000 $event = \mod_forum\event\discussion_created::create($params); 1001 $event->add_record_snapshot('forum_discussions', $discussion); 1002 $event->trigger(); 1003 1004 if ($fromform->mailnow) { 1005 $message .= get_string("postmailnow", "forum"); 1006 } else { 1007 $message .= '<p>'.get_string("postaddedsuccess", "forum") . '</p>'; 1008 $message .= '<p>'.get_string("postaddedtimeleft", "forum", format_time($CFG->maxeditingtime)) . '</p>'; 1009 } 1010 1011 $subscribemessage = forum_post_subscription($fromform, $forum, $discussion); 1012 } else { 1013 print_error("couldnotadd", "forum", $errordestination); 1014 } 1015 } 1016 1017 // Update completion status. 1018 $completion = new completion_info($course); 1019 if ($completion->is_enabled($cm) && 1020 ($forum->completiondiscussions || $forum->completionposts)) { 1021 $completion->update_state($cm, COMPLETION_COMPLETE); 1022 } 1023 1024 // Redirect back to the discussion. 1025 redirect( 1026 forum_go_back_to($redirectto->out()), 1027 $message . $subscribemessage, 1028 null, 1029 \core\output\notification::NOTIFY_SUCCESS 1030 ); 1031 } 1032 } 1033 1034 1035 // This section is only shown after all checks are in place, and the forumentity and any relevant discussion and post 1036 // entity are available. 1037 1038 if (!empty($discussionentity)) { 1039 $titlesubject = format_string($discussionentity->get_name(), true); 1040 } else if ('news' == $forumentity->get_type()) { 1041 $titlesubject = get_string("addanewtopic", "forum"); 1042 } else { 1043 $titlesubject = get_string("addanewdiscussion", "forum"); 1044 } 1045 1046 if (empty($post->edit)) { 1047 $post->edit = ''; 1048 } 1049 1050 if (empty($discussion->name)) { 1051 if (empty($discussion)) { 1052 $discussion = new stdClass(); 1053 } 1054 $discussion->name = $forum->name; 1055 } 1056 1057 $strdiscussionname = ''; 1058 if ('single' == $forumentity->get_type()) { 1059 // There is only one discussion thread for this forum type. We should 1060 // not show the discussion name (same as forum name in this case) in 1061 // the breadcrumbs. 1062 $strdiscussionname = ''; 1063 } else if (!empty($discussionentity)) { 1064 // Show the discussion name in the breadcrumbs. 1065 $strdiscussionname = format_string($discussionentity->get_name()) . ': '; 1066 } 1067 1068 $forcefocus = empty($reply) ? null : 'message'; 1069 1070 if (!empty($discussion->id)) { 1071 $PAGE->navbar->add($titlesubject, $urlfactory->get_discussion_view_url_from_discussion($discussionentity)); 1072 } 1073 1074 if ($post->parent) { 1075 $PAGE->navbar->add(get_string('reply', 'forum')); 1076 } 1077 1078 if ($edit) { 1079 $PAGE->navbar->add(get_string('edit', 'forum')); 1080 } 1081 1082 $PAGE->set_title("{$course->shortname}: {$strdiscussionname}{$titlesubject}"); 1083 $PAGE->set_heading($course->fullname); 1084 1085 echo $OUTPUT->header(); 1086 echo $OUTPUT->heading(format_string($forum->name), 2); 1087 1088 // Checkup. 1089 if (!empty($parententity) && !$capabilitymanager->can_view_post($USER, $discussionentity, $parententity)) { 1090 print_error('cannotreply', 'forum'); 1091 } 1092 1093 if (empty($parententity) && empty($edit) && !$capabilitymanager->can_create_discussions($USER, $groupid)) { 1094 print_error('cannotcreatediscussion', 'forum'); 1095 } 1096 1097 if (!empty($discussionentity) && 'qanda' == $forumentity->get_type()) { 1098 $displaywarning = $capabilitymanager->must_post_before_viewing_discussion($USER, $discussionentity); 1099 $displaywarning = $displaywarning && !forum_user_has_posted($forumentity->get_id(), $discussionentity->get_id(), $USER->id); 1100 if ($displaywarning) { 1101 echo $OUTPUT->notification(get_string('qandanotify', 'forum')); 1102 } 1103 } 1104 1105 // If there is a warning message and we are not editing a post we need to handle the warning. 1106 if (!empty($thresholdwarning) && !$edit) { 1107 // Here we want to throw an exception if they are no longer allowed to post. 1108 forum_check_blocking_threshold($thresholdwarning); 1109 } 1110 1111 if (!empty($parententity)) { 1112 $postentities = [$parententity]; 1113 1114 if (empty($post->edit)) { 1115 if ('qanda' != $forumentity->get_type() || forum_user_can_see_discussion($forum, $discussion, $modcontext)) { 1116 $replies = $postvault->get_replies_to_post( 1117 $USER, 1118 $parententity, 1119 $capabilitymanager->can_view_any_private_reply($USER), 1120 'created ASC' 1121 ); 1122 $postentities = array_merge($postentities, $replies); 1123 } 1124 } 1125 1126 $rendererfactory = mod_forum\local\container::get_renderer_factory(); 1127 $postsrenderer = $rendererfactory->get_single_discussion_posts_renderer(FORUM_MODE_THREADED, true); 1128 echo $postsrenderer->render($USER, [$forumentity], [$discussionentity], $postentities); 1129 } else { 1130 if (!empty($forum->intro)) { 1131 echo $OUTPUT->box(format_module_intro('forum', $forum, $cm->id), 'generalbox', 'intro'); 1132 } 1133 } 1134 1135 // Call print disclosure for enabled plagiarism plugins. 1136 if (!empty($CFG->enableplagiarism)) { 1137 require_once($CFG->libdir.'/plagiarismlib.php'); 1138 echo plagiarism_print_disclosure($cm->id); 1139 } 1140 1141 if (!empty($formheading)) { 1142 echo $OUTPUT->heading($formheading, 2, array('class' => 'accesshide')); 1143 } 1144 1145 if (!empty($postentity)) { 1146 $data = (object) [ 1147 'tags' => core_tag_tag::get_item_tags_array('mod_forum', 'forum_posts', $postentity->get_id()) 1148 ]; 1149 $mformpost->set_data($data); 1150 } 1151 1152 $mformpost->display(); 1153 1154 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body