/** * Adds a discussion to the list (internal use only). * @param mod_forumng_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 mod_forumng_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 * @param bool $selector If true, adds a selector class to the form (indicating that the * JavaScript post selector should be used) * @return string HTML code for button */ protected static function get_button($discussion, $name, $script, $post = false, $options = array(), $extrahtml = '', $highlight = false, $selector = 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 = 'forumng-highlight'; } if ($selector) { $class .= ' forumng-selectorbutton'; } if ($class !== '') { $class = ' class="' . trim($class) . '"'; } return "<form method='{$method}' action='{$script}' {$class}><div>" . "{$optionshtml}<input type='submit' value='{$name}' />" . "{$extrahtml}</div></form>"; }
/** * Merges the contents of this discussion into another discussion. * @param mod_forumng_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 $DB; $transaction = $DB->start_delegated_transaction(); // Delete search data for the source discussion $this->ismakingsearchchange = true; $root = $this->get_root_post(); $root->search_update(); $root->search_update_children(); $this->ismakingsearchchange = false; // Update parent post id of root post $record = new stdClass(); $record->id = $this->discussionfields->postid; $record->parentpostid = $targetdiscussion->discussionfields->postid; $DB->update_record('forumng_posts', $record); // Move all posts into new discussion $DB->execute("UPDATE {forumng_posts} SET discussionid = ? WHERE discussionid = ?", array($targetdiscussion->get_id(), $this->get_id())); // Delete this discussion $DB->delete_records('forumng_discussions', array('id' => $this->discussionfields->id)); // Attachments are OK because they are still in the same context, postid // etc (note this would NOT be the case if we allowed merging between // forums). if ($this->get_forum()->get_id() != $targetdiscussion->get_forum()->get_id()) { throw new coding_exception('Cannot merge into different forum'); } // 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); // Update the search data for the target discussion after the merge $newroot = $targetdiscussion->get_root_post(); $newroot->search_update(); $newroot->search_update_children(); if ($log) { $this->log('merge discussion', 'd' . $this->get_id() . ' into d' . $targetdiscussion->get_id()); } $transaction->allow_commit(); $this->uncache(); $targetdiscussion->uncache(); }
/** * Displays a short version (suitable for including in discussion list) * of this discussion including a link to view the discussion and to * mark it read (if enabled). * @param mod_forumng_discussion $discussion Discussion * @param int $groupid Group ID for display; may be NO_GROUPS or ALL_GROUPS * @param bool $last True if this is the last item in the list * @return string HTML code to print out for this discussion */ public function render_discussion_list_item(mod_forumng_discussion $discussion, $groupid, $last) { global $CFG, $USER; $showgroups = $groupid == mod_forumng::ALL_GROUPS; // Work out CSS classes to use for discussion $classes = ''; $alts = array(); $icons = array(); if ($discussion->is_deleted()) { $classes .= ' forumng-deleted'; $alts[] = get_string('alt_discussion_deleted', 'forumng'); $icons[] = array(); // No icon, text will be output on its own } if (!$discussion->is_within_time_period()) { $classes .= ' forumng-timeout'; $icon = 'timeout'; $alts[] = get_string('alt_discussion_timeout', 'forumng'); $icons[] = array('timeout', 'mod_forumng'); } if ($discussion->is_sticky()) { $classes .= ' forumng-sticky'; $alts[] = get_string('alt_discussion_sticky', 'forumng'); $icons[] = array('sticky', 'mod_forumng'); } if ($discussion->is_locked()) { $classes .= ' forumng-locked'; $alts[] = get_string('alt_discussion_locked', 'forumng'); $icons[] = array('i/unlock', 'moodle'); } // Classes for Moodle table styles static $rownum = 0; $classes .= ' r' . $rownum; $rownum = 1 - $rownum; if ($last) { $classes .= ' lastrow'; } $courseid = $discussion->get_forum()->get_course_id(); // Start row $canmarkread = $discussion->get_forum()->can_mark_read(); if ($canmarkread) { $unreadposts = $discussion->get_num_unread_posts(); $classes = $unreadposts ? $classes . ' forumng-discussion-unread' : $classes; } $result = "<tr id='discrow_{$discussion->get_id()}' class='forumng-discussion-short{$classes}'>"; // Get any tags. $tags = $discussion->get_tags(); $taglinks = ''; $linkparams = $discussion->get_forum()->get_link_params(mod_forumng::PARAM_HTML); if ($tags) { $taglinks = "<div class='forumng_discuss_tags'>Tags: "; // Unlist them. foreach ($tags as $key => $value) { $taglinks .= "<a href='view.php?{$linkparams}&tag={$key}'>{$value}</a>, "; } $taglinks .= "</div>"; } // Subject, with icons $result .= "<td class='forumng-subject cell c0'>"; foreach ($icons as $index => $icon) { $alt = $alts[$index]; if ($icon) { $url = $this->pix_url($icon[0], $icon[1]); $result .= "<img src='{$url}' alt='{$alt}' title='{$alt}' /> "; } else { $result .= "<span class='accesshide'>{$alt}:</span> "; } } $result .= "<a href='discuss.php?" . $discussion->get_link_params(mod_forumng::PARAM_HTML) . "'>" . format_string($discussion->get_subject(true), true, $courseid) . "</a>{$taglinks}</td>"; // Author. $result .= $this->render_discussion_list_item_author($discussion, $courseid); $num = 2; // Group if ($showgroups) { $result .= '<td class="cell c' . $num . '">' . $discussion->get_group_name() . '</td>'; $num++; } // Number of posts $result .= '<td class="cell c' . $num . '">' . $discussion->get_num_posts() . '</td>'; $num++; // Number of unread posts if ($canmarkread) { $result .= '<td class="cell forumng-unreadcount c3">'; if ($unreadposts) { $result .= '<a href="discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_HTML) . '#firstunread">' . $unreadposts . '</a>' . '<form method="post" action="markread.php"><div> ' . $discussion->get_link_params(mod_forumng::PARAM_FORM) . '<input type="hidden" name="back" value="view" />' . '<input type="image" title="' . get_string('markdiscussionread', 'forumng') . '" src="' . $this->pix_url('clear', 'mod_forumng') . '" ' . 'class="iconsmall" alt="' . get_string('markdiscussionread', 'forumng') . '" /></div></form>'; } else { $result .= $unreadposts; } $result .= '</td>'; $num = 4; } // Update last post user profile link. // Last post. $lastpostcell = $this->render_discussion_list_item_lastpost($discussion, $discussion->get_last_post_anon(), $num); $result .= $lastpostcell . "</tr>"; return $result; }
/** * 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 mod_forumng_post $post Post object * @param mod_forumng_post $inreplyto Parent post * @param mod_forumng_discussion $discussion Discus * @param mod_forumng $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]->forumngid = -1; // Get header text $headerdata = new object(); $headerdata->sitename = format_string($course->fullname, true); $headerdata->userprefs = $CFG->wwwroot . '/user/edit.php?id=' . $user->id . '&course=' . $course->id; $userdigests[$user->id]->text = get_string('digestmailheader', 'forumng', $headerdata) . "\n\n"; // Get header HTML $html = "<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]->forumngid != $forum->get_id()) { $userdigests[$user->id]->forumngid = $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(mod_forumng::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(mod_forumng::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; }
/** * 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 mod_forumng_discussion $discussion Discussion object (intended only * for calls via the mod_forumng_discussion method) * @return array Array of mod_forumng_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 $whereparams = array(); if ($discussion) { $where = 'fd.id = ?'; $whereparams[] = $discussion->get_id(); } else { $where = 'fd.forumngid = ?'; $whereparams[] = $this->get_id(); if ($this->get_group_mode() && $groupid != self::ALL_GROUPS) { $where .= ' AND fd.groupid = ?'; $whereparams[] = $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 < ?)" . " AND (fd.timeend = 0 OR fd.timeend > ?)"; $whereparams[] = $now; $whereparams[] = $now; $postrecs = mod_forumng_post::query_posts($where, $whereparams, '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 mod_forumng_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; } list($discussionpart, $discussionpartparams) = mod_forumng_utils::get_in_array_sql('fd.id', $discussionids); $rs = mod_forumng_discussion::query_discussions($discussionpart, $discussionpartparams, -1, 'id'); // Build the discussion and post objects $posts = array(); foreach ($rs as $rec) { $discussion = new mod_forumng_discussion($this, $rec, true, -1); if ($discussion->can_view($userid)) { foreach ($discussionposts[$discussion->get_id()] as $postid) { $post = new mod_forumng_post($discussion, $postrecs[$postid], null); $posts[$postid] = $post; } } } $rs->close(); // 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; }