/** * Set up message and mail sinks, and set up other requirements for the * cron to be tested here. */ public function setUp() { global $CFG; $this->helper = new stdClass(); // Messaging is not compatible with transactions... $this->preventResetByRollback(); // Catch all messages $this->helper->messagesink = $this->redirectMessages(); $this->helper->mailsink = $this->redirectEmails(); // Confirm that we have an empty message sink so far. $messages = $this->helper->messagesink->get_messages(); $this->assertEquals(0, count($messages)); $messages = $this->helper->mailsink->get_messages(); $this->assertEquals(0, count($messages)); // Tell Moodle that we've not sent any digest messages out recently. $CFG->digestmailtimelast = 0; // And set the digest sending time to a negative number - this has // the effect of making it 11pm the previous day. $CFG->digestmailtime = -1; // Forcibly reduce the maxeditingtime to a one second to ensure that // messages are sent out. $CFG->maxeditingtime = 1; // We must clear the subscription caches. This has to be done both before each test, and after in case of other // tests using these functions. \mod_forum\subscriptions::reset_forum_cache(); \mod_forum\subscriptions::reset_discussion_cache(); }
/** * Observer for role_assigned event. * * @param \core\event\role_assigned $event * @return void */ public static function role_assigned(\core\event\role_assigned $event) { global $CFG, $DB; $context = context::instance_by_id($event->contextid, MUST_EXIST); // If contextlevel is course then only subscribe user. Role assignment // at course level means user is enroled in course and can subscribe to forum. if ($context->contextlevel != CONTEXT_COURSE) { return; } // Forum lib required for the constant used below. require_once $CFG->dirroot . '/mod/forum/lib.php'; $userid = $event->relateduserid; $sql = "SELECT f.id, f.course as course, cm.id AS cmid, f.forcesubscribe\n FROM {forum} f\n JOIN {course_modules} cm ON (cm.instance = f.id)\n JOIN {modules} m ON (m.id = cm.module)\n LEFT JOIN {forum_subscriptions} fs ON (fs.forum = f.id AND fs.userid = :userid)\n WHERE f.course = :courseid\n AND f.forcesubscribe = :initial\n AND m.name = 'forum'\n AND fs.id IS NULL"; $params = array('courseid' => $context->instanceid, 'userid' => $userid, 'initial' => FORUM_INITIALSUBSCRIBE); $forums = $DB->get_records_sql($sql, $params); foreach ($forums as $forum) { // If user doesn't have allowforcesubscribe capability then don't subscribe. $modcontext = context_module::instance($forum->cmid); if (has_capability('mod/forum:allowforcesubscribe', $modcontext, $userid)) { \mod_forum\subscriptions::subscribe_user($userid, $forum, $modcontext); } } }
$node->display = false; if ($node && $post->id != $discussion->firstpost) { $node->add(format_string($post->subject), $PAGE->url); } $PAGE->set_title("{$course->shortname}: " . format_string($discussion->name)); $PAGE->set_heading($course->fullname); $PAGE->set_button($searchform); $renderer = $PAGE->get_renderer('mod_forum'); echo $OUTPUT->header(); echo $OUTPUT->heading(format_string($forum->name), 2); echo $OUTPUT->heading(format_string($discussion->name), 3, 'discussionname'); // is_guest should be used here as this also checks whether the user is a guest in the current course. // Guests and visitors cannot subscribe - only enrolled users. if (!is_guest($modcontext, $USER) && isloggedin() && has_capability('mod/forum:viewdiscussion', $modcontext)) { // Discussion subscription. if (\mod_forum\subscriptions::is_subscribable($forum)) { echo html_writer::div(forum_get_discussion_subscription_icon($forum, $post->discussion, null, true), 'discussionsubscription'); echo forum_get_discussion_subscription_icon_preloaders(); } } /// Check to see if groups are being used in this forum /// If so, make sure the current person is allowed to see this discussion /// Also, if we know they should be able to reply, then explicitly set $canreply for performance reasons $canreply = forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext); if (!$canreply and $forum->type !== 'news') { if (isguestuser() or !isloggedin()) { $canreply = true; } if (!is_enrolled($modcontext) and !is_viewing($modcontext)) { // allow guests and not-logged-in to see the link - they are prompted to log in after clicking the link // normal users with temporary guest access see this link too, they are asked to enrol instead
$includetext = optional_param('includetext', false, PARAM_BOOL); $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST); $course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST); $discussion = $DB->get_record('forum_discussions', array('id' => $discussionid, 'forum' => $forumid), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST); $context = context_module::instance($cm->id); require_sesskey(); require_login($course, false, $cm); require_capability('mod/forum:viewdiscussion', $context); $return = new stdClass(); if (is_guest($context, $USER)) { // is_guest should be used here as this also checks whether the user is a guest in the current course. // Guests and visitors cannot subscribe - only enrolled users. throw new moodle_exception('noguestsubscribe', 'mod_forum'); } if (!\mod_forum\subscriptions::is_subscribable($forum)) { // Nothing to do. We won't actually output any content here though. echo json_encode($return); die; } if (\mod_forum\subscriptions::is_subscribed($USER->id, $forum, $discussion->id, $cm)) { // The user is subscribed, unsubscribe them. \mod_forum\subscriptions::unsubscribe_user_from_discussion($USER->id, $discussion, $context); } else { // The user is unsubscribed, subscribe them. \mod_forum\subscriptions::subscribe_user_to_discussion($USER->id, $discussion, $context); } // Now return the updated subscription icon. $return->icon = forum_get_discussion_subscription_icon($forum, $discussion->id, null, $includetext); echo json_encode($return); die;
/** * @dataProvider is_subscribable_loggedin_provider */ public function test_is_subscribable_loggedin($options, $expect) { $this->resetAfterTest(true); // Create a course, with a forum. $course = $this->getDataGenerator()->create_course(); $options['course'] = $course->id; $forum = $this->getDataGenerator()->create_module('forum', $options); $user = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($user->id, $course->id); $this->setUser($user); $this->assertEquals($expect, \mod_forum\subscriptions::is_subscribable($forum)); }
/** * Test subscription using disallow subscription on create. */ public function test_forum_disallow_subscribe_on_create() { global $CFG; $this->resetAfterTest(); $usercount = 5; $course = $this->getDataGenerator()->create_course(); $users = array(); for ($i = 0; $i < $usercount; $i++) { $user = $this->getDataGenerator()->create_user(); $users[] = $user; $this->getDataGenerator()->enrol_user($user->id, $course->id); } $options = array('course' => $course->id, 'forcesubscribe' => FORUM_DISALLOWSUBSCRIBE); // Subscription prevented. $forum = $this->getDataGenerator()->create_module('forum', $options); $result = \mod_forum\subscriptions::fetch_subscribed_users($forum); // No subscriptions by default. $this->assertEquals(0, count($result)); foreach ($users as $user) { $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum)); } }
/** * Returns a list of user objects who are subscribed to this forum. * * @param stdClass $forum The forum record. * @param int $groupid The group id if restricting subscriptions to a group of users, or 0 for all. * @param context_module $context the forum context, to save re-fetching it where possible. * @param string $fields requested user fields (with "u." table prefix). * @param boolean $includediscussionsubscriptions Whether to take discussion subscriptions and unsubscriptions into consideration. * @return array list of users. */ public static function fetch_subscribed_users($forum, $groupid = 0, $context = null, $fields = null, $includediscussionsubscriptions = false) { global $CFG, $DB; if (empty($fields)) { $allnames = get_all_user_name_fields(true, 'u'); $fields = "u.id,\n u.username,\n {$allnames},\n u.maildisplay,\n u.mailformat,\n u.maildigest,\n u.imagealt,\n u.email,\n u.emailstop,\n u.city,\n u.country,\n u.lastaccess,\n u.lastlogin,\n u.picture,\n u.timezone,\n u.theme,\n u.lang,\n u.trackforums,\n u.mnethostid"; } // Retrieve the forum context if it wasn't specified. $context = forum_get_context($forum->id, $context); if (self::is_forcesubscribed($forum)) { $results = \mod_forum\subscriptions::get_potential_subscribers($context, $groupid, $fields, "u.email ASC"); } else { // Only active enrolled users or everybody on the frontpage. list($esql, $params) = get_enrolled_sql($context, '', $groupid, true); $params['forumid'] = $forum->id; if ($includediscussionsubscriptions) { $params['sforumid'] = $forum->id; $params['dsforumid'] = $forum->id; $params['unsubscribed'] = self::FORUM_DISCUSSION_UNSUBSCRIBED; $sql = "SELECT {$fields}\n FROM (\n SELECT userid FROM {forum_subscriptions} s\n WHERE\n s.forum = :sforumid\n UNION\n SELECT userid FROM {forum_discussion_subs} ds\n WHERE\n ds.forum = :dsforumid AND ds.preference <> :unsubscribed\n ) subscriptions\n JOIN {user} u ON u.id = subscriptions.userid\n JOIN ({$esql}) je ON je.id = u.id\n ORDER BY u.email ASC"; } else { $sql = "SELECT {$fields}\n FROM {user} u\n JOIN ({$esql}) je ON je.id = u.id\n JOIN {forum_subscriptions} s ON s.userid = u.id\n WHERE\n s.forum = :forumid\n ORDER BY u.email ASC"; } $results = $DB->get_records_sql($sql, $params); } // Guest user should never be subscribed to a forum. unset($results[$CFG->siteguest]); // Apply the activity module availability resetrictions. $cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course); $modinfo = get_fast_modinfo($forum->course); $info = new \core_availability\info_module($modinfo->get_cm($cm->id)); $results = $info->filter_user_list($results); return $results; }
/** * Test that a user unsubscribed from a forum who has subscribed to a discussion, only receives posts made after * they subscribed to the discussion. */ public function test_forum_discussion_subscription_forum_unsubscribed_discussion_subscribed_after_post() { $this->resetAfterTest(true); // Create a course, with a forum. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); $forum = $this->getDataGenerator()->create_module('forum', $options); $expectedmessages = array(); // Create a user enrolled in the course as a student. list($author) = $this->helper_create_users($course, 1); // Post a discussion to the forum. list($discussion, $post) = $this->helper_post_to_forum($forum, $author); $this->helper_update_post_time($post, -90); $expectedmessages[] = array('id' => $post->id, 'subject' => $post->subject, 'count' => 0); // Then subscribe the user to the discussion. $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion)); $this->helper_update_subscription_time($author, $discussion, -60); // Then post a reply to the first discussion. $reply = $this->helper_post_to_discussion($forum, $discussion, $author); $this->helper_update_post_time($reply, -30); $expectedmessages[] = array('id' => $reply->id, 'subject' => $reply->subject, 'count' => 1); $expectedcount = 1; // Run cron and check that the expected number of users received the notification. $messages = $this->helper_run_cron_check_counts($expectedmessages, $expectedcount); }
/** * Form definition * * @return void */ function definition() { global $CFG, $OUTPUT; $mform =& $this->_form; $course = $this->_customdata['course']; $cm = $this->_customdata['cm']; $coursecontext = $this->_customdata['coursecontext']; $modcontext = $this->_customdata['modcontext']; $forum = $this->_customdata['forum']; $post = $this->_customdata['post']; $subscribe = $this->_customdata['subscribe']; $edit = $this->_customdata['edit']; $thresholdwarning = $this->_customdata['thresholdwarning']; $mform->addElement('header', 'general', ''); //fill in the data depending on page params later using set_data // If there is a warning message and we are not editing a post we need to handle the warning. if (!empty($thresholdwarning) && !$edit) { // Here we want to display a warning if they can still post but have reached the warning threshold. if ($thresholdwarning->canpost) { $message = get_string($thresholdwarning->errorcode, $thresholdwarning->module, $thresholdwarning->additional); $mform->addElement('html', $OUTPUT->notification($message)); } } $mform->addElement('text', 'subject', get_string('subject', 'forum'), 'size="48"'); $mform->setType('subject', PARAM_TEXT); $mform->addRule('subject', get_string('required'), 'required', null, 'client'); $mform->addRule('subject', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); $mform->addElement('editor', 'message', get_string('message', 'forum'), null, self::editor_options($modcontext, empty($post->id) ? null : $post->id)); $mform->setType('message', PARAM_RAW); $mform->addRule('message', get_string('required'), 'required', null, 'client'); $manageactivities = has_capability('moodle/course:manageactivities', $coursecontext); if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { $mform->addElement('checkbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); $mform->freeze('discussionsubscribe'); $mform->setDefaults('discussionsubscribe', 0); $mform->addHelpButton('discussionsubscribe', 'forcesubscribed', 'forum'); } else { if (\mod_forum\subscriptions::subscription_disabled($forum) && !$manageactivities) { $mform->addElement('checkbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); $mform->freeze('discussionsubscribe'); $mform->setDefaults('discussionsubscribe', 0); $mform->addHelpButton('discussionsubscribe', 'disallowsubscription', 'forum'); } else { $mform->addElement('checkbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); $mform->addHelpButton('discussionsubscribe', 'discussionsubscription', 'forum'); } } if (!empty($forum->maxattachments) && $forum->maxbytes != 1 && has_capability('mod/forum:createattachment', $modcontext)) { // 1 = No attachments at all $mform->addElement('filemanager', 'attachments', get_string('attachment', 'forum'), null, self::attachment_options($forum)); $mform->addHelpButton('attachments', 'attachment', 'forum'); } if (empty($post->id) && $manageactivities) { $mform->addElement('checkbox', 'mailnow', get_string('mailnow', 'forum')); } if (!empty($CFG->forum_enabletimedposts) && !$post->parent && has_capability('mod/forum:viewhiddentimedposts', $coursecontext)) { // hack alert $mform->addElement('header', 'displayperiod', get_string('displayperiod', 'forum')); $mform->addElement('date_time_selector', 'timestart', get_string('displaystart', 'forum'), array('optional' => true)); $mform->addHelpButton('timestart', 'displaystart', 'forum'); $mform->addElement('date_time_selector', 'timeend', get_string('displayend', 'forum'), array('optional' => true)); $mform->addHelpButton('timeend', 'displayend', 'forum'); } else { $mform->addElement('hidden', 'timestart'); $mform->setType('timestart', PARAM_INT); $mform->addElement('hidden', 'timeend'); $mform->setType('timeend', PARAM_INT); $mform->setConstants(array('timestart' => 0, 'timeend' => 0)); } if ($groupmode = groups_get_activity_groupmode($cm, $course)) { $groupdata = groups_get_activity_allowed_groups($cm); $groupinfo = array(); foreach ($groupdata as $groupid => $group) { // Check whether this user can post in this group. // We must make this check because all groups are returned for a visible grouped activity. if (forum_user_can_post_discussion($forum, $groupid, null, $cm, $modcontext)) { // Build the data for the groupinfo select. $groupinfo[$groupid] = $group->name; } else { unset($groupdata[$groupid]); } } $groupcount = count($groupinfo); // Check whether a user can post to all of their own groups. // Posts to all of my groups are copied to each group that the user is a member of. Certain conditions must be met. // 1) It only makes sense to allow this when a user is in more than one group. // Note: This check must come before we consider adding accessallgroups, because that is not a real group. $canposttoowngroups = empty($post->edit) && $groupcount > 1; // 2) Important: You can *only* post to multiple groups for a top level post. Never any reply. $canposttoowngroups = $canposttoowngroups && empty($post->parent); // 3) You also need the canposttoowngroups capability. $canposttoowngroups = $canposttoowngroups && has_capability('mod/forum:canposttomygroups', $modcontext); if ($canposttoowngroups) { // This user is in multiple groups, and can post to all of their own groups. // Note: This is not the same as accessallgroups. This option will copy a post to all groups that a // user is a member of. $mform->addElement('checkbox', 'posttomygroups', get_string('posttomygroups', 'forum')); $mform->addHelpButton('posttomygroups', 'posttomygroups', 'forum'); $mform->disabledIf('groupinfo', 'posttomygroups', 'checked'); } // Check whether this user can post to all groups. // Posts to the 'All participants' group go to all groups, not to each group in a list. // It makes sense to allow this, even if there currently aren't any groups because there may be in the future. if (forum_user_can_post_discussion($forum, -1, null, $cm, $modcontext)) { // Note: We must reverse in this manner because array_unshift renumbers the array. $groupinfo = array_reverse($groupinfo, true); $groupinfo[-1] = get_string('allparticipants'); $groupinfo = array_reverse($groupinfo, true); $groupcount++; } // Determine whether the user can select a group from the dropdown. The dropdown is available for several reasons. // 1) This is a new post (not an edit), and there are at least two groups to choose from. $canselectgroupfornew = empty($post->edit) && $groupcount > 1; // 2) This is editing of an existing post and the user is allowed to movediscussions. // We allow this because the post may have been moved from another forum where groups are not available. // We show this even if no groups are available as groups *may* have been available but now are not. $canselectgroupformove = $groupcount && !empty($post->edit) && has_capability('mod/forum:movediscussions', $modcontext); // Important: You can *only* change the group for a top level post. Never any reply. $canselectgroup = empty($post->parent) && ($canselectgroupfornew || $canselectgroupformove); if ($canselectgroup) { $mform->addElement('select', 'groupinfo', get_string('group'), $groupinfo); $mform->setDefault('groupinfo', $post->groupid); $mform->setType('groupinfo', PARAM_INT); } else { if (empty($post->groupid)) { $groupname = get_string('allparticipants'); } else { $groupname = format_string($groupdata[$post->groupid]->name); } $mform->addElement('static', 'groupinfo', get_string('group'), $groupname); } } //------------------------------------------------------------------------------- // buttons if (isset($post->edit)) { // hack alert $submit_string = get_string('savechanges'); } else { $submit_string = get_string('posttoforum', 'forum'); } $this->add_action_buttons(true, $submit_string); $mform->addElement('hidden', 'course'); $mform->setType('course', PARAM_INT); $mform->addElement('hidden', 'forum'); $mform->setType('forum', PARAM_INT); $mform->addElement('hidden', 'discussion'); $mform->setType('discussion', PARAM_INT); $mform->addElement('hidden', 'parent'); $mform->setType('parent', PARAM_INT); $mform->addElement('hidden', 'userid'); $mform->setType('userid', PARAM_INT); $mform->addElement('hidden', 'groupid'); $mform->setType('groupid', PARAM_INT); $mform->addElement('hidden', 'edit'); $mform->setType('edit', PARAM_INT); $mform->addElement('hidden', 'reply'); $mform->setType('reply', PARAM_INT); }
/** * Get the list of potential subscribers to a forum. * * @param object $forumcontext the forum context. * @param integer $groupid the id of a group, or 0 for all groups. * @param string $fields the list of fields to return for each user. As for get_users_by_capability. * @param string $sort sort order. As for get_users_by_capability. * @return array list of users. * @deprecated since Moodle 2.8 use \mod_forum\subscriptions::get_potential_subscribers() instead */ function forum_get_potential_subscribers($forumcontext, $groupid, $fields, $sort = '') { debugging("forum_get_potential_subscribers() has been deprecated, please use \\mod_forum\\subscriptions::get_potential_subscribers() instead.", DEBUG_DEVELOPER); \mod_forum\subscriptions::get_potential_subscribers($forumcontext, $groupid, $fields, $sort); }
} $subscriberselector->invalidate_selected_users(); $existingselector->invalidate_selected_users(); $subscriberselector->set_existing_subscribers($existingselector->find_users('')); } $strsubscribers = get_string("subscribers", "forum"); $PAGE->navbar->add($strsubscribers); $PAGE->set_title($strsubscribers); $PAGE->set_heading($COURSE->fullname); if (has_capability('mod/forum:managesubscriptions', $context)) { $PAGE->set_button(forum_update_subscriptions_button($course->id, $id)); if ($edit != -1) { $USER->subscriptionsediting = $edit; } } else { unset($USER->subscriptionsediting); } echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('forum', 'forum') . ' ' . $strsubscribers); if (empty($USER->subscriptionsediting)) { $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, $currentgroup, $context); echo $forumoutput->subscriber_overview($subscribers, $forum, $course); } else { if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { $subscriberselector->set_force_subscribed(true); echo $forumoutput->subscribed_users($subscriberselector); } else { echo $forumoutput->subscriber_selection_form($existingselector, $subscriberselector); } } echo $OUTPUT->footer();
/** * Prints the discussion view screen for a forum. * * @global object * @global object * @param object $course The current course object. * @param object $forum Forum to be printed. * @param int $maxdiscussions . * @param string $displayformat The display format to use (optional). * @param string $sort Sort arguments for database query (optional). * @param int $groupmode Group mode of the forum (optional). * @param void $unused (originally current group) * @param int $page Page mode, page to display (optional). * @param int $perpage The maximum number of discussions per page(optional) * @param boolean $subscriptionstatus Whether the user is currently subscribed to the discussion in some fashion. * */ function oc_forum_print_latest_discussions($course, $forum, $maxdiscussions = -1, $displayformat = 'plain', $sort = '', $currentgroup = -1, $groupmode = -1, $page = -1, $perpage = 100, $cm = null) { global $CFG, $USER, $OUTPUT; if (!$cm) { if (!($cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course))) { print_error('invalidcoursemodule'); } } $context = context_module::instance($cm->id); if (empty($sort)) { $sort = "d.timemodified DESC"; } $olddiscussionlink = false; // Sort out some defaults if ($perpage <= 0) { $perpage = 0; $page = -1; } if ($maxdiscussions == 0) { // all discussions - backwards compatibility $page = -1; $perpage = 0; if ($displayformat == 'plain') { $displayformat = 'header'; // Abbreviate display by default } } else { if ($maxdiscussions > 0) { $page = -1; $perpage = $maxdiscussions; } } $fullpost = false; if ($displayformat == 'plain') { $fullpost = true; } // Decide if current user is allowed to see ALL the current discussions or not // First check the group stuff if ($currentgroup == -1 or $groupmode == -1) { $groupmode = groups_get_activity_groupmode($cm, $course); $currentgroup = groups_get_activity_group($cm); } $groups = array(); //cache // If the user can post discussions, then this is a good place to put the // button for it. We do not show the button if we are showing site news // and the current user is a guest. $canstart = forum_user_can_post_discussion($forum, $currentgroup, $groupmode, $cm, $context); if (!$canstart and $forum->type !== 'news') { if (isguestuser() or !isloggedin()) { $canstart = true; } if (!is_enrolled($context) and !is_viewing($context)) { // allow guests and not-logged-in to see the button - they are prompted to log in after clicking the link // normal users with temporary guest access see this button too, they are asked to enrol instead // do not show the button to users with suspended enrolments here $canstart = enrol_selfenrol_available($course->id); } } if ($canstart) { echo '<div class="singlebutton forumaddnew">'; echo "<form id=\"newdiscussionform\" method=\"get\" action=\"{$CFG->wwwroot}/blocks/oc_mooc_nav/forum_post.php\">"; echo '<div>'; echo "<input type=\"hidden\" name=\"forum\" value=\"{$forum->id}\" />"; switch ($forum->type) { case 'news': case 'blog': $buttonadd = get_string('addanewtopic', 'forum'); break; case 'qanda': $buttonadd = get_string('addanewquestion', 'forum'); break; default: $buttonadd = get_string('addanewdiscussion', 'forum'); break; } echo '<input type="submit" value="' . $buttonadd . '" />'; echo '</div>'; echo '</form>'; echo "</div>\n"; } else { if (isguestuser() or !isloggedin() or $forum->type == 'news' or $forum->type == 'qanda' and !has_capability('mod/forum:addquestion', $context) or $forum->type != 'qanda' and !has_capability('mod/forum:startdiscussion', $context)) { // no button and no info } else { if ($groupmode and !has_capability('moodle/site:accessallgroups', $context)) { // inform users why they can not post new discussion if (!$currentgroup) { echo $OUTPUT->notification(get_string('cannotadddiscussionall', 'forum')); } else { if (!groups_is_member($currentgroup)) { echo $OUTPUT->notification(get_string('cannotadddiscussion', 'forum')); } } } } } // Get all the recent discussions we're allowed to see $getuserlastmodified = $displayformat == 'header'; if (!($discussions = forum_get_discussions($cm, $sort, $fullpost, null, $maxdiscussions, $getuserlastmodified, $page, $perpage))) { echo '<div class="forumnodiscuss">'; if ($forum->type == 'news') { echo '(' . get_string('nonews', 'forum') . ')'; } else { if ($forum->type == 'qanda') { echo '(' . get_string('noquestions', 'forum') . ')'; } else { echo '(' . get_string('nodiscussions', 'forum') . ')'; } } echo "</div>\n"; return; } // If we want paging if ($page != -1) { ///Get the number of discussions found $numdiscussions = forum_get_discussions_count($cm); ///Show the paging bar echo $OUTPUT->paging_bar($numdiscussions, $page, $perpage, "view.php?f={$forum->id}"); if ($numdiscussions > 1000) { // saves some memory on sites with very large forums $replies = forum_count_discussion_replies($forum->id, $sort, $maxdiscussions, $page, $perpage); } else { $replies = forum_count_discussion_replies($forum->id); } } else { $replies = forum_count_discussion_replies($forum->id); if ($maxdiscussions > 0 and $maxdiscussions <= count($discussions)) { $olddiscussionlink = true; } } $canviewparticipants = has_capability('moodle/course:viewparticipants', $context); $strdatestring = get_string('strftimerecentfull'); // Check if the forum is tracked. if ($cantrack = forum_tp_can_track_forums($forum)) { $forumtracked = forum_tp_is_tracked($forum); } else { $forumtracked = false; } if ($forumtracked) { $unreads = forum_get_discussions_unread($cm); } else { $unreads = array(); } if ($displayformat == 'header') { echo '<table cellspacing="0" class="forumheaderlist">'; echo '<thead>'; echo '<tr>'; echo '<th class="header topic" scope="col">' . get_string('discussion', 'forum') . '</th>'; echo '<th class="header author" colspan="2" scope="col">' . get_string('startedby', 'forum') . '</th>'; if ($groupmode > 0) { echo '<th class="header group" scope="col">' . get_string('group') . '</th>'; } if (has_capability('mod/forum:viewdiscussion', $context)) { echo '<th class="header replies" scope="col">' . get_string('replies', 'forum') . '</th>'; // If the forum can be tracked, display the unread column. if ($cantrack) { echo '<th class="header replies" scope="col">' . get_string('unread', 'forum'); if ($forumtracked) { echo '<a title="' . get_string('markallread', 'forum') . '" href="' . $CFG->wwwroot . '/mod/forum/markposts.php?f=' . $forum->id . '&mark=read&returnpage=view.php">' . '<img src="' . $OUTPUT->pix_url('t/markasread') . '" class="iconsmall" alt="' . get_string('markallread', 'forum') . '" /></a>'; } echo '</th>'; } } echo '<th class="header lastpost" scope="col">' . get_string('lastpost', 'forum') . '</th>'; if (!is_guest($context, $USER) && isloggedin() && has_capability('mod/forum:viewdiscussion', $context)) { if (\mod_forum\subscriptions::is_subscribable($forum)) { echo '<th class="header discussionsubscription" scope="col">'; echo forum_get_discussion_subscription_icon_preloaders(); echo '</th>'; } } echo '</tr>'; echo '</thead>'; echo '<tbody>'; } foreach ($discussions as $discussion) { if ($forum->type == 'qanda' && !has_capability('mod/forum:viewqandawithoutposting', $context) && !forum_user_has_posted($forum->id, $discussion->discussion, $USER->id)) { $canviewparticipants = false; } if (!empty($replies[$discussion->discussion])) { $discussion->replies = $replies[$discussion->discussion]->replies; $discussion->lastpostid = $replies[$discussion->discussion]->lastpostid; } else { $discussion->replies = 0; } // SPECIAL CASE: The front page can display a news item post to non-logged in users. // All posts are read in this case. if (!$forumtracked) { $discussion->unread = '-'; } else { if (empty($USER)) { $discussion->unread = 0; } else { if (empty($unreads[$discussion->discussion])) { $discussion->unread = 0; } else { $discussion->unread = $unreads[$discussion->discussion]; } } } if (isloggedin()) { $ownpost = $discussion->userid == $USER->id; } else { $ownpost = false; } // Use discussion name instead of subject of first post $discussion->subject = $discussion->name; switch ($displayformat) { case 'header': if ($groupmode > 0) { if (isset($groups[$discussion->groupid])) { $group = $groups[$discussion->groupid]; } else { $group = $groups[$discussion->groupid] = groups_get_group($discussion->groupid); } } else { $group = -1; } forum_print_discussion_header($discussion, $forum, $group, $strdatestring, $cantrack, $forumtracked, $canviewparticipants, $context); break; default: $link = false; if ($discussion->replies) { $link = true; } else { $modcontext = context_module::instance($cm->id); $link = forum_user_can_see_discussion($forum, $discussion, $modcontext, $USER); } $discussion->forum = $forum->id; forum_print_post($discussion, $discussion, $forum, $cm, $course, $ownpost, 0, $link, false, '', null, true, $forumtracked); break; } } if ($displayformat == "header") { echo '</tbody>'; echo '</table>'; } if ($olddiscussionlink) { if ($forum->type == 'news') { $strolder = get_string('oldertopics', 'forum'); } else { $strolder = get_string('olderdiscussions', 'forum'); } echo '<div class="forumolddiscuss">'; echo '<a href="' . $CFG->wwwroot . '/mod/forum/view.php?f=' . $forum->id . '&showall=1">'; echo $strolder . '</a> ...</div>'; } if ($page != -1) { ///Show the paging bar echo $OUTPUT->paging_bar($numdiscussions, $page, $perpage, "view.php?f={$forum->id}"); } }
$strunsubscribeall = get_string('unsubscribeall', 'forum'); $PAGE->navbar->add(get_string('modulename', 'forum')); $PAGE->navbar->add($strunsubscribeall); $PAGE->set_title($strunsubscribeall); $PAGE->set_heading($COURSE->fullname); echo $OUTPUT->header(); echo $OUTPUT->heading($strunsubscribeall); if (data_submitted() and $confirm and confirm_sesskey()) { $forums = \mod_forum\subscriptions::get_unsubscribable_forums(); foreach ($forums as $forum) { \mod_forum\subscriptions::unsubscribe_user($USER->id, $forum, context_module::instance($forum->cm), true); } $DB->set_field('user', 'autosubscribe', 0, array('id' => $USER->id)); echo $OUTPUT->box(get_string('unsubscribealldone', 'forum')); echo $OUTPUT->continue_button($return); echo $OUTPUT->footer(); die; } else { $a = count(\mod_forum\subscriptions::get_unsubscribable_forums()); if ($a) { $msg = get_string('unsubscribeallconfirm', 'forum', $a); echo $OUTPUT->confirm($msg, new moodle_url('unsubscribeall.php', array('confirm' => 1)), $return); echo $OUTPUT->footer(); die; } else { echo $OUTPUT->box(get_string('unsubscribeallempty', 'forum')); echo $OUTPUT->continue_button($return); echo $OUTPUT->footer(); die; } }
public function test_optional_with_unsubscribed_discussion_in_subscribed_forum() { $this->resetAfterTest(true); // Create a course, with a forum. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); $forum = $this->getDataGenerator()->create_module('forum', $options); // Create two users enrolled in the course as students. list($author, $recipient) = $this->helper_create_users($course, 2); // Post a discussion to the forum. list($discussion, $post) = $this->helper_post_to_forum($forum, $author); // Unsubscribe the 'recipient' user from the discussion. \mod_forum\subscriptions::subscribe_user($recipient->id, $forum); // Then unsubscribe them from the discussion. \mod_forum\subscriptions::unsubscribe_user_from_discussion($recipient->id, $discussion); // We don't expect any users to receive this post. $expected = 0; // Run cron and check that the expected number of users received the notification. $messages = $this->helper_run_cron_check_count($post, $expected); }
/** * Test that after toggling the forum subscription as another user, * the discussion subscription functionality works as expected. */ public function test_forum_subscribe_toggle_as_other_repeat_subscriptions() { global $DB; $this->resetAfterTest(true); // Create a course, with a forum. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); $forum = $this->getDataGenerator()->create_module('forum', $options); // Create a user enrolled in the course as a student. list($user) = $this->helper_create_users($course, 1); // Post a discussion to the forum. list($discussion, $post) = $this->helper_post_to_forum($forum, $user); // Confirm that the user is currently not subscribed to the forum. $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum)); // Confirm that the user is unsubscribed from the discussion too. $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion->id)); // Confirm that we have no records in either of the subscription tables. $this->assertEquals(0, $DB->count_records('forum_subscriptions', array('userid' => $user->id, 'forum' => $forum->id))); $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array('userid' => $user->id, 'discussion' => $discussion->id))); // Subscribing to the forum should create a record in the subscriptions table, but not the forum discussion // subscriptions table. \mod_forum\subscriptions::subscribe_user($user->id, $forum); $this->assertEquals(1, $DB->count_records('forum_subscriptions', array('userid' => $user->id, 'forum' => $forum->id))); $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array('userid' => $user->id, 'discussion' => $discussion->id))); // Now unsubscribe from the discussion. This should return true. $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion)); // Attempting to unsubscribe again should return false because no change was made. $this->assertFalse(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion)); // Subscribing to the discussion again should return truthfully as the subscription preference was removed. $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion)); // Attempting to subscribe again should return false because no change was made. $this->assertFalse(\mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion)); // Now unsubscribe from the discussion. This should return true once more. $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion)); // And unsubscribing from the forum but not as a request from the user should maintain their preference. \mod_forum\subscriptions::unsubscribe_user($user->id, $forum); $this->assertEquals(0, $DB->count_records('forum_subscriptions', array('userid' => $user->id, 'forum' => $forum->id))); $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array('userid' => $user->id, 'discussion' => $discussion->id))); // Subscribing to the discussion should return truthfully because a change was made. $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion)); $this->assertEquals(0, $DB->count_records('forum_subscriptions', array('userid' => $user->id, 'forum' => $forum->id))); $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array('userid' => $user->id, 'discussion' => $discussion->id))); }
/** * Form definition * * @return void */ function definition() { global $CFG, $OUTPUT; $mform =& $this->_form; $course = $this->_customdata['course']; $cm = $this->_customdata['cm']; $coursecontext = $this->_customdata['coursecontext']; $modcontext = $this->_customdata['modcontext']; $forum = $this->_customdata['forum']; $post = $this->_customdata['post']; $subscribe = $this->_customdata['subscribe']; $edit = $this->_customdata['edit']; $thresholdwarning = $this->_customdata['thresholdwarning']; $mform->addElement('header', 'general', ''); //fill in the data depending on page params later using set_data // If there is a warning message and we are not editing a post we need to handle the warning. if (!empty($thresholdwarning) && !$edit) { // Here we want to display a warning if they can still post but have reached the warning threshold. if ($thresholdwarning->canpost) { $message = get_string($thresholdwarning->errorcode, $thresholdwarning->module, $thresholdwarning->additional); $mform->addElement('html', $OUTPUT->notification($message)); } } $mform->addElement('text', 'subject', get_string('subject', 'forum'), 'size="48"'); $mform->setType('subject', PARAM_TEXT); $mform->addRule('subject', get_string('required'), 'required', null, 'client'); $mform->addRule('subject', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); $mform->addElement('editor', 'message', get_string('message', 'forum'), null, self::editor_options($modcontext, empty($post->id) ? null : $post->id)); $mform->setType('message', PARAM_RAW); $mform->addRule('message', get_string('required'), 'required', null, 'client'); $manageactivities = has_capability('moodle/course:manageactivities', $coursecontext); if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { $mform->addElement('static', 'subscribemessage', get_string('subscription', 'forum'), get_string('everyoneissubscribed', 'forum')); $mform->addElement('hidden', 'subscribe'); $mform->setType('subscribe', PARAM_INT); $mform->addHelpButton('subscribemessage', 'forcesubscribed', 'forum'); } else { if (\mod_forum\subscriptions::subscription_disabled($forum) && !$manageactivities) { $mform->addElement('static', 'subscribemessage', get_string('subscription', 'forum'), get_string('disallowsubscribe', 'forum')); $mform->addElement('hidden', 'discussionsubscribe'); $mform->setType('discussionsubscribe', PARAM_INT); $mform->addHelpButton('subscribemessage', 'disallowsubscription', 'forum'); } else { $options = array(); $options[0] = get_string('discussionsubscribestop', 'forum'); $options[1] = get_string('discussionsubscribestart', 'forum'); $mform->addElement('select', 'discussionsubscribe', get_string('discussionsubscription', 'forum'), $options); $mform->addHelpButton('discussionsubscribe', 'discussionsubscription', 'forum'); } } if (!empty($forum->maxattachments) && $forum->maxbytes != 1 && has_capability('mod/forum:createattachment', $modcontext)) { // 1 = No attachments at all $mform->addElement('filemanager', 'attachments', get_string('attachment', 'forum'), null, self::attachment_options($forum)); $mform->addHelpButton('attachments', 'attachment', 'forum'); } if (empty($post->id) && $manageactivities) { $mform->addElement('checkbox', 'mailnow', get_string('mailnow', 'forum')); } if (!empty($CFG->forum_enabletimedposts) && !$post->parent && has_capability('mod/forum:viewhiddentimedposts', $coursecontext)) { // hack alert $mform->addElement('header', 'displayperiod', get_string('displayperiod', 'forum')); $mform->addElement('date_selector', 'timestart', get_string('displaystart', 'forum'), array('optional' => true)); $mform->addHelpButton('timestart', 'displaystart', 'forum'); $mform->addElement('date_selector', 'timeend', get_string('displayend', 'forum'), array('optional' => true)); $mform->addHelpButton('timeend', 'displayend', 'forum'); } else { $mform->addElement('hidden', 'timestart'); $mform->setType('timestart', PARAM_INT); $mform->addElement('hidden', 'timeend'); $mform->setType('timeend', PARAM_INT); $mform->setConstants(array('timestart' => 0, 'timeend' => 0)); } if ($groupmode = groups_get_activity_groupmode($cm, $course)) { // hack alert $groupdata = groups_get_activity_allowed_groups($cm); $groupcount = count($groupdata); $groupinfo = array(); $modulecontext = context_module::instance($cm->id); // Check whether the user has access to all groups in this forum from the accessallgroups cap. if ($groupmode == VISIBLEGROUPS || has_capability('moodle/site:accessallgroups', $modulecontext)) { // Only allow posting to all groups if the user has access to all groups. $groupinfo = array('0' => get_string('allparticipants')); $groupcount++; } $contextcheck = has_capability('mod/forum:movediscussions', $modulecontext) && empty($post->parent) && $groupcount > 1; if ($contextcheck) { foreach ($groupdata as $grouptemp) { $groupinfo[$grouptemp->id] = $grouptemp->name; } $mform->addElement('select', 'groupinfo', get_string('group'), $groupinfo); $mform->setDefault('groupinfo', $post->groupid); $mform->setType('groupinfo', PARAM_INT); } else { if (empty($post->groupid)) { $groupname = get_string('allparticipants'); } else { $groupname = format_string($groupdata[$post->groupid]->name); } $mform->addElement('static', 'groupinfo', get_string('group'), $groupname); } } //------------------------------------------------------------------------------- // buttons if (isset($post->edit)) { // hack alert $submit_string = get_string('savechanges'); } else { $submit_string = get_string('posttoforum', 'forum'); } $this->add_action_buttons(true, $submit_string); $mform->addElement('hidden', 'course'); $mform->setType('course', PARAM_INT); $mform->addElement('hidden', 'forum'); $mform->setType('forum', PARAM_INT); $mform->addElement('hidden', 'discussion'); $mform->setType('discussion', PARAM_INT); $mform->addElement('hidden', 'parent'); $mform->setType('parent', PARAM_INT); $mform->addElement('hidden', 'userid'); $mform->setType('userid', PARAM_INT); $mform->addElement('hidden', 'groupid'); $mform->setType('groupid', PARAM_INT); $mform->addElement('hidden', 'edit'); $mform->setType('edit', PARAM_INT); $mform->addElement('hidden', 'reply'); $mform->setType('reply', PARAM_INT); }
/** * Test that the correct context is used in the events when subscribing * users. */ public function test_forum_subscription_page_context_valid() { global $CFG, $PAGE; require_once $CFG->dirroot . '/mod/forum/lib.php'; // Setup test data. $course = $this->getDataGenerator()->create_course(); $user = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($user->id, $course->id); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE); $forum = $this->getDataGenerator()->create_module('forum', $options); $quiz = $this->getDataGenerator()->create_module('quiz', $options); // Add a discussion. $record = array(); $record['course'] = $course->id; $record['forum'] = $forum->id; $record['userid'] = $user->id; $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); // Add a post. $record = array(); $record['discussion'] = $discussion->id; $record['userid'] = $user->id; $post = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record); // Set up the default page event to use this forum. $PAGE = new moodle_page(); $cm = get_coursemodule_from_instance('forum', $discussion->forum); $context = \context_module::instance($cm->id); $PAGE->set_context($context); $PAGE->set_cm($cm, $course, $forum); // Trigger and capturing the event. $sink = $this->redirectEvents(); // Trigger the event by subscribing the user to the forum. \mod_forum\subscriptions::subscribe_user($user->id, $forum); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\subscription_created', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by unsubscribing the user to the forum. \mod_forum\subscriptions::unsubscribe_user($user->id, $forum); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\subscription_deleted', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by subscribing the user to the discussion. \mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\discussion_subscription_created', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by unsubscribing the user from the discussion. \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\discussion_subscription_deleted', $event); $this->assertEquals($context, $event->get_context()); // Now try with the context for a different module (quiz). $PAGE = new moodle_page(); $cm = get_coursemodule_from_instance('quiz', $quiz->id); $quizcontext = \context_module::instance($cm->id); $PAGE->set_context($quizcontext); $PAGE->set_cm($cm, $course, $quiz); // Trigger and capturing the event. $sink = $this->redirectEvents(); // Trigger the event by subscribing the user to the forum. \mod_forum\subscriptions::subscribe_user($user->id, $forum); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\subscription_created', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by unsubscribing the user to the forum. \mod_forum\subscriptions::unsubscribe_user($user->id, $forum); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\subscription_deleted', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by subscribing the user to the discussion. \mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\discussion_subscription_created', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by unsubscribing the user from the discussion. \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\discussion_subscription_deleted', $event); $this->assertEquals($context, $event->get_context()); // Now try with the course context - the module context should still be used. $PAGE = new moodle_page(); $coursecontext = \context_course::instance($course->id); $PAGE->set_context($coursecontext); // Trigger the event by subscribing the user to the forum. \mod_forum\subscriptions::subscribe_user($user->id, $forum); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\subscription_created', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by unsubscribing the user to the forum. \mod_forum\subscriptions::unsubscribe_user($user->id, $forum); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\subscription_deleted', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by subscribing the user to the discussion. \mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\discussion_subscription_created', $event); $this->assertEquals($context, $event->get_context()); // Trigger the event by unsubscribing the user from the discussion. \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion); $events = $sink->get_events(); $sink->clear(); $this->assertCount(1, $events); $event = reset($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_forum\\event\\discussion_subscription_deleted', $event); $this->assertEquals($context, $event->get_context()); }
/** * Test that providing a context_module instance to is_subscribed does not result in additional lookups to retrieve * the context_module. */ public function test_is_subscribed_cm() { global $DB; $this->resetAfterTest(true); // Create a course, with a forum. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE); $forum = $this->getDataGenerator()->create_module('forum', $options); // Create a user enrolled in the course as a student. list($user) = $this->helper_create_users($course, 1); // Retrieve the $cm now. $cm = get_fast_modinfo($forum->course)->instances['forum'][$forum->id]; // Reset get_fast_modinfo. get_fast_modinfo(0, 0, true); // Call is_subscribed without passing the $cmid - this should result in a lookup and filling of some of the // caches. This provides us with consistent data to start from. $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum)); $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum)); // Make a note of the number of DB calls. $basecount = $DB->perf_get_reads(); // Call is_subscribed - it should give return the correct result (False), and result in no additional queries. $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, null, $cm)); // The capability check does require some queries, so we don't test it directly. // We don't assert here because this is dependant upon linked code which could change at any time. $suppliedcmcount = $DB->perf_get_reads() - $basecount; // Call is_subscribed without passing the $cmid now - this should result in a lookup. get_fast_modinfo(0, 0, true); $basecount = $DB->perf_get_reads(); $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum)); $calculatedcmcount = $DB->perf_get_reads() - $basecount; // There should be more queries than when we performed the same check a moment ago. $this->assertGreaterThan($suppliedcmcount, $calculatedcmcount); }
$forumname = format_string($forum->name, true); if ($cm->visible) { $style = ''; } else { $style = 'class="dimmed"'; } $forumlink = "<a href=\"view.php?f={$forum->id}\" {$style}>" . format_string($forum->name, true) . "</a>"; $discussionlink = "<a href=\"view.php?f={$forum->id}\" {$style}>" . $count . "</a>"; $row = array($printsection, $forumlink, $forum->intro, $discussionlink); if ($usetracking) { $row[] = $unreadlink; $row[] = $trackedlink; // Tracking. } if ($can_subscribe) { if (!\mod_forum\subscriptions::subscription_disabled($forum)) { $row[] = forum_get_subscribe_link($forum, $context, array('subscribed' => $stryes, 'unsubscribed' => $strno, 'forcesubscribed' => $stryes, 'cantsubscribe' => '-'), false, false, true); } else { $row[] = '-'; } $digestoptions_selector->url->param('id', $forum->id); if ($forum->maildigest === null) { $digestoptions_selector->selected = -1; } else { $digestoptions_selector->selected = $forum->maildigest; } $row[] = $OUTPUT->render($digestoptions_selector); } //If this forum has RSS activated, calculate it if ($show_rss) { if ($forum->rsstype and $forum->rssarticles) {
$modcontext = context_module::instance($cm->id); $cansub = false; if (has_capability('mod/forum:viewdiscussion', $modcontext)) { $cansub = true; } if ($cansub && $cm->visible == 0 && !has_capability('mod/forum:managesubscriptions', $modcontext)) { $cansub = false; } if (!\mod_forum\subscriptions::is_forcesubscribed($forum)) { $subscribed = \mod_forum\subscriptions::is_subscribed($USER->id, $forum, null, $cm); $canmanageactivities = has_capability('moodle/course:manageactivities', $coursecontext, $USER->id); if (($canmanageactivities || \mod_forum\subscriptions::is_subscribable($forum)) && $subscribe && !$subscribed && $cansub) { \mod_forum\subscriptions::subscribe_user($USER->id, $forum, $modcontext, true); } else { if (!$subscribe && $subscribed) { \mod_forum\subscriptions::unsubscribe_user($USER->id, $forum, $modcontext, true); } } } } $returnto = forum_go_back_to(new moodle_url('/mod/forum/index.php', array('id' => $course->id))); $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); if ($subscribe) { redirect($returnto, get_string('nowallsubscribed', 'forum', $shortname), null, \core\output\notification::NOTIFY_SUCCESS); } else { redirect($returnto, get_string('nowallunsubscribed', 'forum', $shortname), null, \core\output\notification::NOTIFY_SUCCESS); } } /// First, let's process the general forums and build up a display if ($generalforums) { foreach ($generalforums as $forum) {
$heading = get_string("yourreply", "forum"); $formheading = get_string('reply', 'forum'); } else { if ($forum->type == 'qanda') { $heading = get_string('yournewquestion', 'forum'); } else { $heading = get_string('yournewtopic', 'forum'); } } $postid = empty($post->id) ? null : $post->id; $draftid_editor = file_get_submitted_draft_itemid('message'); $currenttext = file_prepare_draft_area($draftid_editor, $modcontext->id, 'mod_forum', 'post', $postid, mod_forum_post_form::editor_options($modcontext, $postid), $post->message); // Respect the user's discussion autosubscribe preference unless they have already posted - in which case, use that preference. $discussionsubscribe = $USER->autosubscribe; if (isset($discussion) && forum_user_has_posted($forum->id, $discussion->id, $USER->id)) { $discussionsubscribe = \mod_forum\subscriptions::is_subscribed($USER->id, $forum, $discussion->id, $cm); } $mform_post->set_data(array('attachments' => $draftitemid, 'general' => $heading, 'subject' => $post->subject, 'message' => array('text' => $currenttext, 'format' => empty($post->messageformat) ? editors_get_preferred_format() : $post->messageformat, 'itemid' => $draftid_editor), 'discussionsubscribe' => $discussionsubscribe, 'mailnow' => !empty($post->mailnow), 'userid' => $post->userid, 'parent' => $post->parent, 'discussion' => $post->discussion, 'course' => $course->id) + $page_params + (isset($post->format) ? array('format' => $post->format) : array()) + (isset($discussion->timestart) ? array('timestart' => $discussion->timestart) : array()) + (isset($discussion->timeend) ? array('timeend' => $discussion->timeend) : array()) + (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) + (isset($discussion->id) ? array('discussion' => $discussion->id) : array())); if ($mform_post->is_cancelled()) { if (!isset($discussion->id) || $forum->type === 'qanda') { // Q and A forums don't have a discussion page, so treat them like a new thread.. redirect(new moodle_url('/blocks/oc_mooc_nav/forum_view.php', array('f' => $forum->id))); } else { redirect(new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id))); } } else { if ($fromform = $mform_post->get_data()) { if (empty($SESSION->fromurl)) { $errordestination = "{$CFG->wwwroot}/blocks/oc_mooc_nav/forum_view.php?f={$forum->id}"; } else { $errordestination = $SESSION->fromurl;
public function tearDown() { // We must clear the subscription caches. This has to be done both before each test, and after in case of other // tests using these functions. \mod_forum\subscriptions::reset_forum_cache(); }
$draftid_editor = file_get_submitted_draft_itemid('message'); $currenttext = file_prepare_draft_area($draftid_editor, $modcontext->id, 'mod_forum', 'post', $postid, mod_forum_post_form::editor_options($modcontext, $postid), $post->message); $manageactivities = has_capability('moodle/course:manageactivities', $coursecontext); if (\mod_forum\subscriptions::subscription_disabled($forum) && !$manageactivities) { // User does not have permission to subscribe to this discussion at all. $discussionsubscribe = false; } else { if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { // User does not have permission to unsubscribe from this discussion at all. $discussionsubscribe = true; } else { if (isset($discussion) && \mod_forum\subscriptions::is_subscribed($USER->id, $forum, $discussion->id, $cm)) { // User is subscribed to the discussion - continue the subscription. $discussionsubscribe = true; } else { if (!isset($discussion) && \mod_forum\subscriptions::is_subscribed($USER->id, $forum, null, $cm)) { // Starting a new discussion, and the user is subscribed to the forum - subscribe to the discussion. $discussionsubscribe = true; } else { // User is not subscribed to either forum or discussion. Follow user preference. $discussionsubscribe = $USER->autosubscribe; } } } } $mform_post->set_data(array('attachments' => $draftitemid, 'general' => $heading, 'subject' => $post->subject, 'message' => array('text' => $currenttext, 'format' => empty($post->messageformat) ? editors_get_preferred_format() : $post->messageformat, 'itemid' => $draftid_editor), 'discussionsubscribe' => $discussionsubscribe, 'mailnow' => !empty($post->mailnow), 'userid' => $post->userid, 'parent' => $post->parent, 'discussion' => $post->discussion, 'course' => $course->id) + $page_params + (isset($post->format) ? array('format' => $post->format) : array()) + (isset($discussion->timestart) ? array('timestart' => $discussion->timestart) : array()) + (isset($discussion->timeend) ? array('timeend' => $discussion->timeend) : array()) + (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) + (isset($discussion->id) ? array('discussion' => $discussion->id) : array())); if ($mform_post->is_cancelled()) { if (!isset($discussion->id) || $forum->type === 'qanda') { // Q and A forums don't have a discussion page, so treat them like a new thread.. redirect(new moodle_url('/mod/forum/view.php', array('f' => $forum->id))); } else {
require_once $CFG->dirroot . '/mod/forum/lib.php'; if (!($newsforum = forum_get_course_forum($SITE->id, 'news'))) { print_error('cannotfindorcreateforum', 'forum'); } // Fetch news forum context for proper filtering to happen. $newsforumcm = get_coursemodule_from_instance('forum', $newsforum->id, $SITE->id, false, MUST_EXIST); $newsforumcontext = context_module::instance($newsforumcm->id, MUST_EXIST); $forumname = format_string($newsforum->name, true, array('context' => $newsforumcontext)); echo html_writer::tag('a', get_string('skipa', 'access', core_text::strtolower(strip_tags($forumname))), array('href' => '#skipsitenews', 'class' => 'skip-block')); // Wraps site news forum in div container. echo html_writer::start_tag('div', array('id' => 'site-news-forum')); if (isloggedin()) { $SESSION->fromdiscussion = $CFG->wwwroot; $subtext = ''; if (\mod_forum\subscriptions::is_subscribed($USER->id, $newsforum)) { if (!\mod_forum\subscriptions::is_forcesubscribed($newsforum)) { $subtext = get_string('unsubscribe', 'forum'); } } else { $subtext = get_string('subscribe', 'forum'); } echo $OUTPUT->heading($forumname); $suburl = new moodle_url('/mod/forum/subscribe.php', array('id' => $newsforum->id, 'sesskey' => sesskey())); echo html_writer::tag('div', html_writer::link($suburl, $subtext), array('class' => 'subscribelink')); } else { echo $OUTPUT->heading($forumname); } forum_print_latest_discussions($SITE, $newsforum, $SITE->newsitems, 'plain', 'p.modified DESC'); // End site news forum div container. echo html_writer::end_tag('div'); echo html_writer::tag('span', '', array('class' => 'skip-block-to', 'id' => 'skipsitenews'));
/** * Adds module specific settings to the settings block * * @param settings_navigation $settings The settings navigation object * @param navigation_node $forumnode The node to add module settings to */ function forum_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $forumnode) { global $USER, $PAGE, $CFG, $DB, $OUTPUT; $forumobject = $DB->get_record("forum", array("id" => $PAGE->cm->instance)); if (empty($PAGE->cm->context)) { $PAGE->cm->context = context_module::instance($PAGE->cm->instance); } // for some actions you need to be enrolled, beiing admin is not enough sometimes here $enrolled = is_enrolled($PAGE->cm->context, $USER, '', false); $activeenrolled = is_enrolled($PAGE->cm->context, $USER, '', true); $canmanage = has_capability('mod/forum:managesubscriptions', $PAGE->cm->context); $subscriptionmode = \mod_forum\subscriptions::get_subscription_mode($forumobject); $cansubscribe = $activeenrolled && !\mod_forum\subscriptions::is_forcesubscribed($forumobject) && (!\mod_forum\subscriptions::subscription_disabled($forumobject) || $canmanage); if ($canmanage) { $mode = $forumnode->add(get_string('subscriptionmode', 'forum'), null, navigation_node::TYPE_CONTAINER); $allowchoice = $mode->add(get_string('subscriptionoptional', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id' => $forumobject->id, 'mode' => FORUM_CHOOSESUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); $forceforever = $mode->add(get_string("subscriptionforced", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id' => $forumobject->id, 'mode' => FORUM_FORCESUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); $forceinitially = $mode->add(get_string("subscriptionauto", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id' => $forumobject->id, 'mode' => FORUM_INITIALSUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); $disallowchoice = $mode->add(get_string('subscriptiondisabled', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id' => $forumobject->id, 'mode' => FORUM_DISALLOWSUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); switch ($subscriptionmode) { case FORUM_CHOOSESUBSCRIBE: // 0 $allowchoice->action = null; $allowchoice->add_class('activesetting'); break; case FORUM_FORCESUBSCRIBE: // 1 $forceforever->action = null; $forceforever->add_class('activesetting'); break; case FORUM_INITIALSUBSCRIBE: // 2 $forceinitially->action = null; $forceinitially->add_class('activesetting'); break; case FORUM_DISALLOWSUBSCRIBE: // 3 $disallowchoice->action = null; $disallowchoice->add_class('activesetting'); break; } } else { if ($activeenrolled) { switch ($subscriptionmode) { case FORUM_CHOOSESUBSCRIBE: // 0 $notenode = $forumnode->add(get_string('subscriptionoptional', 'forum')); break; case FORUM_FORCESUBSCRIBE: // 1 $notenode = $forumnode->add(get_string('subscriptionforced', 'forum')); break; case FORUM_INITIALSUBSCRIBE: // 2 $notenode = $forumnode->add(get_string('subscriptionauto', 'forum')); break; case FORUM_DISALLOWSUBSCRIBE: // 3 $notenode = $forumnode->add(get_string('subscriptiondisabled', 'forum')); break; } } } if ($cansubscribe) { if (\mod_forum\subscriptions::is_subscribed($USER->id, $forumobject)) { $linktext = get_string('unsubscribe', 'forum'); } else { $linktext = get_string('subscribe', 'forum'); } $url = new moodle_url('/mod/forum/subscribe.php', array('id' => $forumobject->id, 'sesskey' => sesskey())); $forumnode->add($linktext, $url, navigation_node::TYPE_SETTING); } if (has_capability('mod/forum:viewsubscribers', $PAGE->cm->context)) { $url = new moodle_url('/mod/forum/subscribers.php', array('id' => $forumobject->id)); $forumnode->add(get_string('showsubscribers', 'forum'), $url, navigation_node::TYPE_SETTING); } if ($enrolled && forum_tp_can_track_forums($forumobject)) { // keep tracking info for users with suspended enrolments if ($forumobject->trackingtype == FORUM_TRACKING_OPTIONAL || !$CFG->forum_allowforcedreadtracking && $forumobject->trackingtype == FORUM_TRACKING_FORCED) { if (forum_tp_is_tracked($forumobject)) { $linktext = get_string('notrackforum', 'forum'); } else { $linktext = get_string('trackforum', 'forum'); } $url = new moodle_url('/mod/forum/settracking.php', array('id' => $forumobject->id)); $forumnode->add($linktext, $url, navigation_node::TYPE_SETTING); } } if (!isloggedin() && $PAGE->course->id == SITEID) { $userid = guest_user()->id; } else { $userid = $USER->id; } $hascourseaccess = $PAGE->course->id == SITEID || can_access_course($PAGE->course, $userid); $enablerssfeeds = !empty($CFG->enablerssfeeds) && !empty($CFG->forum_enablerssfeeds); if ($enablerssfeeds && $forumobject->rsstype && $forumobject->rssarticles && $hascourseaccess) { if (!function_exists('rss_get_url')) { require_once "{$CFG->libdir}/rsslib.php"; } if ($forumobject->rsstype == 1) { $string = get_string('rsssubscriberssdiscussions', 'forum'); } else { $string = get_string('rsssubscriberssposts', 'forum'); } $url = new moodle_url(rss_get_url($PAGE->cm->context->id, $userid, "mod_forum", $forumobject->id)); $forumnode->add($string, $url, settings_navigation::TYPE_SETTING, null, null, new pix_icon('i/rss', '')); } }
/** * Get the link to unsubscribe from the discussion. * * @return string */ public function get_unsubscribediscussionlink() { if (!\mod_forum\subscriptions::is_subscribable($this->forum)) { return null; } $link = new \moodle_url('/mod/forum/subscribe.php', array('id' => $this->forum->id, 'd' => $this->discussion->id)); return $link->out(false); }