/**
  * Adds a discussion to the list (internal use only).
  * @param forum_discussion $discussion
  */
 function add_discussion($discussion)
 {
     if ($discussion->is_sticky() && !$discussion->is_deleted()) {
         $this->stickydiscussions[$discussion->get_id()] = $discussion;
     } else {
         $this->normaldiscussions[$discussion->get_id()] = $discussion;
     }
 }
 /**
  * Convenience function for subclasses. Returns HTML code suitable to
  * use for a button in this area.
  * @param forum_discussion $discussion
  * @param string $name Text of button
  * @param string $script Name/path of .php script (relative to mod/forumng)
  * @param bool $post If true, makes the button send a POST request
  * @param array $options If included, passes these options as well as 'd'
  * @param string $extrahtml If specified, adds this HTML at end of (just
  *   inside) the form
  * @param bool $highlight If true, adds a highlight class to the form
  * @return string HTML code for button
  */
 protected static function get_button($discussion, $name, $script, $post = false, $options = array(), $extrahtml = '', $highlight = false)
 {
     $method = $post ? 'post' : 'get';
     $optionshtml = '';
     $options['d'] = $discussion->get_id();
     if ($discussion->get_forum()->is_shared()) {
         $options['clone'] = $discussion->get_forum()->get_course_module_id();
     }
     if ($post) {
         $options['sesskey'] = sesskey();
     }
     foreach ($options as $key => $value) {
         $optionshtml .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />';
     }
     $class = '';
     if ($highlight) {
         $class = ' class="forumng-highlight"';
     }
     return "<form method='{$method}' action='{$script}' {$class}><div>" . "{$optionshtml}<input type='submit' value='{$name}' />" . "{$extrahtml}</div></form>";
 }
function make_discussion($forum, $posts, $readusers, &$userids, $ratingpercent)
{
    set_time_limit(200);
    // Make discussion
    static $index = 0;
    $index++;
    list($discussionid, $postid) = $forum->create_discussion(null, 'Discussion ' . $index, get_post_text(), FORMAT_HTML, array(), false, 0, 0, false, false, $userids[mt_rand(0, count($userids) - 1)], false);
    $discussion = forum_discussion::get_from_id($discussionid, forum::CLONE_DIRECT);
    // Make posts
    $count = my_random($posts) - 1;
    $allposts = array($discussion->get_root_post());
    for ($i = 0; $i < $count; $i++) {
        make_post($discussion, $allposts, $userids, $ratingpercent);
    }
    // Mark the discussion read if requested
    if ($readusers > 0) {
        $now = time();
        for ($i = 0; $i < $readusers; $i++) {
            $discussion->mark_read($now, $userids[$i]);
        }
    }
    // Progress
    print '.';
}
<?php

require_once '../../../../config.php';
require_once $CFG->dirroot . '/mod/forumng/forum.php';
$d = required_param('d', PARAM_INT);
$cloneid = optional_param('clone', 0, PARAM_INT);
$delete = required_param('delete', PARAM_INT);
try {
    $discussion = forum_discussion::get_from_id($d, $cloneid);
    $forum = $discussion->get_forum();
    $cm = $forum->get_course_module();
    $course = $forum->get_course();
    // Check permission for change
    $discussion->require_edit();
    // Is this the actual delete?
    if ($_SERVER['REQUEST_METHOD'] == 'POST') {
        if ($delete) {
            $discussion->delete();
            redirect($forum->get_url(forum::PARAM_PLAIN));
        } else {
            $discussion->undelete();
            redirect('../../discuss.php?' . $discussion->get_link_params(forum::PARAM_PLAIN));
        }
    }
    // Confirm page. Work out navigation for header
    $pagename = get_string($delete ? 'deletediscussion' : 'undeletediscussion', 'forumng', $discussion->get_subject(false));
    $navigation = array();
    $navigation[] = array('name' => shorten_text(htmlspecialchars($discussion->get_subject())), 'link' => $discussion->get_url(), 'type' => 'forumng');
    $navigation[] = array('name' => $pagename, 'type' => 'forumng');
    $PAGEWILLCALLSKIPMAINDESTINATION = true;
    print_header_simple(format_string($forum->get_name()) . ': ' . $pagename, "", build_navigation($navigation, $cm), "", "", true, '', navmenu($course, $cm));
 /**
  * Displays the discussion page.
  * @param forum_discussion $discussion Discussion
  */
 public function print_discussion_page($discussion)
 {
     $previousread = (int) $discussion->get_time_read();
     // 'Read date' option (used when viewing all posts so that they keep
     // their read/unread colouring)
     $timeread = optional_param('timeread', 0, PARAM_INT);
     if ($timeread) {
         $discussion->pretend_time_read($timeread);
         $previousread = $timeread;
     }
     // 'Expand all' option (always chosen for non-JS browsers)
     $expandall = optional_param('expand', 0, PARAM_INT) || forum_utils::is_bad_browser();
     // 'Expand all' option (always chosen for non-JS browsers)
     $collapseall = optional_param('collapse', 0, PARAM_INT);
     // Magic expand tracker (for use in JS only, never set server-side).
     // This tracks expanded posts, and makes the Back button 'work' in
     // the sense that it will expand these posts again.
     print '<form method="post" action="."><div>' . '<input type="hidden" id="expanded_posts" name="expanded_posts" ' . 'value="" /></div></form>';
     // Get content for all posts in the discussion
     $options = array();
     if ($expandall) {
         $options[forum_post::OPTION_CHILDREN_EXPANDED] = true;
     }
     if ($collapseall) {
         $options[forum_post::OPTION_CHILDREN_COLLAPSED] = true;
     }
     $content = $this->display_discussion($discussion, $options);
     // Some post display options use the read time to construct links
     // (usually for non-JS version) so that unread state is maintained.
     $options[forum_post::OPTION_READ_TIME] = $previousread;
     // Display expand all option if there are any 'Expand' links in content
     $fakedate = '&amp;timeread=' . $previousread;
     print '<div id="forumng-expandall">';
     $showexpandall = preg_match('~<a [^>]*href="discuss\\.php\\?d=[0-9]+[^"]*&amp;expand=1#p[0-9]+">~', $content);
     $showcollapseall = preg_match('~<div class="forumng-post forumng-full.*<div class="forumng-post forumng-full~s', $content);
     if ($showexpandall) {
         print '<a href="' . $discussion->get_url(forum::PARAM_HTML) . '&amp;expand=1' . $fakedate . '">' . get_string('expandall', 'forumng') . '</a>';
         if ($showcollapseall) {
             print ' &#x2022; ';
         }
     }
     if ($showcollapseall) {
         print '<a href="' . $discussion->get_url(forum::PARAM_HTML) . '&amp;collapse=1' . $fakedate . '">' . get_string('collapseall', 'forumng') . '</a> ';
     }
     print '</div>';
     // Display content
     print $content;
     // Print reply/edit forms for AJAX
     print $this->display_ajax_forms($discussion->get_forum());
     // Link back to forum
     print $discussion->display_link_back_to_forum();
     // Display discussion features (row of buttons)
     print $discussion->display_discussion_features();
     // Display the subscription options to this disucssion if available
     print $discussion->display_subscribe_options();
     // Atom/RSS links
     print $discussion->display_feed_links();
     // Set read data [shouldn't this logic be somewhere else as it is not
     // part of display?]
     if (forum::mark_read_automatically()) {
         $discussion->mark_read();
     }
 }
    $OUMOBILESUPPORT = true;
    ou_set_is_mobile(ou_get_is_mobile_from_cookies());
}
require_once 'forum.php';
if (class_exists('ouflags')) {
    $DASHBOARD_COUNTER = DASHBOARD_FORUMNG_VIEW;
}
// Require discussion parameter here. Other parameters may be required in forum
// type.
$discussionid = required_param('d', PARAM_INT);
$cloneid = optional_param('clone', 0, PARAM_INT);
try {
    // Construct discussion variable (will check id is valid)
    // Retrieve new copy of discussion from database, but store it in cache
    // for further use.
    $discussion = forum_discussion::get_from_id($discussionid, $cloneid, 0, false, true);
    $forum = $discussion->get_forum();
    $course = $forum->get_course();
    $cm = $forum->get_course_module();
    $context = $forum->get_context();
    $draftid = optional_param('draft', 0, PARAM_INT);
    if ($draftid) {
        $draft = forum_draft::get_from_id($draftid);
        if (!$draft->is_reply() || $draft->get_discussion_id() != $discussionid) {
            print_error('draft_mismatch', 'forumng', $forum->get_url(forum::PARAM_HTML));
        }
        $root = $discussion->get_root_post();
        $inreplyto = $root->find_child($draft->get_parent_post_id(), false);
        if (!$inreplyto || !$inreplyto->can_reply($whynot) || !$discussion->can_view()) {
            print_error('draft_cannotreply', 'forumng', $forum->get_url(forum::PARAM_HTML), get_string($whynot, 'forumng'));
        }
    /**
     * This function handles all aspects of page processing and then calls
     * methods in $selector at the appropriate moments.
     * @param post_selector $selector Object that extends this base class
     */
    static function go($selector)
    {
        $d = required_param('d', PARAM_INT);
        $cloneid = optional_param('clone', 0, PARAM_INT);
        $fromselect = optional_param('fromselect', 0, PARAM_INT);
        $all = optional_param('all', '', PARAM_RAW);
        $select = optional_param('select', '', PARAM_RAW);
        try {
            // Get basic objects
            $discussion = forum_discussion::get_from_id($d, $cloneid);
            if (optional_param('cancel', '', PARAM_RAW)) {
                // CALL TYPE 6
                redirect('../../discuss.php?' . $discussion->get_link_params(forum::PARAM_PLAIN));
            }
            $forum = $discussion->get_forum();
            $cm = $forum->get_course_module();
            $course = $forum->get_course();
            $isform = optional_param('postselectform', 0, PARAM_INT);
            // Page name and permissions
            $pagename = $selector->get_page_name();
            $buttonname = $selector->get_button_name();
            $discussion->require_view();
            $selector->require_capability($forum->get_context(), $discussion);
            if (!($fromselect || $isform || $all)) {
                // Either an initial request (non-JS) to display the 'dialog' box,
                // or a request to show the list of posts with checkboxes for
                // selection
                // Both types share same navigation
                $discussion->print_subpage_header($pagename);
                if (!$select) {
                    // Show initial dialog
                    print_box_start();
                    ?>
<h2><?php 
                    print $buttonname;
                    ?>
</h2>
<form action="<?php 
                    echo $_SERVER['PHP_SELF'];
                    ?>
" method="get"><div>
<?php 
                    print $discussion->get_link_params(forum::PARAM_FORM);
                    ?>
<p><?php 
                    print_string('selectorall', 'forumng');
                    ?>
</p>
<div class="forumng-buttons">
<input type="submit" name="all" value="<?php 
                    print_string('discussion', 'forumng');
                    ?>
" />
<input type="submit" name="select" value="<?php 
                    print_string('selectedposts', 'forumng');
                    ?>
" />
</div>
</div></form>
<?php 
                    print_box_end();
                } else {
                    // Show list of posts to select
                    ?>
<div class="forumng-selectintro">
  <p><?php 
                    print_string('selectintro', 'forumng');
                    ?>
</p>
</div>
<form action="<?php 
                    echo $_SERVER['PHP_SELF'];
                    ?>
" method="post"><div>
<?php 
                    print $discussion->get_link_params(forum::PARAM_FORM);
                    ?>
<input type="hidden" name="fromselect" value="1" />
<?php 
                    print $forum->get_type()->display_discussion($discussion, array(forum_post::OPTION_NO_COMMANDS => true, forum_post::OPTION_CHILDREN_EXPANDED => true, forum_post::OPTION_SELECTABLE => true));
                    ?>
<div class="forumng-selectoutro">
<input type="submit" value="<?php 
                    print_string('confirmselection', 'forumng');
                    ?>
" />
<input type="submit" name="cancel" value="<?php 
                    print_string('cancel');
                    ?>
" />
</div>
</div></form>
<?php 
                }
                // Display footer
                print_footer($course);
            } else {
                // Call types 3, 4, and 5 use the form (and may include list of postids)
                if ($all) {
                    $postids = false;
                } else {
                    $postids = array();
                    foreach ($_POST as $field => $value) {
                        $matches = array();
                        if ((string) $value !== '0' && preg_match('~^selectp([0-9]+)$~', $field, $matches)) {
                            $postids[] = $matches[1];
                        }
                    }
                }
                // Get form to use
                $mform = $selector->get_form($discussion, $all, $postids);
                if (!$mform) {
                    // Some options do not need a confirmation form; in that case,
                    // just apply the action immediately.
                    $selector->apply($discussion, $all, $postids, null);
                    exit;
                }
                // Check cancel
                if ($mform->is_cancelled()) {
                    redirect('../../discuss.php?' . $discussion->get_link_params(forum::PARAM_PLAIN));
                }
                if ($fromform = $mform->get_data()) {
                    // User submitted form to confirm process, which should now be
                    // applied by selector.
                    $selector->apply($discussion, $all, $postids, $fromform);
                    exit;
                } else {
                    $discussion->print_subpage_header($pagename);
                    // User requested form either via JavaScript or the other way, and
                    // either with all messages or the whole discussion.
                    // Print form
                    print $mform->display();
                    // Print optional content that goes after form
                    print $selector->get_content_after_form($discussion, $all, $postids, $fromform);
                    // Display footer
                    print_footer($course);
                }
            }
        } catch (forum_exception $e) {
            forum_utils::handle_exception($e);
        }
    }
 /**
  * Called when displaying a group of posts together on one page.
  * @param forum_discussion $discussion Forum object
  * @param string $html HTML that has already been created for the group
  *   of posts
  * @return string Modified (if necessary) HTML
  */
 public function display_post_group($discussion, $html)
 {
     // Add rating form if there are any rating selects
     $hasratings = strpos($html, '<div class="forumng-editrating">') !== false;
     $hasflags = strpos($html, '<div class="forumng-flag">') !== false;
     if ($hasflags || $hasratings) {
         $script = '<script type="text/javascript">' . 'document.getElementById("forumng-actionform").autocomplete=false;' . '</script>';
         $html = '<form method="post" id="forumng-actionform" ' . 'action="action.php"><div>' . $script . $html . $discussion->get_link_params(forum::PARAM_FORM);
         if ($hasratings) {
             $html .= '<input type="submit" id="forumng-saveallratings" value="' . get_string('saveallratings', 'forumng') . '" name="action.rate"/>';
         }
         $html .= '</div></form>';
     }
     return $html;
 }
 /**
  * Either delete or archive old discussions based on the forum setting
  */
 static function archive_old_discussions()
 {
     global $CFG;
     $now = time();
     $housekeepingquery = " \nFROM \n    {$CFG->prefix}forumng_discussions fd\n    INNER JOIN {$CFG->prefix}forumng_posts fp ON fd.lastpostid = fp.id\n    INNER JOIN {$CFG->prefix}forumng f ON fd.forumid = f.id\nWHERE\n    f.removeafter<>0  AND fd.sticky<>1 AND fp.modified<{$now} - f.removeafter \n";
     $count = forum_utils::count_records_sql("SELECT COUNT(1) {$housekeepingquery}");
     if ($count) {
         mtrace("\nBeginning processing {$count} discussion archiving/deleting requests");
         $housekeepingrs = forum_utils::get_recordset_sql("\nSELECT \n    fd.id AS discussionid, f.id AS forumid, f.removeafter, f.removeto {$housekeepingquery} ORDER BY f.removeto\n            ");
         $targetforum = null;
         $targetcourseid = null;
         $cron_log = '';
         $discussionmovecount = 0;
         $discussiondeletecount = 0;
         while ($rec = rs_fetch_next_record($housekeepingrs)) {
             $discussion = forum_discussion::get_from_id($rec->discussionid, forum::CLONE_DIRECT);
             if ($rec->removeto) {
                 //moving to a different forum
                 $forum = $discussion->get_forum();
                 $course = $forum->get_course();
                 $modinfo = get_fast_modinfo($course);
                 if ($forum->can_archive_forum($modinfo, $cron_log)) {
                     //Do not get the target forum and course id again if the target forum is the same
                     if (!$targetforum || $targetforum->get_id() != $rec->removeto) {
                         $targetforum = forum::get_from_id($rec->removeto, forum::CLONE_DIRECT);
                         $targetforum = $targetforum->get_real_forum();
                     }
                     //target discussion groupid must be the same as the original groupid
                     $targetgroupmode = $targetforum->get_group_mode();
                     $targetgroupid = $targetgroupmode ? $discussion->get_group_id() : null;
                     $discussion->move($targetforum, $targetgroupid);
                     $discussionmovecount++;
                 }
             } else {
                 //Delete all discussions and relevant data permanently
                 $discussion->permanently_delete();
                 $discussiondeletecount++;
             }
         }
         rs_close($housekeepingrs);
         mtrace("\n {$discussionmovecount} discussions have been archived and {$discussiondeletecount} discussions have been deleted permanently.");
     }
 }
<?php

// Scripts for paste the discussion or cancel the paste.
require_once '../../../../config.php';
require_once $CFG->dirroot . '/mod/forumng/forum.php';
$cmid = required_param('cmid', PARAM_INT);
$groupid = optional_param('group', forum::NO_GROUPS, PARAM_INT);
$cloneid = optional_param('clone', 0, PARAM_INT);
try {
    $targetforum = forum::get_from_cmid($cmid, $cloneid);
    if (optional_param('cancel', '', PARAM_RAW)) {
        unset($SESSION->forumng_copyfrom);
        redirect($targetforum->get_url(forum::PARAM_PLAIN));
    }
    //If the paste action has already been done or cancelled in a different window/tab
    if (!isset($SESSION->forumng_copyfrom)) {
        redirect($targetforum->get_url(forum::PARAM_PLAIN));
    }
    $olddiscussionid = $SESSION->forumng_copyfrom;
    $oldcloneid = $SESSION->forumng_copyfromclone;
    $olddiscussion = forum_discussion::get_from_id($olddiscussionid, $oldcloneid);
    // Check permission to copy the discussion
    require_capability('mod/forumng:copydiscussion', $olddiscussion->get_forum()->get_context());
    //security check to see if can start a new discussion in the target forum
    $targetforum->require_start_discussion($groupid);
    $olddiscussion->copy($targetforum, $groupid);
    unset($SESSION->forumng_copyfrom);
    redirect($targetforum->get_url(forum::PARAM_PLAIN));
} catch (forum_exception $e) {
    forum_utils::handle_exception($e);
}
 /**
  * Merges the contents of this discussion into another discussion.
  * @param forum_discussion $targetdiscussion Target discussion
  * @param int $userid User ID (0 = current)
  * @param bool $log True to log this action
  */
 public function merge_into($targetdiscussion, $userid = 0, $log = true)
 {
     global $CFG;
     forum_utils::start_transaction();
     // Update parent post id of root post
     $record = new stdClass();
     $record->id = $this->discussionfields->postid;
     $record->parentpostid = $targetdiscussion->discussionfields->postid;
     forum_utils::update_record('forumng_posts', $record);
     // Move all posts into new discussion
     forum_utils::execute_sql("UPDATE {$CFG->prefix}forumng_posts SET " . "discussionid=" . $targetdiscussion->get_id() . " WHERE discussionid=" . $this->get_id());
     // Delete this discussion
     forum_utils::delete_records('forumng_discussions', 'id', $this->discussionfields->id);
     // Merge attachments (if any)
     $oldfolder = $this->get_attachment_folder();
     $newfolder = $targetdiscussion->get_attachment_folder();
     if (is_dir($oldfolder)) {
         $handle = forum_utils::opendir($oldfolder);
         $madenewfolder = false;
         while (false !== ($name = readdir($handle))) {
             if ($name != '.' && $name != '..') {
                 if (!$madenewfolder) {
                     check_dir_exists($newfolder, true, true);
                     $madenewfolder = true;
                 }
                 $oldname = $oldfolder . '/' . $name;
                 $newname = $newfolder . '/' . $name;
                 forum_utils::rename($oldname, $newname);
             }
         }
         closedir($handle);
     }
     // Merging the discussion into another might cause completion changes
     // (if there was a requirement for discussions and this is no longer
     // a discussion in its own right).
     $this->update_completion(false);
     if ($log) {
         $this->log('merge discussion d' . $targetdiscussion->get_id());
     }
     forum_utils::finish_transaction();
     $this->uncache();
     $targetdiscussion->uncache();
 }
 /**
  * Obtains list of posts to include in an Atom/RSS feed.
  * @param int $groupid Group ID (may be ALL_GROUPS)
  * @param int $userid User ID
  * @param forum_discussion $discussion Discussion object (intended only
  *   for calls via the forum_discussion method)
  * @return array Array of forum_post objects
  */
 public function get_feed_posts($groupid, $userid, $discussion = null)
 {
     // Don't let user view any posts in a discussion feed they can't see
     // (I don't think they should be given a key in this case, but just
     // to be sure).
     if ($discussion && !$this->get_type()->can_view_discussion($discussion, $userid)) {
         return array();
     }
     // Number of items to output
     $items = $this->get_effective_feed_items();
     // Get most recent N posts from db
     if ($discussion) {
         $where = 'fd.id=' . $discussion->get_id();
     } else {
         $where = 'fd.forumid=' . $this->get_id();
         if ($this->get_group_mode() && $groupid != self::ALL_GROUPS) {
             $where .= ' AND fd.groupid=' . $groupid;
         }
     }
     // Don't include deleted or old-version posts
     $where .= ' AND fp.oldversion=0 AND fp.deleted=0 AND fd.deleted=0';
     // Or ones out of time
     $now = time();
     $where .= " AND (fd.timestart < {$now})" . " AND (fd.timeend = 0 OR fd.timeend > {$now})";
     $postrecs = forum_post::query_posts($where, 'GREATEST(fp.created, fd.timestart) DESC', false, false, false, $userid, true, false, 0, $items);
     if (count($postrecs) == 0) {
         // No posts!
         return array();
     }
     $result = array();
     if ($discussion) {
         foreach ($postrecs as $rec) {
             $post = new forum_post($discussion, $rec, null);
             $result[$rec->id] = $post;
         }
     } else {
         // Based on these posts, get all mentioned discussions
         $discussionids = array();
         $discussionposts = array();
         foreach ($postrecs as $rec) {
             $discussionids[] = $rec->discussionid;
             $discussionposts[$rec->discussionid][] = $rec->id;
         }
         $discussionpart = forum_utils::in_or_equals($discussionids);
         $rs = forum_discussion::query_discussions("fd.id " . $discussionpart, -1, 'id');
         // Build the discussion and post objects
         $posts = array();
         while ($rec = rs_fetch_next_record($rs)) {
             $discussion = new forum_discussion($this, $rec, true, -1);
             if ($discussion->can_view($userid)) {
                 foreach ($discussionposts[$discussion->get_id()] as $postid) {
                     $post = new forum_post($discussion, $postrecs[$postid], null);
                     $posts[$postid] = $post;
                 }
             }
         }
         rs_close($rs);
         // Put them back in order of the post records, and return
         foreach ($postrecs as $rec) {
             // Records might be excluded if user can't view discussion
             if (array_key_exists($rec->id, $posts)) {
                 $result[$rec->id] = $posts[$rec->id];
             }
         }
     }
     return $result;
 }
 $discussion = forum_discussion::get_from_id($d, $cloneid);
 $forum = $discussion->get_forum();
 $cm = $forum->get_course_module();
 $course = $forum->get_course();
 // Require that you can see this discussion (etc) and merge them
 $discussion->require_view();
 if (!$discussion->can_split($whynot)) {
     print_error($whynot, 'forumng');
 }
 if ($stage == 2) {
     if (!confirm_sesskey()) {
         print_error('invalidsesskey');
     }
     if (!isset($_POST['cancel'])) {
         // Get source discussion and check permissions
         $sourcediscussion = forum_discussion::get_from_id($SESSION->forumng_mergefrom, $SESSION->forumng_mergefromclone);
         $sourcediscussion->require_view();
         if (!$sourcediscussion->can_split($whynot)) {
             print_error($whynot, 'forumng');
         }
         // Do actual merge
         $sourcediscussion->merge_into($discussion);
     }
     unset($SESSION->forumng_mergefrom);
     redirect('../../discuss.php?' . $discussion->get_link_params(forum::PARAM_PLAIN));
 }
 // Create form
 require_once 'merge_form.php';
 $mform = new mod_forumng_merge_form('merge.php', array('d' => $d, 'clone' => $cloneid));
 if ($mform->is_cancelled()) {
     redirect('../../discuss.php?' . $discussion->get_link_params(forum::PARAM_PLAIN));
 /**
  * Calls search_update on each child of the current post, and recurses.
  * Used when the subject's discussion is changed.
  */
 function search_update_children()
 {
     if (!forum::search_installed()) {
         return;
     }
     // If the in-memory post object isn't already part of a full
     // discussion...
     if (!is_array($this->children)) {
         // ...then get one
         $discussion = forum_discussion::get_from_id($this->discussion->get_id(), $this->get_forum()->get_course_module_id());
         $post = $discussion->get_root_post()->find_child($this->get_id());
         // Do this update on the new discussion
         $post->search_update_children();
         return;
     }
     // Loop through all children
     foreach ($this->children as $child) {
         // Update its search fields
         $child->search_update();
         // Recurse
         $child->search_update_children();
     }
 }