/**
  * 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>";
 }
 /**
  * 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;
 }
 /**
  * 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;
 }