public function display($discussion) { // Obtain list of other forums in this course where the user has the // 'move discussion' feature $course = $discussion->get_forum()->get_course(); $modinfo = get_fast_modinfo($course); $results = array(); foreach ($modinfo->instances['forumng'] as $other) { // Don't let user move discussion to its current forum if ($other->instance == $discussion->get_forum()->get_id() || $other->id == $discussion->get_forum()->get_course_module_id()) { continue; } $othercontext = context_module::instance($other->id); if (has_capability('mod/forumng:movediscussions', $othercontext)) { $results[$other->id] = $other->name; } } if (count($results) == 0) { return ''; } // Make list alphabetical uasort($results, array('forumngfeature_move', 'sort_ignore_case')); // Build select using the list $out = mod_forumng_utils::get_renderer(); $select = html_writer::select($results, 'target', '', array('' => get_string('movethisdiscussionto', 'forumngfeature_move'))); return '<form method="post" action="feature/move/move.php"><div>' . $discussion->get_link_params(mod_forumng::PARAM_FORM) . $select . '<input class="forumng-zero-disable" ' . 'type="submit" value="' . get_string('move') . '" /></div></form>'; }
public function apply($discussion, $all, $selected, $formdata) { global $COURSE, $USER, $CFG, $PAGE; $d = $discussion->get_id(); $forum = $discussion->get_forum(); $PAGE->set_pagelayout('embedded'); $out = mod_forumng_utils::get_renderer(); print $out->header(); $backlink = new moodle_url('/mod/forumng/discuss.php', $discussion->get_link_params_array()); print html_writer::start_tag('div', array('class' => 'forumng-printable-header')); print html_writer::tag('div', link_arrow_left($discussion->get_subject(), $backlink), array('class' => 'forumng-printable-backlink')); print html_writer::tag('div', get_string('printedat', 'forumngfeature_print', userdate(time())), array('class' => 'forumng-printable-date')); print html_writer::tag('div', '', array('class' => 'clearer')); print "\n"; print $out->box(get_string('back', 'forumngfeature_print', $backlink->out()), 'generalbox forumng-donotprint'); print html_writer::start_tag('div', array('class' => 'forumng-showprintable')); if ($all) { print $out->render_discussion($discussion, array(mod_forumng_post::OPTION_NO_COMMANDS => true, mod_forumng_post::OPTION_CHILDREN_EXPANDED => true, mod_forumng_post::OPTION_PRINTABLE_VERSION => true)); } else { $allhtml = ''; $alltext = ''; $discussion->build_selected_posts_email($selected, $alltext, $allhtml, array(mod_forumng_post::OPTION_PRINTABLE_VERSION)); print $allhtml; } print html_writer::end_tag('div'); $forum->print_js(0, false); print $out->footer(); }
/** * Saves a new draft message. * @param int $forumngid ID of forum * @param int $groupid Group ID (null if none) * @param int $parentpostid ID of post this is in reply to, or 0 for * a new discussion * @param string $subject Subject of draft post * @param string $message Message of draft post * @param int $messageformat Format (FORMAT_xx) of message * @param bool $attachments True if draft contains attachments * @param string $options Options (null if none) * @param int $userid User ID or 0 for current * @return int ID of new draft */ public static function save_new($forum, $groupid, $parentpostid, $subject, $message, $messageformat, $attachments, $options, $userid = 0) { global $DB; $userid = mod_forumng_utils::get_real_userid($userid); $serializedoptions = $options ? serialize($options) : null; $record = (object) array('userid' => $userid, 'forumngid' => $forum->get_id(), 'parentpostid' => $parentpostid ? $parentpostid : null, 'subject' => $subject, 'message' => $message, 'messageformat' => $messageformat, 'attachments' => $attachments ? 1 : 0, 'saved' => time(), 'groupid' => $groupid, 'options' => $serializedoptions); return $DB->insert_record('forumng_drafts', $record); }
public function get_unread_restriction_sql($forum, $userid = 0) { $userid = mod_forumng_utils::get_real_userid($userid); // See if they're already allowed to view all discussions if ($forum->can_view_hidden($userid)) { return array('', array()); } // Otherwise restrict it return array('fpfirst.userid = ?', array($userid)); }
public function display($forum) { if (has_capability('forumngfeature/userposts:view', $forum->get_context())) { $name = get_string('viewpostsbyuser', 'forumngfeature_userposts'); $script = 'feature/userposts/list.php'; return parent::get_button($forum, $name, $script); } else { $name = get_string('viewownposts', 'forumngfeature_userposts'); $script = 'feature/userposts/user.php'; return parent::get_button($forum, $name, $script, false, array('user' => mod_forumng_utils::get_real_userid())); } }
public function display($forum) { $out = mod_forumng_utils::get_renderer(); // Work out current status $manualmark = !mod_forumng::mark_read_automatically(); $current = get_string($manualmark ? 'manualmark_manual' : 'manualmark_auto', 'forumngfeature_manualmark'); // Make a help button $change = get_string('manualmark_change', 'forumngfeature_manualmark'); $helpbutton = $out->help_icon('manualmark_change', 'forumngfeature_manualmark'); // Get the button form $params = $forum->get_link_params_array(); return parent::get_button($forum, $change, 'feature/manualmark/change.php', true, $params, $helpbutton, 'forumng-manualmark', $current . ' ', 'forumng-button-to-link'); }
function get_forumng_deleted_discussion_posts($forum, $groupid = 0, $deleteuserid = 0, $creatorid = 0) { $forumngid = $forum->get_id(); // Get deleted posts for this forum by discussion. $rows = get_deleted_posts_for_forumng($forumngid, $groupid, $deleteuserid, $creatorid); $prevdiscussionid = 0; $discussioncount = 0; $deletedpostscount = 0; $result = array(); foreach ($rows as $rec) { $discussionfields = mod_forumng_utils::extract_subobject($rec, 'fd_'); if ($discussionfields->id != $prevdiscussionid) { $discussion = new mod_forumng_discussion($forum, $discussionfields, false, -1); $prevdiscussionid = $discussionfields->id; } $result[$rec->id] = new mod_forumng_post($discussion, $rec); } return $result; }
function definition() { global $CFG, $USER; $mform = $this->_form; $course = $this->_customdata; // Query for supported forums $forums = mod_forumng_utils::get_convertible_forums($course); $forumoptions = array(); foreach ($forums as $forum) { $forumoptions[$forum->id] = $forum->name; } $mform->addElement('static', '', '', get_string('convert_info', 'forumng')); $select = $mform->addElement('select', 'forums', get_string('modulenameplural', 'forum'), $forumoptions); $select->setMultiple(true); $mform->addElement('checkbox', 'nodata', '', get_string('convert_nodata', 'forumng')); $mform->addElement('static', '', '', get_string('convert_warning', 'forumng')); $mform->addElement('checkbox', 'hide', '', get_string('convert_hide', 'forumng')); $this->add_action_buttons(true, get_string('convert_title', 'forumng')); $mform->addElement('hidden', 'course', $this->_customdata->id); }
/** * Library for Atom feeds, sort of like the system RSS library. (Originally * by Matt Clarkson from Catalyst.) * @package mod * @subpackage forumng * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function atom_standard_header($uniqueid, $link, $updated, $title = NULL, $description = NULL) { global $CFG, $USER; $status = true; $result = ""; if (!($site = get_site())) { $status = false; } if ($status) { //Calculate title, link and description if (empty($title)) { $title = format_string($site->fullname); } //xml headers $result .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; $result .= "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"; //open the channel //write channel info $result .= atom_full_tag('id', 1, false, htmlspecialchars($uniqueid)); $result .= atom_full_tag('updated', 1, false, date_format_rfc3339($updated)); $result .= atom_full_tag('title', 1, false, htmlspecialchars(html_to_text($title))); $result .= atom_full_tag('link', 1, false, null, array('href' => $link, 'rel' => 'self')); if (!empty($description)) { $result .= atom_full_tag('subtitle', 1, false, $description); } $result .= atom_full_tag('generator', 1, false, 'Moodle'); $today = getdate(); $result .= atom_full_tag('rights', 1, false, '© ' . $today['year'] . ' ' . format_string($site->fullname)); //write image info $out = mod_forumng_utils::get_renderer(); $atompix = $out->pix_url('/i/rsssitelogo'); //write the info $result .= atom_full_tag('logo', 1, false, $atompix); } if (!$status) { return false; } else { return $result; } }
public function display($discussion) { require_once dirname(__FILE__) . '/lib.php'; if (is_a($discussion, 'mod_forumng_discussion')) { // Obtain list of other forums in this course where the user has the // 'move discussion' feature. $course = $discussion->get_forum()->get_course(); $modinfo = get_fast_modinfo($course); $results = array(); foreach ($modinfo->instances['forumng'] as $other) { // Don't let user move discussion to its current forum. if ($other->instance == $discussion->get_forum()->get_id() || $other->id == $discussion->get_forum()->get_course_module_id()) { continue; } $othercontext = context_module::instance($other->id); if (has_capability('mod/forumng:movediscussions', $othercontext)) { $results[$other->id] = $other->name; } } if (count($results) == 0) { return ''; } // Make list alphabetical. uasort($results, 'sort_ignore_case'); // Build select using the list. $out = mod_forumng_utils::get_renderer(); $select = html_writer::select($results, 'target', '', array('' => get_string('movethisdiscussionto', 'forumngfeature_move'))); return '<form method="post" action="feature/move/move.php"><div>' . $discussion->get_link_params(mod_forumng::PARAM_FORM) . $select . '<input class="forumng-zero-disable" ' . 'type="submit" value="' . get_string('move') . '" /></div></form>'; } else { // Display button. $params['exclude'] = 'forumng-deleted'; $excludedget = array_merge($params, $_GET); if (is_a($discussion, 'mod_forumng')) { return forumngfeature_discussion_list::get_button($discussion, get_string('move', 'forumngfeature_move'), 'feature/move/moveall.php', false, $excludedget, '', 'forumng-dselectorbutton', '', ''); } } }
/** * Returns all posts in this forum by the given user within the given group. * @param int $userid * @param int $groupid * @param string $order Sort order; the default is fp.id - note this is preferable * to fp.timecreated because it works correctly if there are two posts in * the same second * @return array Array of mod_forumng_post objects */ public function get_all_posts_by_user($userid, $groupid, $order = 'fp.id') { $where = 'fd.forumngid = ? AND fp.userid = ? AND fp.oldversion = 0 AND fp.deleted = 0'; $whereparams = array($this->get_id(), $userid); if ($groupid != self::NO_GROUPS && $groupid != self::ALL_GROUPS) { $where .= ' AND (fd.groupid = ? OR fd.groupid IS NULL)'; $whereparams[] = $groupid; } $result = array(); $posts = mod_forumng_post::query_posts($where, $whereparams, $order, false, false, true, 0, true, true); foreach ($posts as $fields) { $discussionfields = mod_forumng_utils::extract_subobject($fields, 'fd_'); $discussion = new mod_forumng_discussion($this, $discussionfields, false, -1); $result[$fields->id] = new mod_forumng_post($discussion, $fields); } return $result; }
$initialvalues->message['itemid'] = $messagedraftitemid; } if ($edit || $draft) { $mform->set_data($initialvalues); } else { $draftitemid = file_get_submitted_draft_itemid('attachments'); file_prepare_draft_area($draftitemid, $filecontext->id, 'mod_forumng', 'attachment', null, $fileoptions); $initialvalues->attachments = $draftitemid; $messagedraftitemid = file_get_submitted_draft_itemid('message'); file_prepare_draft_area($messagedraftitemid, $filecontext->id, 'mod_forumng', 'message', 0, $fileoptions); $initialvalues->message = array('text' => '', 'format' => editors_get_preferred_format(), 'itemid' => $messagedraftitemid); $mform->set_data($initialvalues); } // Require JavaScript (form.js). $forum->print_form_js(); // Print form $mform->display(); // In iframe mode, inform parent that iframe has loaded. if ($iframe) { $PAGE->requires->js_init_code('window.parent.iframe_has_loaded(window);', true); } // Display footer print $out->footer(); } } } catch (Exception $e) { // Add special entry to log mod_forumng_utils::log_exception($e); // Let default exception handler cope with it throw $e; }
/** * Displays a flagged item. * @param mod_forumng_post $post * @param bool $last * @return string HTML code for table row */ public function render_flagged_list_item($post, $last) { global $CFG; // Classes for Moodle table styles static $rownum = 0; $classes = ' r' . $rownum; $rownum = 1 - $rownum; if ($last) { $classes .= ' lastrow'; } $result = '<tr class="' . $classes . '">'; // Post cell $result .= '<td class="cell c0">'; // Show flag icon. (Note: I tried to use before this so the // icon never ends up on a line of its own, but it does not work.) $result .= ' <form class="forumng-flag" action="flagpost.php" method="post"><div>' . '<input type="hidden" name="p" value="' . $post->get_id() . '" />' . '<input type="hidden" name="back" value="view" />' . '<input type="hidden" name="flag" value="0" />' . '<input type="image" title="' . get_string('clearflag', 'forumng') . '" src="' . $this->pix_url('flag.on', 'mod_forumng') . '" alt="' . get_string('flagon', 'forumng') . '" /></div></form> '; // Get post URL $discussion = $post->get_discussion(); $link = '<a href="discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_HTML) . '#p' . $post->get_id() . '">'; // Get post summary $summary = self::get_post_summary($post->get_subject(), $post->get_formatted_message()); $result .= $link . $summary . '</a>'; $result .= '<small> ' . get_string('postby', 'forumng', $post->get_forum()->display_user_link($post->get_user())) . '</small></td>'; // Discussion cell. $result .= '<td class="cell c1"><a href="discuss.php?' . $discussion->get_link_params(mod_forumng::PARAM_HTML) . '">' . format_string($discussion->get_subject()) . '</a></td>'; // Date cell. $result .= '<td class="cell c2 lastcol">' . mod_forumng_utils::display_date($post->get_created()) . '</td></tr>'; return $result; }
/** * Displays the discussion page. * @param mod_forumng_discussion $discussion Discussion */ public function print_discussion_page($discussion) { global $PAGE; $out = mod_forumng_utils::get_renderer(); $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) || $PAGE->devicetypeinuse == 'legacy'; // 'Expand all' option (always chosen for non-JS browsers) $collapseall = optional_param('collapse', 0, PARAM_INT); if (!$collapseall && !$expandall && $PAGE->devicetypeinuse == 'mobile') { $collapseall = 1; } // Link back to first unread post if there is one print $discussion->display_unread_skip_link(); // 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[mod_forumng_post::OPTION_CHILDREN_EXPANDED] = true; } if ($collapseall) { $options[mod_forumng_post::OPTION_CHILDREN_COLLAPSED] = true; } $content = $out->render_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[mod_forumng_post::OPTION_READ_TIME] = $previousread; // Display expand all option if there are any 'Expand' links in content $fakedate = '&timeread=' . $previousread; print '<div id="forumng-expandall">'; $showexpandall = preg_match('~<a [^>]*href="discuss\\.php\\?d=[0-9]+[^"]*&expand=1#p[0-9]+">~', $content); // Note: On bad browsers we always expand all posts $showcollapseall = preg_match('~<div class="forumng-post forumng-full.*<div class="forumng-post forumng-full~s', $content) && $PAGE->devicetypeinuse != 'legacy'; if ($showexpandall) { print '<a class="forumng-expandall-link" href="' . $discussion->get_url(mod_forumng::PARAM_HTML) . '&expand=1' . $fakedate . '">' . get_string('expandall', 'forumng') . '</a>'; if ($showcollapseall) { print '<span class="forumng-dot-separator"> • </span>'; } } if ($showcollapseall) { print '<a class="forumng-collapseall-link" href="' . $discussion->get_url(mod_forumng::PARAM_HTML) . '&collapse=1' . $fakedate . '">' . get_string('collapseall', 'forumng') . '</a> '; } print '</div>'; // Display content print $content; // Link back to forum print $discussion->display_link_back_to_forum(); // Display discussion features (row of buttons) print $discussion->display_forumngfeature_discussions(); // 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 (mod_forumng::mark_read_automatically()) { $discussion->mark_read(); } }
/** * Get search results. * @param object $course * @param string $author * @param int $daterangefrom * @param int $daterangeto * @param int $page * @param int $resultsperpage (FORUMNG_SEARCH_RESULTSPERPAGE used as constant) * @return object */ function forumng_get_results_for_all_forums($course, $author = null, $daterangefrom = 0, $daterangeto = 0, $page, $asmoderator = false, $resultsperpage = FORUMNG_SEARCH_RESULTSPERPAGE) { $before = microtime(true); global $CFG, $DB, $USER; require_once $CFG->dirroot . '/mod/forumng/mod_forumng.php'; // Get all forums $modinfo = get_fast_modinfo($course); $visibleforums = array(); $accessallgroups = array(); foreach ($modinfo->cms as $cmid => $cm) { if ($cm->modname === 'forumng' && $cm->uservisible) { $visibleforums[$cm->instance] = $cm->groupmode; // Check access all groups for this forum, if they have it, add to list $forum = mod_forumng::get_from_id($cm->instance, mod_forumng::CLONE_DIRECT); if ($forum->get_group_mode() == SEPARATEGROUPS) { if (has_capability('moodle/site:accessallgroups', $forum->get_context())) { $accessallgroups[] = $cm->instance; } } } } $forumngids = array_keys($visibleforums); $separategroupsforumngids = array_keys($visibleforums, SEPARATEGROUPS); $params = array(); list($inforumngids, $moreparams) = mod_forumng_utils::get_in_array_sql('d.forumngid', $forumngids); $where = "WHERE {$inforumngids}"; $params = array_merge($params, $moreparams); list($inseparategroups, $moreparams) = mod_forumng_utils::get_in_array_sql('d.forumngid', $separategroupsforumngids); $where .= " AND ((NOT ({$inseparategroups}))"; $params = array_merge($params, $moreparams); list($inaccessallgroups, $moreparams) = mod_forumng_utils::get_in_array_sql('d.forumngid', $accessallgroups); $where .= " OR {$inaccessallgroups}"; $params = array_merge($params, $moreparams); $where .= " OR gm.id IS NOT NULL"; $where .= " OR d.groupid IS NULL)"; // Note: Even if you have capability to view the deleted or timed posts, // we don't show them for consistency with the full-text search. $currenttime = time(); $where .= " AND (? >= d.timestart OR d.timestart = 0)"; $params[] = $currenttime; $where .= " AND (? < d.timeend OR d.timeend = 0)"; $params[] = $currenttime; // Exclude older post versions. $where .= " AND p.oldversion = 0 "; $where .= " AND d.deleted = 0 AND p.deleted = 0 "; if (!empty($author)) { $coursecontext = context_course::instance($course->id); $seeanon = has_capability('mod/forumng:postanon', $coursecontext); if ($asmoderator) { if ($seeanon) { $where .= " AND p.asmoderator > ? "; $params[] = mod_forumng::ASMODERATOR_NO; } else { $where .= " AND p.asmoderator = ? "; $params[] = mod_forumng::ASMODERATOR_IDENTIFY; } } else { if (!$seeanon) { $where .= " AND p.asmoderator != ? "; $params[] = mod_forumng::ASMODERATOR_ANON; } } } if ($author) { list($morewhere, $moreparams) = forumng_get_author_sql($author); $where .= $morewhere; $params = array_merge($params, $moreparams); } if ($daterangefrom && !is_array($daterangefrom)) { $where .= " AND p.modified>=?"; $params[] = $daterangefrom; } if ($daterangeto && !is_array($daterangeto)) { $where .= " AND p.modified<=?"; $params[] = $daterangeto; } $sql = "SELECT p.modified, p.id, p.discussionid, gm.id AS useringroup,\n p.userid, p.parentpostid, p.subject AS title, p.message AS summary, u.username,\n u.firstname, u.lastname, d.forumngid, d.groupid, p2.subject AS discussionsubject\n FROM {forumng_posts} p\n INNER JOIN {forumng_discussions} d ON d.id = p.discussionid\n INNER JOIN {forumng_posts} p2 ON p2.id = d.postid\n INNER JOIN {user} u ON p.userid = u.id\n LEFT JOIN {groups_members} gm ON gm.groupid = d.groupid AND gm.userid = {$USER->id}\n {$where}\n ORDER BY p.modified DESC, p.id ASC"; $results = new stdClass(); $results->success = 1; $results->numberofentries = 0; $results->done = 0; $posts = $DB->get_records_sql($sql, $params, $page, $resultsperpage); foreach ($posts as $post) { if (!$post->title) { // Ideally we would get the parent post that has a subject, but // this could involve a while loop that might make numeroous // queries, so instead, let's just use the discussion subject $post->title = get_string('re', 'forumng', $post->discussionsubject); } $post->title = s(strip_tags($post->title)); $post->summary = s(strip_tags(shorten_text($post->summary, 250))); $post->url = $CFG->wwwroot . "/mod/forumng/discuss.php?d={$post->discussionid}" . $forum->get_clone_param(mod_forumng::PARAM_PLAIN) . "#p{$post->id}"; } $results->results = $posts; $results->searchtime = microtime(true) - $before; $results->numberofentries = count($results->results); if (count($results->results) < $resultsperpage) { $results->done = 1; } else { if (!($extrapost = $DB->get_records_sql($sql, $params, $page + $resultsperpage, 1))) { $results->done = 1; } } return $results; }
public function definition() { global $CFG, $COURSE, $DB; $mform =& $this->_form; $coursecontext = context_course::instance($COURSE->id); $forumng = $this->_instance ? $DB->get_record('forumng', array('id' => $this->_instance)) : null; $this->clone = $forumng ? $forumng->originalcmid : 0; // If this is a clone, don't show the normal form if ($this->clone) { $mform->addElement('hidden', 'name', $forumng->name); if (!empty($CFG->formatstringstriptags)) { $mform->setType('name', PARAM_TEXT); } else { $mform->setType('name', PARAM_NOTAGS); } $mform->addElement('static', 'sharedthing', '', get_string('sharedinfo', 'forumng', $CFG->wwwroot . '/course/modedit.php?update=' . $this->clone . '&return=1')); $this->shared_definition_part($coursecontext); return; } $mform->addElement('header', 'general', get_string('general', 'form')); // Forum name $mform->addElement('text', 'name', get_string('forumname', 'forumng'), array('size' => '64')); if (!empty($CFG->formatstringstriptags)) { $mform->setType('name', PARAM_TEXT); } else { $mform->setType('name', PARAM_NOTAGS); } $mform->addRule('name', null, 'required', null, 'client'); $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); // Forum types $types = forumngtype::get_all(); $options = array(); foreach ($types as $type) { if ($type->is_user_selectable()) { $options[$type->get_id()] = $type->get_name(); } } $mform->addElement('select', 'type', get_string('forumtype', 'forumng'), $options); $mform->addHelpButton('type', 'forumtype', 'forumng'); $mform->setDefault('type', 'general'); $this->standard_intro_elements(get_string('forumintro', 'forumng')); // Subscription option displays only if enabled at site level if ($CFG->forumng_subscription == -1) { $options = mod_forumng::get_subscription_options(); $mform->addElement('select', 'subscription', get_string('subscription', 'forumng'), $options); $mform->setDefault('subscription', mod_forumng::SUBSCRIPTION_PERMITTED); $mform->addHelpButton('subscription', 'subscription', 'forumng'); } else { // Hidden element contains default value (not used anyhow) $mform->addElement('hidden', 'subscription', mod_forumng::SUBSCRIPTION_PERMITTED); $mform->setType('subscription', PARAM_INT); } // Max size of attachments $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes); $choices[-1] = get_string('uploadnotallowed'); $mform->addElement('select', 'attachmentmaxbytes', get_string('attachmentmaxbytes', 'forumng'), $choices); $mform->addHelpButton('attachmentmaxbytes', 'attachmentmaxbytes', 'forumng'); $mform->setDefault('attachmentmaxbytes', $CFG->forumng_attachmentmaxbytes); // Email address for reporting unacceptable post for this forum, default is blank. $mform->addElement('text', 'reportingemail', get_string('reportingemail', 'forumng'), array('size' => 64)); $mform->setType('reportingemail', PARAM_NOTAGS); $mform->addRule('reportingemail', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); $mform->addHelpButton('reportingemail', 'reportingemail', 'forumng'); $mform->addElement('checkbox', 'canpostanon', get_string('canpostanon', 'forumng')); $mform->addHelpButton('canpostanon', 'canpostanon', 'forumng'); // Atom/RSS feed on/off/discussions-only if ($CFG->enablerssfeeds && !empty($CFG->forumng_enablerssfeeds)) { if ($CFG->forumng_feedtype == -1 || $CFG->forumng_feeditems == -1) { $mform->addElement('header', '', get_string('feeds', 'forumng')); } if ($CFG->forumng_feedtype == -1) { $mform->addElement('select', 'feedtype', get_string('feedtype', 'forumng'), mod_forumng::get_feedtype_options()); $mform->setDefault('feedtype', mod_forumng::FEEDTYPE_ALL_POSTS); $mform->addHelpButton('feedtype', 'feedtype', 'forumng'); } // Atom/RSS feed item count if ($CFG->forumng_feeditems == -1) { $mform->addElement('select', 'feeditems', get_string('feeditems', 'forumng'), mod_forumng::get_feeditems_options()); $mform->setDefault('feeditems', 20); $mform->addHelpButton('feeditems', 'feeditems', 'forumng'); } } // Add tagging to discussions. if ($CFG->usetags) { $mform->addElement('header', '', get_string('tagging', 'forumng')); // Enable tagging. $mform->addElement('checkbox', 'tags', get_string('enabletagging', 'forumng')); $mform->addHelpButton('tags', 'tagging', 'forumng'); // Add 'Set' forumng wide named tags to discussion tagging dropdowns. $settags = null; if ($forumng) { $settags = mod_forumng::get_set_tags($this->_instance); // Create 'Set' forumng wide tags. $mform->addElement('tags', 'settags', get_string('setforumtags', 'forumng'), array('display' => 'noofficial')); $mform->disabledIf('settags', 'tags', 'notchecked'); $mform->setType('settags', PARAM_TAGLIST); $mform->setDefault('settags', $settags); $mform->addHelpButton('settags', 'settags', 'forumng'); } } // Ratings header /*///////////////*/ $mform->addElement('header', '', get_string('ratings', 'forumng')); $options = array(mod_forumng::FORUMNG_NO_RATING => get_string('noratings', 'forumng'), mod_forumng::FORUMNG_RATING_OBSOLETE => get_string('forumngratingsobsolete', 'forumng'), mod_forumng::FORUMNG_STANDARD_RATING => get_string('standardratings', 'forumng')); $mform->addElement('select', 'enableratings', get_string('enableratings', 'forumng'), $options); $mform->addHelpButton('enableratings', 'enableratings', 'forumng'); // Scale $mform->addElement('modgrade', 'ratingscale', get_string('scale'), null, true); $mform->disabledIf('ratingscale', 'enableratings', 'eq', 0); $mform->setDefault('ratingscale', 5); // From/until times $mform->addElement('date_time_selector', 'ratingfrom', get_string('ratingfrom', 'forumng'), array('optional' => true)); $mform->disabledIf('ratingfrom', 'enableratings', 'eq', 0); $mform->addElement('date_time_selector', 'ratinguntil', get_string('ratinguntil', 'forumng'), array('optional' => true)); $mform->disabledIf('ratinguntil', 'enableratings', 'eq', 0); $mform->addElement('text', 'ratingthreshold', get_string('ratingthreshold', 'forumng')); $mform->setType('ratingthreshold', PARAM_INT); $mform->setDefault('ratingthreshold', 1); $mform->addRule('ratingthreshold', get_string('error_ratingthreshold', 'forumng'), 'regex', '/[1-9][0-9]*/', 'client'); $mform->addHelpButton('ratingthreshold', 'ratingthreshold', 'forumng'); $mform->disabledIf('ratingthreshold', 'enableratings', 'neq', mod_forumng::FORUMNG_RATING_OBSOLETE); // Grading. $mform->addElement('header', '', get_string('grading', 'forumng')); $mform->addElement('select', 'grading', get_string('grade'), mod_forumng::get_grading_options()); $mform->setDefault('grading', mod_forumng::GRADING_NONE); $mform->addHelpButton('grading', 'grading', 'forumng'); $mform->addElement('modgrade', 'gradingscale', get_string('gradingscale', 'forumng')); $mform->disabledIf('gradingscale', 'grading', 'ne', mod_forumng::GRADING_MANUAL); $mform->setDefault('gradingscale', 5); // Blocking header /*////////////////*/ $mform->addElement('header', '', get_string('limitposts', 'forumng')); // Post dates $mform->addElement('date_time_selector', 'postingfrom', get_string('postingfrom', 'forumng'), array('optional' => true)); $mform->addElement('date_time_selector', 'postinguntil', get_string('postinguntil', 'forumng'), array('optional' => true)); // User limits $limitgroup = array(); $limitgroup[] = $mform->createElement('checkbox', 'enablelimit', ''); $options = mod_forumng::get_max_posts_period_options(); $limitgroup[] = $mform->createElement('text', 'maxpostsblock', '', array('size' => 3)); $limitgroup[] = $mform->createElement('static', 'staticthing', '', ' ' . get_string('postsper', 'forumng') . ' '); $limitgroup[] = $mform->createElement('select', 'maxpostsperiod', '', $options); $mform->addGroup($limitgroup, 'limitgroup', get_string('enablelimit', 'forumng')); $mform->disabledIf('limitgroup[maxpostsblock]', 'limitgroup[enablelimit]'); $mform->disabledIf('limitgroup[maxpostsperiod]', 'limitgroup[enablelimit]'); $mform->addHelpButton('limitgroup', 'enablelimit', 'forumng'); $mform->setType('limitgroup[maxpostsblock]', PARAM_INT); $mform->setDefault('limitgroup[maxpostsblock]', '10'); // Remove old discussion $options = array(); $options[0] = get_string('removeolddiscussionsdefault', 'forumng'); for ($i = 1; $i <= 36; $i++) { $options[$i * 2592000] = $i > 1 ? get_string('nummonths', 'moodle', $i) : get_string('onemonth', 'forumng'); } $mform->addElement('header', '', get_string('removeolddiscussions', 'forumng')); $mform->addElement('select', 'removeafter', get_string('removeolddiscussionsafter', 'forumng'), $options); $mform->addHelpButton('removeafter', 'removeolddiscussions', 'forumng'); $options = array(); $options[0] = get_string('deletepermanently', 'forumng'); $options[-1] = get_string('automaticallylock', 'forumng'); $modinfo = get_fast_modinfo($COURSE); $targetforumngid = $this->_instance ? $this->_instance : 0; // Add all instances to drop down if the user can access them and // it's not the same as the current forum if (array_key_exists('forumng', $modinfo->instances)) { foreach ($modinfo->instances['forumng'] as $info) { if ($info->uservisible && $targetforumngid != $info->instance) { $options[$info->instance] = $info->name; } } } $mform->addElement('select', 'removeto', get_string('withremoveddiscussions', 'forumng'), $options); $mform->disabledIf('removeto', 'removeafter', 'eq', 0); $mform->addHelpButton('removeto', 'withremoveddiscussions', 'forumng'); // Sharing options are advanced and for administrators only if ($CFG->forumng_enableadvanced && has_capability('mod/forumng:addinstance', context_system::instance())) { $mform->addElement('header', '', get_string('sharing', 'forumng')); $mform->addElement('advcheckbox', 'shared', get_string('shared', 'forumng')); $mform->addHelpButton('shared', 'shared', 'forumng'); // Only when creating a forum, you can choose to make it a clone if (!$this->_instance) { $sharegroup = array(); $sharegroup[] = $mform->createElement('checkbox', 'useshared', ''); $sharegroup[] = $mform->createElement('text', 'originalcmidnumber', ''); $mform->setType('usesharedgroup[originalcmidnumber]', PARAM_RAW); $mform->addGroup($sharegroup, 'usesharedgroup', get_string('useshared', 'forumng')); $mform->disabledIf('usesharedgroup[originalcmidnumber]', 'usesharedgroup[useshared]', 'notchecked'); $mform->addHelpButton('usesharedgroup', 'useshared', 'forumng'); } } // Do definition that is shared with clone version of form $this->shared_definition_part($coursecontext); if (count(mod_forumng_utils::get_convertible_forums($COURSE)) > 0 && !$this->_instance) { $mform->addElement('static', '', '', '<div class="forumng-convertoffer">' . get_string('offerconvert', 'forumng', $CFG->wwwroot . '/mod/forumng/convert.php?course=' . $COURSE->id) . '</div>'); } }
/** @return string User picture HTML (for post author) */ public function display_user_picture() { $out = mod_forumng_utils::get_renderer(); return $out->user_picture($this->get_user(), array('courseid' => $this->get_forum()->get_course_id())); }
/** * Returns all posts in this forum by the given user within the given group. * @param object $forum * @param int $userid * @param int $groupid * @param int $ratedstart * @param int $ratedend * @param string $order Sort order; the default is fp.id - note this is preferable * to fp.timecreated because it works correctly if there are two posts in * the same second * @param bool $hasrating if true only returns posts which ahve been rated * @return array Array of mod_forumng_post objects */ public function get_rated_posts_by_user($forum, $userid, $groupid, $order = 'fp.id', $ratedstart = null, $ratedend = null, $start = null, $end = null) { global $CFG, $USER; if ($forum->get_enableratings() != mod_forumng::FORUMNG_STANDARD_RATING) { return array(); } $where = 'fd.forumngid = ? AND fp.userid <> ? AND fp.oldversion = 0 AND fp.deleted = 0'; $whereparams = array($this->get_id(), $userid); if ($groupid != self::NO_GROUPS && $groupid != self::ALL_GROUPS) { $where .= ' AND (fd.groupid = ? OR fd.groupid IS NULL)'; $whereparams[] = $groupid; } if (!empty($start)) { $where .= ' AND fp.created >= ?'; $whereparams[] = $start; } if (!empty($end)) { $where .= ' AND fp.created <= ?'; $whereparams[] = $end; } $sqlselectstring = 'SELECT r.itemid FROM {rating} r WHERE r.itemid = fp.id AND r.ratingarea = \'post\' AND r.contextid = ? AND r.userid = ?'; $extraparams = array(); if (!empty($ratedstart)) { $sqlselectstring .= ' AND r.timemodified >= ?'; $extraparams[] = $ratedstart; } if (!empty($ratedend)) { $sqlselectstring .= ' AND r.timemodified <= ?'; $extraparams[] = $ratedend; } $where .= ' AND ' . self::select_exists($sqlselectstring); $whereparams[] = $this->get_context(true)->id; $whereparams[] = $userid; $whereparams = array_merge($whereparams, $extraparams); $result = array(); $posts = mod_forumng_post::query_posts($where, $whereparams, $order, false, false, true, 0, true, true); // Add standard ratings if enabled. if ($this->get_enableratings() == mod_forumng::FORUMNG_STANDARD_RATING) { require_once $CFG->dirroot . '/rating/lib.php'; // If grading is 'No grading' or 'Teacher grades students'. if ($this->get_grading() == mod_forumng::GRADING_NONE || $this->get_grading() == mod_forumng::GRADING_MANUAL) { // Set the aggregation method. if ($this->get_rating_scale() > 0) { $aggregate = RATING_AGGREGATE_AVERAGE; } else { $aggregate = RATING_AGGREGATE_COUNT; } } else { $aggregate = $this->get_grading(); } $ratingoptions = new stdClass(); $ratingoptions->context = $this->get_context(true); $ratingoptions->component = 'mod_forumng'; $ratingoptions->ratingarea = 'post'; $ratingoptions->items = $posts; $ratingoptions->aggregate = $aggregate; $ratingoptions->scaleid = $this->get_rating_scale(); $ratingoptions->userid = $USER->id; $ratingoptions->assesstimestart = $this->get_ratingfrom(); $ratingoptions->assesstimefinish = $this->get_ratinguntil(); $rm = new rating_manager(); $posts = $rm->get_ratings($ratingoptions); } foreach ($posts as $fields) { $discussionfields = mod_forumng_utils::extract_subobject($fields, 'fd_'); $discussion = new mod_forumng_discussion($this, $discussionfields, false, -1); $result[$fields->id] = new mod_forumng_post($discussion, $fields); } return $result; }
/** * Create output for post information (Title, date, user) * Returns content and user object (discussion poster, null if anon) * @param object $forum * @param object $discussion * @param object $post * @return array content html, poster user object */ public function render_usage_post_info($forum, $discussion, mod_forumng_post $post) { $user = $post->get_user(); $link = html_writer::link($post->get_url(), format_string($post->get_effective_subject())); $content = html_writer::div($link); $content .= html_writer::div(mod_forumng_utils::display_date($post->get_created())); $content .= html_writer::start_div('fng_userlink'); if ($post->get_asmoderator() == mod_forumng::ASMODERATOR_ANON && !$forum->can_post_anonymously()) { // Hide user details if anon post and user does not have permission to see. $user = null; } else { $content .= $forum->display_user_link($user) . ' '; } if ($post->get_asmoderator() != mod_forumng::ASMODERATOR_NO) { $content .= get_string('moderator', 'mod_forumng'); } $content .= html_writer::end_div(); return array($content, $user); }
private function mark_mailed($time) { global $DB; list($wheresql, $whereparams) = $this->get_query_where($time, 'forumng_posts'); $querychunk = $this->get_query_from() . $wheresql; $before = microtime(true); mtrace('Marking processed posts: ', ''); mod_forumng_utils::update_with_subquery_grrr_mysql("\nUPDATE\n {forumng_posts}\nSET\n mailstate = " . $this->get_target_mail_state() . "\nWHERE\n id %'IN'%", "SELECT fp.id {$querychunk}", $whereparams); mtrace(round(microtime(true) - $before, 1) . 's.'); unset_config($this->get_pending_flag_name(), 'forumng'); }
/** * Displays a Moodle standard paging bar for this result. * @param string $baseurl Base URL (may include page= if you like) * @return string HTML code for paging bar */ public function display_paging_bar($baseurl) { // Don't do anything if no pages if ($this->pagecount < 2) { return ''; } // Remove page= if included and append & $baseurl = preg_replace('~&page=[0-9]+~', '', $baseurl) . '&'; $out = mod_forumng_utils::get_renderer(); $result = $out->render(new paging_bar($this->pagecount, $this->page - 1, 1, htmlspecialchars($baseurl))); // This is really damn annoying but discussionlist pages start from 1 // not 0, so need to change the params $result = preg_replace_callback('~(&page=)([0-9]+)~', 'mod_forumng_discussion_list::munge_page_number', $result); return $result; }
/** * Used when selecting posts inside other SQL statements. * @param string $alias Alias of table to extract * @return string SQL select fields (no comma at start or end) */ static function select_post_fields($alias) { return mod_forumng_utils::select_fields(array('id', 'discussionid', 'parentpostid', 'userid', 'created', 'modified', 'deleted', 'important', 'mailstate', 'oldversion', 'edituserid', 'subject', 'message', 'messageformat', 'attachments'), $alias); }
/** * Gets URL for an Atom/RSS feed to this discussion. * @param int $feedformat FEEDFORMAT_xx constant * @param int $userid User ID or 0 for current * @return string URL for feed */ public function get_feed_url($feedformat, $userid = 0) { global $CFG; $userid = mod_forumng_utils::get_real_userid($userid); $groupid = $this->get_group_id(); return $CFG->wwwroot . '/mod/forumng/feed.php?' . $this->get_link_params(mod_forumng::PARAM_PLAIN) . '&user='******'&key=' . $this->get_forum()->get_feed_key($groupid, $userid) . '&format=' . ($feedformat == mod_forumng::FEEDFORMAT_RSS ? 'rss' : 'atom'); }
$inputdata = new stdClass(); $inputdata->query = $query; $inputdata->author = $author; $editform->set_data($inputdata); if ($editform->is_cancelled()) { if (isset($forum)) { $returnurl = $forum->get_url(mod_forumng::PARAM_PLAIN); } else { $returnurl = $CFG->wwwroot . '/course/view.php?id=' . $course->id; } redirect($returnurl, '', 0); } // Process form data. $data = $editform->get_data(); // Display header $out = mod_forumng_utils::get_renderer(); print $out->header(); $searchtitle = forumng_get_search_results_title($query, $data ? $data->author : '', $data ? $data->datefrom : 0, $data ? $data->dateto : 0); if (!$allforums) { // Display group selector if required groups_print_activity_menu($cm, $url); $groupid = mod_forumng::get_activity_group($cm, true); $forum->require_view($groupid, 0, true); print '<br/><br/>'; } $editform->display(); if ($data) { // Searching for free text with or without filtering author and date range. if ($query) { $result = new local_ousearch_search($query); if ($allforums) {
public static function delete_old_posts() { global $CFG, $DB; // Check if deletion is turned off if (empty($CFG->forumng_permanentdeletion)) { return; } mtrace('Beginning forum deleted/edit message cleanup...'); // Work out how long ago things have to have been 'deleted' before we // permanently delete them $deletebefore = time() - $CFG->forumng_permanentdeletion; // Handle all posts which were deleted (that long ago) or which are in // discussions which were deleted (that long ago) $mainparams = array(); $mainquery = "\nFROM\n {forumng_posts} fp\n INNER JOIN {forumng_discussions} fd ON fd.id = fp.discussionid\n INNER JOIN {forumng} f ON fd.forumngid = f.id\n INNER JOIN {course_modules} cm ON cm.instance = f.id AND cm.module =\n (SELECT id FROM {modules} WHERE name='forumng')\n INNER JOIN {context} x on x.instanceid=cm.id AND x.contextlevel=?\nWHERE\n (fp.deleted<>0 AND fp.deleted<? AND\n NOT EXISTS (SELECT id from {forumng_posts} where parentpostid = fp.id and deleted = 0))\n OR (fp.oldversion<>0 AND fp.modified<?)\n OR (fd.deleted<>0 AND fd.deleted<?)"; $idquery = "SELECT fp.id {$mainquery} "; $mainparams[] = CONTEXT_MODULE; $mainparams[] = $deletebefore; $mainparams[] = $deletebefore; $mainparams[] = $deletebefore; $before = microtime(true); mtrace('Message search: ', ''); $count = $DB->count_records_sql("SELECT COUNT(1) {$mainquery}", $mainparams); mtrace(round(microtime(true) - $before, 1) . 's'); if ($count == 0) { mtrace("No old deleted / edited messages to clean up."); } else { mtrace("Permanently deleting {$count} old deleted / edited messages."); } if ($count) { $before = microtime(true); mtrace('Database post deletion: ', ''); $transaction = $DB->start_delegated_transaction(); // Delete all ratings $DB->execute("DELETE FROM {forumng_ratings} WHERE postid IN ({$idquery})", $mainparams); // Delete all read post records. $DB->execute("DELETE FROM {forumng_read_posts} WHERE postid IN ({$idquery})", $mainparams); // Find all messages... $rs = $DB->get_recordset_sql("\nSELECT\n fp.id AS postid, x.id AS contextid, fp.attachments\n{$mainquery}", $mainparams); // Delete all attachments - this is very very slow (at least 1 query // per post being deleted), it could be done faster in the database // but I thought it might be safer to use the API $fs = get_file_storage(); foreach ($rs as $attachmentrecord) { // Delete both attachments & message attachments if ($attachmentrecord->attachments) { // Only if marked as existing $fs->delete_area_files($attachmentrecord->contextid, 'mod_forumng', 'attachment', $attachmentrecord->postid); } // Always (there is no marker for this one) $fs->delete_area_files($attachmentrecord->contextid, 'mod_forumng', 'message', $attachmentrecord->postid); } $rs->close(); // Delete all posts mod_forumng_utils::update_with_subquery_grrr_mysql("DELETE FROM {forumng_posts} WHERE id %'IN'%", $idquery, $mainparams); // Now delete all discussions $DB->execute("DELETE FROM {forumng_discussions} WHERE deleted<>0 AND deleted<?", array($deletebefore)); $transaction->allow_commit(); mtrace(round(microtime(true) - $before, 1) . 's'); } }