function finish($postid, $cloneid, $url, $fromform, $uploadfolder, $ajaxdata = '')
{
    // Clear out used playspace and/or uploadfolder
    if (isset($fromform->attachmentplayspace)) {
        // Unless we're keeping it, wipe the playspace
        forum::delete_attachment_playspace($fromform->attachmentplayspace, optional_param('keepplayspace', 0, PARAM_INT));
    }
    // Get rid of temporary upload folder
    if ($uploadfolder) {
        remove_dir($uploadfolder);
    }
    global $ajax;
    if ($ajax) {
        if ($ajaxdata) {
            // Print AJAX data if specified
            header('Content-Type: text/plain');
            print $ajaxdata;
            exit;
        } else {
            // Default otherwise is to print post
            forum_post::print_for_ajax_and_exit($postid, $cloneid, array(forum_post::OPTION_DISCUSSION_SUBJECT => true));
        }
    }
    redirect($url);
}
function make_post($discussion, &$allposts, &$userids, $ratingpercent)
{
    // Make reply
    static $index = 0;
    $index++;
    $replyto = $allposts[rand(0, count($allposts) - 1)];
    $newpostid = $replyto->reply(my_random_percentage(25) ? 'Reply ' . $index : null, get_post_text(), FORMAT_HTML, array(), false, $userids[mt_rand(0, count($userids) - 1)], false);
    $newpost = forum_post::get_from_id($newpostid, forum::CLONE_DIRECT);
    $allposts[] = $newpost;
    // Add ratings
    for ($i = 0; $i < count($userids); $i++) {
        if (my_random_percentage($ratingpercent)) {
            $newpost->rate(2, $userids[$i]);
        }
    }
}
<?php

require_once '../../config.php';
require_once 'forum.php';
if (class_exists('ouflags')) {
    require_once '../../local/mobile/ou_lib.php';
    global $OUMOBILESUPPORT;
    $OUMOBILESUPPORT = true;
    ou_set_is_mobile(ou_get_is_mobile_from_cookies());
}
// Post ID
$postid = required_param('p', PARAM_INT);
$cloneid = optional_param('clone', 0, PARAM_INT);
try {
    // Get post
    $post = forum_post::get_from_id($postid, $cloneid, true);
    // Get convenience variables
    $discussion = $post->get_discussion();
    $forum = $post->get_forum();
    $course = $forum->get_course();
    $cm = $forum->get_course_module();
    // Do all access security checks
    $post->require_view();
    if (!$post->can_view_history($whynot)) {
        print_error($whynot, 'forumng');
    }
    // Work out navigation for header
    $pagename = get_string('historypage', 'forumng', $post->get_effective_subject(true));
    $navigation = array();
    $navigation[] = array('name' => shorten_text(htmlspecialchars($discussion->get_subject())), 'link' => $discussion->get_url(), 'type' => 'forumng');
    $navigation[] = array('name' => $pagename, 'type' => 'forumng');
 /**
  * Display a post. This method is used for:
  * - The normal HTML display of a post
  * - HTML email of a post
  * - Text-only email of a post
  * These are all combined in one method since ordinarily they change at
  * the same time (i.e. if adding/hiding information it is usually added to
  * or hidden from all views).
  *
  * $options is an associative array from a forum_post::OPTION_xx constant.
  * All available options are always set - if they were not set by
  * the user, they will have been set to false before this call happens,
  * so there is no need to use empty() or isset().
  *
  * Options are as follows. These are available in email mode:
  *
  * OPTION_TIME_ZONE (int) - Moodle time zone
  * OPTION_VIEW_FULL_NAMES (bool) - If user is allowed to see full names
  * OPTION_EMAIL (bool) - True if this is an email (false = standard view)
  * OPTION_DIGEST (bool) - True if this is part of an email digest
  * OPTION_COMMAND_REPLY (bool) - True if 'Reply' link should be displayed
  *   (available in email too)
  *
  * These options only apply in non-email usage:
  *
  * OPTION_SUMMARY (bool) - True if the entire post should not be displayed,
  *   only a short summary
  * OPTION_NO_COMMANDS (bool) - True if this post is being printed on its own
  * OPTION_COMMAND_EDIT (bool) - Display 'Edit' command
  * OPTION_COMMAND_DELETE (bool) - Display 'Edit' command
  * OPTION_COMMAND_SPLIT (bool) - Display 'Split' command
  * OPTION_RATINGS_VIEW (bool) - True to display current ratings
  * OPTION_RATINGS_EDIT (bool) - True to display ratings edit combo
  * OPTION_LEAVE_DIV_OPEN (bool) - True to not close post div (means that
  *   child posts can be added within).
  * OPTION_EXPANDED (bool) - True to show full post, otherwise abbreviate
  * OPTION_DISCUSSION_SUBJECT (bool) - If true, and only IF post is a 
  *   discussion root, includes subject (HTML, shortened as it would be for
  *   header display) as a hidden field.
  *
  * @param forum_post $post Post object
  * @param bool $html True if using HTML, false to output in plain text
  * @param array $options Associative array of name=>option, as above
  * @return string HTML or text of post
  */
 public function display_post($post, $html, $options)
 {
     global $CFG, $USER, $THEME;
     $discussion = $post->get_discussion();
     $expanded = $options[forum_post::OPTION_EXPANDED];
     $export = $options[forum_post::OPTION_EXPORT];
     $email = $options[forum_post::OPTION_EMAIL];
     // When posts are deleted we hide a lot of info - except when the person
     // viewing it has the ability to view deleted posts.
     $deletedhide = $post->get_deleted() && !$options[forum_post::OPTION_VIEW_DELETED_INFO];
     // Hide deleted messages if they have no replies
     if ($deletedhide && !$email && !$post->has_children()) {
         // note: !email check is to deal with posts that are deleted
         // between when the mail list finds them, and when it sends out
         // mail. It would be confusing to send out a blank email so let's
         // not do that. Also, ->has_children() is not safe to call during
         // email processing because it doesn't load the whole discussion.
         return '';
     }
     // Save some bandwidth by not sending link full paths except in emails
     if ($options[forum_post::OPTION_FULL_ADDRESSES]) {
         $linkprefix = $CFG->wwwroot . '/mod/forumng/';
     } else {
         $linkprefix = '';
     }
     $postnumber = ($options[forum_post::OPTION_NO_COMMANDS] || $email) && !$options[forum_post::OPTION_VISIBLE_POST_NUMBERS] ? '' : $post->get_number();
     $lf = "\n";
     // Initialise result
     $out = '';
     if ($html) {
         if ($export) {
             $out .= '<hr />';
         }
         // Basic intro
         $classes = $expanded ? ' forumng-full' : ' forumng-short';
         $classes .= $post->is_important() ? ' forumng-important' : '';
         $classes .= !$email && !$options[forum_post::OPTION_UNREAD_NOT_HIGHLIGHTED] && $post->is_unread() ? ' forumng-unread' : ' forumng-read';
         $classes .= $post->get_deleted() ? ' forumng-deleted' : '';
         $classes .= ' forumng-p' . $postnumber;
         $out .= $lf . '<div class="forumng-post' . $classes . '"><a id="p' . $post->get_id() . '"></a>';
         if ($options[forum_post::OPTION_FIRST_UNREAD]) {
             $out .= '<a id="firstunread"></a>';
         }
         // Theme hooks
         if (!empty($THEME->forumng_post_hooks)) {
             for ($i = 1; $i <= $THEME->forumng_post_hooks; $i++) {
                 $out .= '<div class="forumng-' . $i . '"></div>';
             }
         }
     }
     if ($html || $options[forum_post::OPTION_VISIBLE_POST_NUMBERS]) {
         // Accessible text giving post a number so we can make links unique
         // etc.
         if ($postnumber) {
             $data = new stdClass();
             $data->num = $postnumber;
             if ($post->get_parent()) {
                 if ($html) {
                     $data->parent = '<a class="forumng-parentlink" href="#p' . $post->get_parent()->get_id() . '">' . $post->get_parent()->get_number() . '</a>';
                 } else {
                     $data->parent = $post->get_parent()->get_number();
                 }
                 $data->info = '';
                 if ($post->is_unread()) {
                     $data->info = get_string('postinfo_unread', 'forumng');
                 }
                 if (!$expanded) {
                     $data->info .= ' ' . get_string('postinfo_short', 'forumng');
                 }
                 if ($post->get_deleted()) {
                     $data->info .= ' ' . get_string('postinfo_deleted', 'forumng');
                 }
                 $data->info = trim($data->info);
                 if ($data->info) {
                     $data->info = ' (' . $data->info . ')';
                 }
                 $info = get_string('postnumreply', 'forumng', $data);
             } else {
                 $info = get_string('postnum', 'forumng', $data);
             }
             if ($options[forum_post::OPTION_VISIBLE_POST_NUMBERS]) {
                 if (!$html) {
                     $out .= "## " . $info . "\n";
                 }
             }
         }
     }
     // Discussion subject (root only)
     if ($options[forum_post::OPTION_DISCUSSION_SUBJECT] && $post->is_root_post()) {
         $out .= '<input type="hidden" name="discussion_subject" value="' . shorten_text(htmlspecialchars($post->get_subject())) . '" />';
     }
     // Pictures (HTML version only)
     if ($html && !$export && $options[forum_post::OPTION_USER_IMAGE]) {
         $out .= $lf . '<div class="forumng-pic">';
         // User picture
         $out .= $deletedhide ? '' : $post->display_user_picture();
         // Group pictures if any - only for expanded version
         if ($expanded) {
             $grouppics = $post->display_group_pictures();
             if ($grouppics) {
                 $out .= '<div class="forumng-grouppicss">' . $grouppics . '</div>';
             }
         }
         $out .= '</div>';
     }
     // Link used to expand post
     $expandlink = '';
     if (!$expanded && !$deletedhide) {
         $expandlink = '&nbsp;[<a class="forumng-expandlink" ' . 'href="' . $linkprefix . 'discuss.php?' . $discussion->get_link_params(forum::PARAM_HTML) . '&amp;expand=1#p' . $post->get_id() . '">' . get_string('expandall', 'forumng') . '</a>] <img src="' . $CFG->pixpath . '/spacer.gif" width="16" height="16" alt="" />';
     }
     // Byline
     $by = new stdClass();
     $by->name = $deletedhide ? '' : fullname($post->get_user(), $options[forum_post::OPTION_VIEW_FULL_NAMES]);
     $by->date = $deletedhide ? '' : userdate($post->get_created(), get_string('strftimedatetime', 'langconfig'), $options[forum_post::OPTION_TIME_ZONE]);
     if ($html) {
         $out .= $lf . '<div class="forumng-info"><h2 class="forumng-author">';
         $out .= $post->is_important() ? '<img src="' . $CFG->modpixpath . '/forumng/exclamation_mark.gif" alt="' . get_string('important', 'forumng') . '" ' . 'title = "' . get_string('important', 'forumng') . '"/>' : '';
         if ($export) {
             $out .= $by->name;
         } else {
             $out .= '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $post->get_user()->id . ($post->get_forum()->is_shared() ? '' : '&amp;course=' . $post->get_forum()->get_course_id()) . '">' . $by->name . '</a>';
         }
         if ($postnumber) {
             if ($options[forum_post::OPTION_VISIBLE_POST_NUMBERS]) {
                 $out .= '<span class="accesshide" style="position:static"> ' . $info . ' </span>';
             } else {
                 $out .= '<span class="accesshide"> ' . $info . ' </span>';
             }
         }
         $out .= $deletedhide ? '' : '</h2> <span class="forumng-separator">&#x2022;</span> ';
         $out .= '<span class="forumng-date">' . $by->date . '</span>';
         if ($edituser = $post->get_edit_user()) {
             $out .= ' <span class="forumng-separator">&#x2022;</span> ' . '<span class="forumng-edit">';
             $edit = new stdClass();
             $edit->date = userdate($post->get_modified(), get_string('strftimedatetime', 'langconfig'), $options[forum_post::OPTION_TIME_ZONE]);
             $edit->name = fullname($edituser, $options[forum_post::OPTION_VIEW_FULL_NAMES]);
             if ($edituser->id == $post->get_user()->id) {
                 $out .= get_string('editbyself', 'forumng', $edit->date);
             } else {
                 $out .= get_string('editbyother', 'forumng', $edit);
             }
             if ($options[forum_post::OPTION_COMMAND_HISTORY]) {
                 $out .= ' (<a href="history.php?' . $post->get_link_params(forum::PARAM_HTML) . '">' . get_string('history', 'forumng') . '</a>)';
             }
             $out .= '</span>';
         }
         if ($options[forum_post::OPTION_SELECTABLE]) {
             $out .= ' &#x2022; <input type="checkbox" name="selectp' . $post->get_id() . '" id="id_selectp' . $post->get_id() . '" /><label class="accesshide" for="id_selectp' . $post->get_id() . '">' . get_string('selectlabel', 'forumng', $postnumber) . '</label>';
         }
         if ($options[forum_post::OPTION_FLAG_CONTROL]) {
             $out .= '<div class="forumng-flag">' . '<input type="image" title="' . get_string($post->is_flagged() ? 'clearflag' : 'setflag', 'forumng') . '" src="' . $CFG->modpixpath . '/forumng/flag.' . ($post->is_flagged() ? 'on' : 'off') . '.png" alt="' . get_string($post->is_flagged() ? 'flagon' : 'flagoff', 'forumng') . '" name="action.flag.p_' . $post->get_id() . '.timeread_' . $options[forum_post::OPTION_READ_TIME] . '.flag_' . ($post->is_flagged() ? 0 : 1) . '"/></div>';
         }
         $out .= '</div>';
     } else {
         $out .= $by->name . ' - ' . $by->date . $lf;
         $out .= forum_cron::EMAIL_DIVIDER;
     }
     if ($post->get_deleted()) {
         $out .= '<p class="forumng-deleted-info"><strong>' . get_string('deletedpost', 'forumng') . '</strong> ';
         if ($deletedhide) {
             $out .= get_string($post->get_delete_user()->id == $post->get_user()->id ? 'deletedbyauthor' : 'deletedbymoderator', 'forumng', userdate($post->get_deleted()));
         } else {
             $a = new stdClass();
             $a->date = userdate($post->get_deleted());
             $a->user = '******' . $CFG->wwwroot . '/user/view.php?id=' . $post->get_delete_user()->id . '&amp;course=' . $post->get_forum()->get_course_id() . '">' . fullname($post->get_delete_user(), $options[forum_post::OPTION_VIEW_FULL_NAMES]) . '</a>';
             $out .= get_string('deletedbyuser', 'forumng', $a);
         }
         $out .= '</p>';
     }
     // Get subject. This may make a db query when showing a single post
     // (which includes parent subject).
     if ($options[forum_post::OPTION_EMAIL] || $options[forum_post::OPTION_NO_COMMANDS]) {
         $subject = $post->get_effective_subject(true);
     } else {
         $subject = $post->get_subject();
     }
     // Otherwise, subject is only displayed if it has changed
     if ($subject !== null && $expanded && !$deletedhide) {
         if ($html) {
             $out .= $lf . '<h3 class="forumng-subject">';
             if ($options[forum_post::OPTION_DIGEST]) {
                 // Digest contains link to original post
                 $out .= '<a href="' . $linkprefix . 'discuss.php?' . $discussion->get_link_params(forum::PARAM_HTML) . '#p' . $post->get_id() . '">' . format_string($subject) . '</a>';
             } else {
                 $out .= format_string($subject);
             }
             $out .= '</h3>';
         } else {
             $out .= format_string($subject, true);
             if ($options[forum_post::OPTION_DIGEST]) {
                 // Link to original post
                 $out .= " <{$linkprefix}discuss.php?" . $discussion->get_link_params(forum::PARAM_HTML) . $discussion->get_id() . '#p' . $post->get_id() . '>';
             }
             $out .= $lf;
         }
     }
     // Get content of actual message in HTML
     if ($html) {
         $textoptions = new stdClass();
         // Don't put a <p> tag round post
         $textoptions->para = false;
         // Does not indicate that we trust the text, only that the
         // TRUSTTEXT marker is supported.
         $textoptions->trusttext = true;
         $message = format_text($post->get_message(), $post->get_format(), $textoptions, $post->get_forum()->get_course_id());
         if (!$expanded && !$deletedhide) {
             // When not expanded and no subject, we include a summary of the
             // message
             $stripped = strip_tags(preg_replace('~<script.*?</script>~s', '', $message));
             $messagetosummarise = $subject !== null ? '<h3>' . $subject . '</h3>&nbsp;' . $stripped : $stripped;
             $summary = self::nice_shorten_text($messagetosummarise, 50);
             $out .= $lf . '<div class="forumng-summary"><div class="forumng-text">' . $summary . '</div> ' . $expandlink . '</div>';
         }
     }
     // Start of post main section
     if ($expanded && !$deletedhide) {
         if ($html) {
             $out .= '<div class="forumng-postmain">';
         }
         // Attachments
         $attachments = $post->get_attachment_names();
         if (count($attachments)) {
             if ($html) {
                 $out .= $lf . '<ul class="forumng-attachments">';
             }
             if (count($attachments) == 1) {
                 $attachmentlabel = get_string('attachment', 'forumng');
             } else {
                 $attachmentlabel = get_string('attachments', 'forumng');
             }
             $out .= '<span class="accesshide">' . $attachmentlabel . '</span>';
             foreach ($attachments as $attachment) {
                 if ($html) {
                     require_once $CFG->libdir . '/filelib.php';
                     $iconsrc = $CFG->pixpath . '/f/' . mimeinfo('icon', $attachment);
                     $alt = get_mimetype_description(mimeinfo('type', $attachment));
                     $out .= '<li><a href="' . $linkprefix . 'attachment.php?' . $post->get_link_params(forum::PARAM_HTML) . '&amp;file=' . $attachment . '">' . '<img src="' . $iconsrc . '" alt="' . $alt . '" /> <span>' . htmlspecialchars($attachment) . '</span></a></li>';
                 } else {
                     // Right-align the entry to 70 characters
                     $padding = 70 - strlen($attachment);
                     if ($padding > 0) {
                         $out .= str_repeat(' ', $padding);
                     }
                     // Add filename
                     $out .= $attachment . $lf;
                 }
             }
             if ($html) {
                 $out .= '</ul>' . $lf;
             } else {
                 $out .= $lf;
                 // Extra line break after attachments
             }
         }
         // Display actual content
         if ($html) {
             if ($options[forum_post::OPTION_PRINTABLE_VERSION]) {
                 $message = preg_replace('~<a[^>]*\\shref\\s*=\\s*[\'"](http:.*?)[\'"][^>]*>' . '(?!(http:|www\\.)).*?</a>~', "\$0 [\$1]", $message);
             }
             $out .= $lf . '<div class="forumng-message">' . $message . '</div>';
         } else {
             $out .= format_text_email(trusttext_strip($post->get_message()), $post->get_format());
             $out .= "\n\n";
         }
         if ($html) {
             $out .= $lf . '<div class="forumng-postfooter">';
         }
         // Ratings
         $ratings = '';
         $ratingclasses = '';
         if ($options[forum_post::OPTION_RATINGS_VIEW]) {
             $ratingclasses .= ' forumng-canview';
             if ($post->get_num_ratings() >= $post->get_forum()->get_rating_threshold()) {
                 if ($html) {
                     $ratings .= '<div class="forumng-rating">';
                     $a = new stdClass();
                     $a->avg = '<strong id="rating_for_' . $post->get_id() . '">' . $post->get_average_rating(true) . '</strong>';
                     $a->num = '<span class="forumng-count">' . $post->get_num_ratings() . '</span>';
                     $ratings .= get_string('averagerating', 'forumng', $a);
                     $ratings .= '</div>';
                 } else {
                     $ratings .= strip_tags($post->get_average_rating(true));
                 }
             }
         }
         if ($options[forum_post::OPTION_RATINGS_EDIT] && $html) {
             $ratingclasses .= ' forumng-canedit';
             $ratings .= '<div class="forumng-editrating">' . get_string('yourrating', 'forumng') . ' ';
             $ratings .= choose_from_menu($post->get_forum()->get_rating_options(), 'rating' . $post->get_id(), $post->get_own_rating(), '-', '', forum_post::NO_RATING, true);
             $ratings .= '</div>';
         }
         if ($ratings) {
             $out .= '<div class="forumng-ratings' . $ratingclasses . '">' . $ratings . '</div>';
         }
         // Commands at bottom of mail
         if (class_exists('ouflags') && ou_get_is_mobile_from_cookies()) {
             $mobileclass = ' class="forumng-mobilepost-link"';
         } else {
             $mobileclass = '';
         }
         if ($html) {
             $commands = '';
             $expires = $post->can_ignore_edit_time_limit() ? '' : '&amp;expires=' . ($post->get_edit_time_limit() - time());
             // Jump box
             if ($options[forum_post::OPTION_JUMP_PREVIOUS] || $options[forum_post::OPTION_JUMP_NEXT] || $options[forum_post::OPTION_JUMP_PARENT]) {
                 $commands .= '<li class="forumng-jumpto">' . get_string('jumpto', 'forumng');
                 if ($nextid = $options[forum_post::OPTION_JUMP_NEXT]) {
                     $commands .= ' <a href="#p' . $nextid . '" class="forumng-next">' . get_string('jumpnext', 'forumng') . '</a>';
                 }
                 if ($pid = $options[forum_post::OPTION_JUMP_PREVIOUS]) {
                     if ($nextid) {
                         $commands .= ' (<a href="#p' . $pid . '" class="forumng-prev">' . get_string('jumppreviousboth', 'forumng') . '</a>)';
                     } else {
                         $commands .= ' <a href="#p' . $pid . '" class="forumng-prev">' . get_string('jumpprevious', 'forumng') . '</a>';
                     }
                 }
                 if ($parentid = $options[forum_post::OPTION_JUMP_PARENT]) {
                     $commands .= ' <a href="#p' . $parentid . '" class="forumng-parent">' . get_string('jumpparent', 'forumng') . '</a>';
                 }
                 $commands .= '</li>';
             }
             //Direct link
             if ($options[forum_post::OPTION_COMMAND_DIRECTLINK]) {
                 $commands .= '<li class="forumng-permalink"><a href="discuss.php?' . $discussion->get_link_params(forum::PARAM_HTML) . '#p' . $post->get_id() . '" title="' . get_string('directlinktitle', 'forumng') . '">' . get_string('directlink', 'forumng', $postnumber) . '</a></li>';
             }
             // Alert link
             if ($options[forum_post::OPTION_COMMAND_REPORT]) {
                 $commands .= '<li><a href="' . $linkprefix . 'alert.php?' . $post->get_link_params(forum::PARAM_HTML) . '" title="' . get_string('alert_linktitle', 'forumng') . '">' . get_string('alert_link', 'forumng', $postnumber) . '</a></li>';
             }
             // Split link
             if ($options[forum_post::OPTION_COMMAND_SPLIT]) {
                 $commands .= '<li class="forumng-split"><a href="' . $linkprefix . 'splitpost.php?' . $post->get_link_params(forum::PARAM_HTML) . '">' . get_string('split', 'forumng', $postnumber) . '</a></li>';
             }
             // Delete link
             if ($options[forum_post::OPTION_COMMAND_DELETE]) {
                 $commands .= '<li><a' . $mobileclass . ' href="' . $linkprefix . 'deletepost.php?' . $post->get_link_params(forum::PARAM_HTML) . $expires . '">' . get_string('delete', 'forumng', $postnumber) . '</a></li>';
             }
             // Undelete link
             if ($options[forum_post::OPTION_COMMAND_UNDELETE]) {
                 $commands .= '<li><a href="' . $linkprefix . 'deletepost.php?' . $post->get_link_params(forum::PARAM_HTML) . '&amp;delete=0">' . get_string('undelete', 'forumng', $postnumber) . '</a></li>';
             }
             // Edit link
             if ($options[forum_post::OPTION_COMMAND_EDIT]) {
                 $commands .= '<li><a' . $mobileclass . ' href="' . $linkprefix . 'editpost.php?' . $post->get_link_params(forum::PARAM_HTML) . $expires . '">' . get_string('edit', 'forumng', $postnumber) . '</a></li>';
             }
             // Reply link
             if ($options[forum_post::OPTION_COMMAND_REPLY]) {
                 $commands .= '<li class="forumng-replylink"><a' . $mobileclass . ' href="' . $linkprefix . 'editpost.php?replyto=' . $post->get_id() . $post->get_forum()->get_clone_param(forum::PARAM_HTML) . '">' . get_string('reply', 'forumng', $postnumber) . '</a></li>';
             }
             if ($commands) {
                 $out .= $lf . '<ul class="forumng-commands">' . $commands . '</ul>';
             }
         } else {
             // Reply link
             if ($options[forum_post::OPTION_COMMAND_REPLY]) {
                 $out .= forum_cron::EMAIL_DIVIDER;
                 if ($options[forum_post::OPTION_EMAIL]) {
                     $course = $post->get_forum()->get_course();
                     $out .= get_string("postmailinfo", "forumng", $course->shortname) . $lf;
                 }
                 $out .= "{$linkprefix}editpost.php?replyto=" . $post->get_id() . $post->get_forum()->get_clone_param(forum::PARAM_PLAIN) . $lf;
             }
             // Only the reply command is available in text mode
         }
         // End of post footer and main section
         if ($html) {
             $out .= '</div></div>';
         }
     }
     // End of post div
     if ($html) {
         $out .= '<div class="forumng-endpost"></div></div>';
         if ($export) {
             $out .= '<br /><br />';
         }
     }
     return $out;
 }
 }
 // Is this the actual delete?
 if ($_SERVER['REQUEST_METHOD'] == 'POST') {
     // Delete counts as edit to a post
     if (class_exists('ouflags')) {
         $DASHBOARD_COUNTER = DASHBOARD_FORUMNG_POST;
     }
     // Delete or undelete the post
     if ($delete) {
         $post->delete();
     } else {
         $post->undelete();
     }
     // Redirect back
     if ($ajax) {
         forum_post::print_for_ajax_and_exit($postid, $cloneid);
     }
     redirect('discuss.php?' . $discussion->get_link_params(forum::PARAM_PLAIN) . '#p' . $post->get_id());
 }
 if (class_exists('ouflags') && ou_get_is_mobile()) {
     ou_mobile_configure_theme();
 }
 // Confirm page. Work out navigation for header
 $pagename = get_string($delete ? 'deletepost' : 'undeletepost', 'forumng', $post->get_effective_subject(true));
 $discussion->print_subpage_header($pagename);
 // Show confirm option
 if ($delete) {
     $confirmstring = get_string('confirmdelete', 'forumng');
     if ($post->is_root_post()) {
         $confirmstring .= ' ' . get_string('confirmdelete_nodiscussion', 'forumng');
     }
/**
 * Obtains a search document given the ousearch parameters.
 * @param object $document Object containing fields from the ousearch documents table
 * @return mixed False if object can't be found, otherwise object containing the following
 *   fields: ->content, ->title, ->url, ->activityname, ->activityurl,
 *   and optionally ->extrastrings array and ->data
 */
function forumng_ousearch_get_document($document)
{
    require_once dirname(__FILE__) . '/forum.php';
    return forum_post::search_get_page($document);
}
 /**
  * Updates the in-memory digest records to add a new post to the given
  * user's digests.
  * @param object $user User object (must include special ->emailtype, etc)
  * @param array $userdigests Array of user id => digest information object
  * @param forum_post $post Post object
  * @param forum_post $inreplyto Parent post
  * @param forum_discussion $discussion Discus
  * @param forum $forum
  * @param object $cm
  * @param object $course
  * @param object $context
  */
 private static function digest_add_post_for_user(&$user, &$userdigests, &$post, &$inreplyto, &$discussion, &$forum, &$cm, &$course, &$context)
 {
     global $CFG;
     // Set up digest for user if required
     if (!array_key_exists($user->id, $userdigests)) {
         $userdigests[$user->id] = new StdClass();
         $userdigests[$user->id]->discussionid = -1;
         // So we do header next
         $userdigests[$user->id]->user = $user;
         $userdigests[$user->id]->forumid = -1;
         // Get header text
         $headerdata = new object();
         $headerdata->sitename = format_string($course->fullname, true);
         $headerdata->userprefs = $CFG->wwwroot . '/user/edit.php?id=' . $user->id . '&amp;course=' . $course->id;
         $userdigests[$user->id]->text = get_string('digestmailheader', 'forumng', $headerdata) . "\n\n";
         // Get header HTML
         $html = "<head>";
         foreach ($CFG->stylesheets as $stylesheet) {
             $html .= '<link rel="stylesheet" type="text/css" href="' . $stylesheet . '" />' . "\n";
         }
         $html .= "</head>\n<body id='forumng-email'>\n";
         $headerdata->userprefs = '<a target="_blank" href="' . $headerdata->userprefs . '">' . get_string('digestmailprefs', 'forumng') . '</a>';
         $html .= '<div class="forumng-emailheader"><p>' . get_string('digestmailheader', 'forumng', $headerdata) . '</p></div><hr size="1" noshade="noshade" />';
         $userdigests[$user->id]->html = $html;
         // Get email subject
         $userdigests[$user->id]->subject = get_string('digestmailsubject', 'forumng', format_string($course->shortname, true));
     }
     // New forum?
     if ($userdigests[$user->id]->forumid != $forum->get_id()) {
         $userdigests[$user->id]->forumid = $forum->get_id();
     }
     // Is this a new discussion?
     if ($userdigests[$user->id]->discussionid != $discussion->get_id()) {
         $strforums = get_string('forums', 'forumng');
         // Per-discussion header (text mode)
         $text = "\n \n";
         $text .= '=====================================================================';
         $text .= "\n \n";
         $text .= "{$course->shortname} -> {$strforums} -> " . format_string($forum->get_name(), true);
         if ($discussion->get_subject(false) !== $forum->get_name()) {
             $text .= " -> " . format_string($discussion->get_subject(false), true);
         }
         $text .= "\n";
         // HTML mode
         $html = '<hr size="1" noshade="noshade" />';
         $html .= "<div class='forumng-breadcrumbs'>" . "<a target='_blank' href='{$CFG->wwwroot}/course/view.php?id={$course->id}'>{$course->shortname}</a> -> " . "<a target='_blank' href='{$CFG->wwwroot}/mod/forumng/index.php?id={$course->id}'>{$strforums}</a> -> " . "<a target='_blank' href='{$CFG->wwwroot}/mod/forumng/view.php?" . $forum->get_link_params(forum::PARAM_HTML) . "'>" . format_string($forum->get_name(), true) . "</a>";
         if ($discussion->get_subject(false) !== $forum->get_name()) {
             $html .= " -> <a target='_blank' href='{$CFG->wwwroot}/mod/forumng/discuss.php?" . $discussion->get_link_params(forum::PARAM_HTML) . "'>" . format_string($discussion->get_subject(false), true) . "</a>";
         }
         $html .= '</div>';
         $userdigests[$user->id]->text .= $text;
         $userdigests[$user->id]->html .= $html;
         $userdigests[$user->id]->discussionid = $discussion->get_id();
     }
     // Get both plaintext and html versions (and subject).
     // The html version will be blank if set to
     // plain text mode.
     $post->build_email($inreplyto, $subject, $text, $html, $user->emailtype & 1, $user->emailtype & 2, $user->emailtype & 4, $user->lang, $user->timezone, true);
     $userdigests[$user->id]->text .= $text;
     $userdigests[$user->id]->html .= $html;
 }
 /**
  * Called when a post is deleted or undeleted or modified, or there is a
  * larger change to the discussion
  * @param forum_post $post Post that has changed; null to always recalculate
  */
 function possible_lastpost_change($post = null)
 {
     $recalculate = false;
     if (!$post) {
         $recalculate = true;
     } else {
         if ($post->get_deleted()) {
             // For deleted posts, recalculate if this was previously
             // considered the latest post
             $recalculate = $this->discussionfields->lastpostid == $post->get_id();
         } else {
             // For other posts, recalculate if this is now newer than the
             // stored last post
             $recalculate = $post->get_modified() > $this->discussionfields->timemodified;
         }
     }
     // If necessary, recalculate the date
     if ($recalculate) {
         global $CFG;
         $change = new stdClass();
         $change->id = $this->get_id();
         $rs = forum_utils::get_recordset_sql("SELECT id " . "FROM {$CFG->prefix}forumng_posts WHERE discussionid = " . $this->get_id() . " AND deleted=0 AND oldversion=0 " . "ORDER BY modified DESC", 0, 1);
         if ($rec = rs_fetch_next_record($rs)) {
             $change->lastpostid = $rec->id;
         } else {
             throw new forum_exception('No last post');
         }
         rs_close($rs);
         if ($change->lastpostid != $this->discussionfields->lastpostid) {
             forum_utils::update_record('forumng_discussions', $change);
         }
     }
 }
 /**
  * Creates a new ForumNG by copying data (including all messages etc) from
  * an old forum. The old forum will be hidden.
  *
  * Behaviour is undefined if the old forum wasn't eligible for conversion
  * (forum_utils::get_convertible_forums).
  * @param object $course Moodle course object
  * @param int $forumcmid Old forum to convert
  * @param bool $progress If true, print progress to output
  * @param bool $hide If true, newly-created forum is also hidden
  * @param bool $nodata If true, no user data (posts, subscriptions, etc)
  *   is copied; you only get a forum with same configuration
  * @param bool $insection If true, remeber to create the new forumNG in the same section.
  * @throws forum_exception If any error occurs
  */
 public static function create_from_old_forum($course, $forumcmid, $progress, $hide, $nodata, $insection = true)
 {
     global $CFG;
     // Start the clock and a database transaction
     $starttime = microtime(true);
     forum_utils::start_transaction();
     // Note we do not use get_fast_modinfo because it doesn't contain the
     // complete $cm object.
     $cm = forum_utils::get_record('course_modules', 'id', $forumcmid);
     $forum = forum_utils::get_record('forum', 'id', $cm->instance);
     if ($progress) {
         print_heading(s($forum->name), '', 3);
         print '<ul><li>' . get_string('convert_process_init', 'forumng');
         flush();
     }
     // Hide forum
     forum_utils::update_record('course_modules', (object) array('id' => $cm->id, 'visible' => 0));
     // Table for changed subscription constants
     $subscriptiontranslate = array(0 => 1, 1 => 3, 2 => 2, 3 => 0);
     // Get, convert, and create forum table data
     $forumng = (object) array('course' => $course->id, 'name' => addslashes($forum->name), 'type' => 'general', 'intro' => addslashes($forum->intro), 'ratingscale' => $forum->scale, 'ratingfrom' => $forum->assesstimestart, 'ratinguntil' => $forum->assesstimefinish, 'ratingthreshold' => 1, 'grading' => $forum->assessed, 'attachmentmaxbytes' => $forum->maxbytes, 'subscription' => $subscriptiontranslate[$forum->forcesubscribe], 'feedtype' => $forum->rsstype, 'feeditems' => $forum->rssarticles, 'maxpostsperiod' => $forum->blockperiod, 'maxpostsblock' => $forum->blockafter, 'postingfrom' => 0, 'postinguntil' => 0, 'typedata' => null);
     require_once $CFG->dirroot . '/mod/forumng/lib.php';
     // Note: The idnumber is required. We cannot copy it because then there
     // would be a duplicate idnumber. Let's just leave blank, people will
     // have to configure this manually.
     $forumng->cmidnumber = '';
     if (!($newforumid = forumng_add_instance($forumng))) {
         throw new forum_exception("Failed to add forumng instance");
     }
     // Create and add course-modules entry
     $newcm = new stdClass();
     $newcm->course = $course->id;
     $newcm->module = get_field('modules', 'id', 'name', 'forumng');
     if (!$newcm->module) {
         throw new forum_exception("Cannot find forumng module id");
     }
     $newcm->instance = $newforumid;
     $newcm->section = $cm->section;
     $newcm->added = time();
     $newcm->score = $cm->score;
     $newcm->indent = $cm->indent;
     $newcm->visible = 0;
     // Forums are always hidden until finished
     $newcm->groupmode = $cm->groupmode;
     $newcm->groupingid = $cm->groupingid;
     $newcm->idnumber = $cm->idnumber;
     $newcm->groupmembersonly = $cm->groupmembersonly;
     // Include extra OU-specific data
     if (class_exists('ouflags')) {
         $newcm->showto = $cm->showto;
         $newcm->stealth = $cm->stealth;
         $newcm->parentcmid = $cm->parentcmid;
         $newcm->completion = $cm->completion;
         $newcm->completiongradeitemnumber = $cm->completiongradeitemnumber;
         $newcm->completionview = $cm->completionview;
         $newcm->availablefrom = $cm->availablefrom;
         $newcm->availableuntil = $cm->availableuntil;
         $newcm->showavailability = $cm->showavailability;
         $newcm->parentpagename = $cm->parentpagename;
     }
     // Add
     $newcm->id = forum_utils::insert_record('course_modules', $newcm);
     // Update section
     if ($insection) {
         $section = forum_utils::get_record('course_sections', 'id', $newcm->section);
         $updatesection = (object) array('id' => $section->id, 'sequence' => str_replace($cm->id, $cm->id . ',' . $newcm->id, $section->sequence));
         if ($updatesection->sequence == $section->sequence) {
             throw new forum_exception("Unable to update sequence");
         }
         forum_utils::update_record('course_sections', $updatesection);
     }
     // Construct forum object for new forum
     $newforum = self::get_from_id($forumng->id, forum::CLONE_DIRECT);
     if ($progress) {
         print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
     }
     if (!$nodata) {
         // Convert subscriptions
         switch ($newforum->get_effective_subscription_option()) {
             case self::SUBSCRIPTION_PERMITTED:
                 if ($progress) {
                     print '<li>' . get_string('convert_process_subscriptions_normal', 'forumng');
                     flush();
                 }
                 // Standard subscription - just copy subscriptions
                 $rs = forum_utils::get_recordset('forum_subscriptions', 'forum', $forum->id);
                 while ($rec = rs_fetch_next_record($rs)) {
                     forum_utils::insert_record('forumng_subscriptions', (object) array('forumid' => $forumng->id, 'userid' => $rec->userid, 'subscribed' => 1));
                 }
                 rs_close($rs);
                 if ($progress) {
                     print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
                 }
                 break;
             case self::SUBSCRIPTION_INITIALLY_SUBSCRIBED:
                 // Initial subscription is handled differently; the old forum
                 // stores all the subscriptions in the database, while in this
                 // forum we only store people who chose to unsubscribe
                 if ($progress) {
                     print '<li>' . get_string('convert_process_subscriptions_initial', 'forumng');
                     flush();
                 }
                 // Get list of those subscribed on old forum
                 $rs = forum_utils::get_recordset('forum_subscriptions', 'forum', $forum->id);
                 $subscribedbefore = array();
                 while ($rec = rs_fetch_next_record($rs)) {
                     $subscribedbefore[$rec->userid] = true;
                 }
                 rs_close();
                 // Get list of those subscribed on new forum
                 $new = $newforum->get_subscribers();
                 // For anyone in the new list but not the old list, add an
                 // unsubscribe
                 foreach ($new as $user) {
                     if (!array_key_exists($user->id, $subscribedbefore)) {
                         forum_utils::insert_record('forumng_subscriptions', (object) array('forumid' => $forumng->id, 'userid' => $user->id, 'subscribed' => 0));
                     }
                 }
                 if ($progress) {
                     print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
                 }
                 break;
         }
         // Convert discussions
         if ($progress) {
             print '<li>' . get_string('convert_process_discussions', 'forumng');
             flush();
         }
         $rsd = forum_utils::get_recordset('forum_discussions', 'forum', $forum->id);
         $count = 0;
         while ($recd = rs_fetch_next_record($rsd)) {
             // Convert discussion options
             $newd = (object) array('forumid' => $forumng->id, 'timestart' => $recd->timestart, 'timeend' => $recd->timeend, 'deleted' => 0, 'locked' => 0, 'sticky' => 0);
             if ($recd->groupid == -1 || !$newcm->groupmode) {
                 $newd->groupid = null;
             } else {
                 $newd->groupid = $recd->groupid;
             }
             // Save discussion
             $newd->id = forum_utils::insert_record('forumng_discussions', $newd);
             // Convert posts
             $lastposttime = -1;
             $discussionupdate = (object) array('id' => $newd->id);
             $postids = array();
             // From old post id to new post id
             $parentposts = array();
             // From new post id to old parent id
             $subjects = array();
             // From new id to subject text (no slashes)
             $rsp = forum_utils::get_recordset('forum_posts', 'discussion', $recd->id);
             while ($recp = rs_fetch_next_record($rsp)) {
                 // Convert post
                 $newp = (object) array('discussionid' => $newd->id, 'userid' => $recp->userid, 'created' => $recp->created, 'modified' => $recp->modified, 'deleted' => 0, 'deleteuserid' => null, 'mailstate' => self::MAILSTATE_DIGESTED, 'oldversion' => 0, 'edituserid' => null, 'subject' => addslashes($recp->subject), 'message' => addslashes($recp->message), 'format' => $recp->format, 'important' => 0);
                 // Are there any attachments?
                 $attachments = array();
                 if (class_exists('ouflags')) {
                     // OU has customisation for existing forum that supports
                     // multiple attachments
                     $attachmentrecords = forum_utils::get_records('forum_attachments', 'postid', $recp->id);
                     foreach ($attachmentrecords as $reca) {
                         $attachments[] = $reca->attachment;
                     }
                 } else {
                     // Standard forum uses attachment field for filename
                     if ($recp->attachment) {
                         $attachments[] = $recp->attachment;
                     }
                 }
                 $newp->attachments = count($attachments) ? 1 : 0;
                 // Add record
                 $newp->id = forum_utils::insert_record('forumng_posts', $newp);
                 // Remember details for later parent update
                 $postids[$recp->id] = $newp->id;
                 if ($recp->parent) {
                     $parentposts[$newp->id] = $recp->parent;
                 } else {
                     $discussionupdate->postid = $newp->id;
                 }
                 if ($newp->created > $lastposttime) {
                     $discussionupdate->lastpostid = $newp->id;
                 }
                 $subjects[$newp->id] = $recp->subject;
                 // Copy attachments
                 $oldfolder = $CFG->dataroot . "/{$course->id}/{$CFG->moddata}/forum/{$forum->id}/{$recp->id}";
                 $newfolder = forum_post::get_any_attachment_folder($course->id, $forumng->id, $newd->id, $newp->id);
                 $filesok = 0;
                 $filesfailed = 0;
                 foreach ($attachments as $attachment) {
                     // Create folder if it isn't there
                     $attachment = clean_filename($attachment);
                     check_dir_exists($newfolder, true, true);
                     // Copy file
                     try {
                         forum_utils::copy("{$oldfolder}/{$attachment}", "{$newfolder}/{$attachment}");
                         $filesok++;
                     } catch (forum_exception $e) {
                         if ($progress) {
                             print "[<strong>Warning</strong>: file copy failed for post " . $recp->id . " => " . $newp->id . ", file " . s($attachment) . "]";
                         }
                         $filesfailed++;
                     }
                 }
                 // If all files failed, clean up
                 if ($filesfailed && !$filesok) {
                     rmdir($newfolder);
                     $noattachments = (object) array('id' => $newp->id, 'attachments' => 0);
                     forum_utils::update_record('forumng_posts', $noattachments);
                 }
                 // Convert ratings
                 if ($forumng->ratingscale) {
                     $rsr = get_recordset('forum_ratings', 'post', $recp->id);
                     while ($recr = rs_fetch_next_record($rsr)) {
                         forum_utils::insert_record('forumng_ratings', (object) array('postid' => $newp->id, 'userid' => $recr->userid, 'time' => $recr->time, 'rating' => $recr->rating));
                     }
                     rs_close($rsr);
                 }
             }
             rs_close($rsp);
             // Update parent numbers
             $newparentids = array();
             foreach ($parentposts as $newid => $oldparentid) {
                 if (!array_key_exists($oldparentid, $postids)) {
                     throw new forum_exception("Unknown parent post {$oldparentid}");
                 }
                 $newparentid = $postids[$oldparentid];
                 forum_utils::update_record('forumng_posts', (object) array('id' => $newid, 'parentpostid' => $newparentid));
                 $newparentids[$newid] = $newparentid;
             }
             // Update subjects
             $removesubjects = array();
             // Array of ints to cancel subjects
             foreach ($newparentids as $newid => $newparentid) {
                 $subject = $subjects[$newid];
                 $parentsubject = $subjects[$newparentid];
                 if ($subject && ($subject == get_string('re', 'forum') . ' ' . $parentsubject || $subject == $parentsubject)) {
                     $removesubjects[] = $newid;
                 }
             }
             if (count($removesubjects)) {
                 $in = forum_utils::in_or_equals($removesubjects);
                 forum_utils::execute_sql("UPDATE {$CFG->prefix}forumng_posts SET subject=NULL WHERE id {$in}");
             }
             // Update first/last post numbers
             forum_utils::update_record('forumng_discussions', $discussionupdate);
             // Convert read data
             $rsr = forum_utils::get_recordset_sql("\nSELECT\n    userid, MAX(lastread) AS lastread\nFROM\n    {$CFG->prefix}forum_read\nWHERE\n    discussionid = {$recd->id}\nGROUP BY\n    userid");
             while ($recr = rs_fetch_next_record($rsr)) {
                 forum_utils::insert_record('forumng_read', (object) array('discussionid' => $newd->id, 'userid' => $recr->userid, 'time' => $recr->lastread));
             }
             rs_close($rsr);
             // Display dot for each discussion
             if ($progress) {
                 print '.';
                 $count++;
                 if ($count % 10 == 0) {
                     print $count;
                 }
                 flush();
             }
         }
         rs_close($rsd);
         if ($progress) {
             print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
         }
     }
     // Show forum
     if (!$hide && $cm->visible) {
         if ($progress) {
             print '<li>' . get_string('convert_process_show', 'forumng');
             flush();
         }
         $updatecm = (object) array('id' => $newcm->id, 'visible' => 1);
         forum_utils::update_record('course_modules', $updatecm);
         if ($progress) {
             print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
         }
     }
     // Transfer role assignments
     $oldcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
     $newcontext = get_context_instance(CONTEXT_MODULE, $newcm->id);
     $roles = get_records('role_assignments', 'contextid', $oldcontext->id);
     if ($roles) {
         if ($progress) {
             print '<li>' . get_string('convert_process_assignments', 'forumng');
             flush();
         }
         foreach ($roles as $role) {
             $newrole = $role;
             $newrole->contextid = $newcontext->id;
             $newrole->enrol = addslashes($newrole->enrol);
             forum_utils::insert_record('role_assignments', $newrole);
         }
         if ($progress) {
             print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
         }
     }
     // Transfer capabilities
     $capabilities = array('moodle/course:viewhiddenactivities' => 'moodle/course:viewhiddenactivities', 'moodle/site:accessallgroups' => 'moodle/site:accessallgroups', 'moodle/site:trustcontent' => 'moodle/site:trustcontent', 'moodle/site:viewfullnames' => 'moodle/site:viewfullnames', 'mod/forum:viewdiscussion' => 'mod/forumng:viewdiscussion', 'mod/forum:startdiscussion' => 'mod/forumng:startdiscussion', 'mod/forum:replypost' => 'mod/forumng:replypost', 'mod/forum:viewrating' => 'mod/forumng:viewrating', 'mod/forum:viewanyrating' => 'mod/forumng:viewanyrating', 'mod/forum:rate' => 'mod/forumng:rate', 'mod/forum:createattachment' => 'mod/forumng:createattachment', 'mod/forum:deleteanypost' => 'mod/forumng:deleteanypost', 'mod/forum:splitdiscussions' => 'mod/forumng:splitdiscussions', 'mod/forum:movediscussions' => 'mod/forumng:movediscussions', 'mod/forum:editanypost' => 'mod/forumng:editanypost', 'mod/forum:viewsubscribers' => 'mod/forumng:viewsubscribers', 'mod/forum:managesubscriptions' => 'mod/forumng:managesubscriptions', 'mod/forum:viewhiddentimedposts' => 'mod/forumng:viewallposts');
     $caps = get_records('role_capabilities', 'contextid', $oldcontext->id);
     if ($caps) {
         if ($progress) {
             print '<li>' . get_string('convert_process_overrides', 'forumng');
             flush();
         }
         foreach ($caps as $cap) {
             foreach ($capabilities as $key => $capability) {
                 if ($cap->capability != $key) {
                     continue;
                 }
                 $newcap = $cap;
                 $newcap->contextid = $newcontext->id;
                 $newcap->capability = $capability;
                 $newcap->capability = addslashes($newcap->capability);
                 forum_utils::insert_record('role_capabilities', $newcap);
             }
         }
         if ($progress) {
             print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
         }
     }
     // Do course cache
     rebuild_course_cache($course->id, true);
     // Update search data
     if (self::search_installed()) {
         if ($progress) {
             print '<li>' . get_string('convert_process_search', 'forumng') . '</li>';
             flush();
         }
         self::search_update_all($progress, $course->id, $newcm->id);
     }
     // OU only: Transfer external dashboard details to new forum
     if (class_exists('ouflags')) {
         if ($progress) {
             print '<li>' . get_string('convert_process_dashboard', 'forumng');
             flush();
         }
         require_once $CFG->dirroot . '/local/externaldashboard/external_dashboard.php';
         $a = new stdClass();
         list($a->yay, $a->nay) = external_dashboard::transfer_favourites($forumcmid, $newcm->id);
         if ($progress) {
             print ' ' . get_string('convert_process_dashboard_done', 'forumng', $a) . '</li>';
         }
     }
     if ($progress) {
         print '<li>' . get_string('convert_process_update_subscriptions', 'forumng');
         flush();
     }
     self::group_subscription_update(false, $newcm->id);
     if ($progress) {
         print ' ' . get_string('convert_process_state_done', 'forumng') . '</li>';
     }
     forum_utils::finish_transaction();
     if ($progress) {
         $a = (object) array('seconds' => round(microtime(true) - $starttime, 1), 'link' => '<a href="view.php?id=' . $newcm->id . '">' . get_string('convert_newforum', 'forumng') . '</a>');
         print '</ul><p>' . get_string('convert_process_complete', 'forumng', $a) . '</p>';
     }
 }
 /**
  * Prints AJAX version of the post to output, and exits.
  * @param mixed $postorid Post object or ID of post
  * @param int $cloneid If $postorid is an id, a clone id may be necessary
  *   to construct the post
  * @param array $options Post options if any
  * @param int $postid ID of post
  */
 public static function print_for_ajax_and_exit($postorid, $cloneid = null, $options = array())
 {
     if (is_object($postorid)) {
         $post = $postorid;
     } else {
         $post = forum_post::get_from_id($postorid, $cloneid, true);
     }
     header('Content-Type: text/plain');
     print trim($post->display(true, $options));
     exit;
 }
     $post = reset($posts);
     $pagename = $post->u_firstname . ' ' . $post->u_lastname;
     $pagename .= $CFG->forumng_showusername ? ' (' . $post->u_username . ')' : '';
 } else {
     if (!($user = get_record('user', 'id', $userid))) {
         throw new forum_exception("Cannot find user (id={$userid}) in the user table");
     }
     $pagename = $user->firstname . ' ' . $user->lastname . ' (' . $user->username . ')';
 }
 // Print page header
 $prevpage = get_string('userposts', 'forumng');
 $navigation = array();
 $navigation[] = array('name' => $prevpage, 'link' => $CFG->wwwroot . '/mod/forumng/feature/userposts/list.php?id=' . $cmid);
 $forum->print_subpage_header($pagename, $navigation);
 foreach ($posts as $postid => $post) {
     $fp = forum_post::get_from_id($postid, $cloneid, false, false, $userid);
     print "<div class='forumng-userpostheading'>";
     // If this post is a reply, then print a link to the discussion
     if (isset($post->parentpostid)) {
         $url = $CFG->wwwroot . '/mod/forumng/discuss.php?d=' . $post->discussionid;
         $title = $post->fd_subject;
         print get_string('re', 'forumng', "<a href='{$url}'>{$title}</a>");
     } else {
         print get_string('newdiscussion', 'forumng');
     }
     print "</div>";
     // Display this post
     $options = array(forum_post::OPTION_NO_COMMANDS => true, forum_post::OPTION_FIRST_UNREAD => false, forum_post::OPTION_UNREAD_NOT_HIGHLIGHTED => true);
     print $fp->display(true, $options);
 }
 // Display link to the discussion
<?php

require_once '../../config.php';
require_once 'forum.php';
if (class_exists('ouflags')) {
    $DASHBOARD_COUNTER = DASHBOARD_FORUMNG_AJAX;
}
// Script retrieves content of a single post (plain). Intended for use only
// by AJAX calls.
// Post ID
$postid = required_param('p', PARAM_INT);
$cloneid = optional_param('clone', 0, PARAM_INT);
$raw = optional_param('raw', 0, PARAM_INT);
try {
    // Get post
    $post = forum_post::get_from_id($postid, $cloneid, true, true);
    // Do all access security checks
    $post->require_view();
    // Display post
    if ($raw) {
        print $post->get_json_format();
    } else {
        forum_post::print_for_ajax_and_exit($post);
    }
} catch (forum_exception $e) {
    header('Content-Type: text/plain', true, 500);
    print $e->getMessage();
}