} // For each subscribed user in this twf and discussion, copy over per-discussion subscriptions if required. $discussiongroup = $discussion->groupid == -1 ? 0 : $discussion->groupid; $potentialsubscribers = \mod_twf\subscriptions::fetch_subscribed_users($twf, $discussiongroup, $modcontext, 'u.id', true); // Pre-seed the subscribed_discussion caches. // Firstly for the twf being moved to. \mod_twf\subscriptions::fill_subscription_cache($twfto->id); // And also for the discussion being moved. \mod_twf\subscriptions::fill_subscription_cache($twf->id); $subscriptionchanges = array(); $subscriptiontime = time(); foreach ($potentialsubscribers as $subuser) { $userid = $subuser->id; $targetsubscription = \mod_twf\subscriptions::is_subscribed($userid, $twfto, null, $cmto); $discussionsubscribed = \mod_twf\subscriptions::is_subscribed($userid, $twf, $discussion->id); $twfsubscribed = \mod_twf\subscriptions::is_subscribed($userid, $twf); if ($twfsubscribed && !$discussionsubscribed && $targetsubscription) { // The user has opted out of this discussion and the move would cause them to receive notifications again. // Ensure they are unsubscribed from the discussion still. $subscriptionchanges[$userid] = \mod_twf\subscriptions::FORUM_DISCUSSION_UNSUBSCRIBED; } else { if (!$twfsubscribed && $discussionsubscribed && !$targetsubscription) { // The user has opted into this discussion and would otherwise not receive the subscription after the move. // Ensure they are subscribed to the discussion still. $subscriptionchanges[$userid] = $subscriptiontime; } } } $DB->set_field('twf_discussions', 'twf', $twfto->id, array('id' => $discussion->id)); $DB->set_field('twf_read', 'twfid', $twfto->id, array('discussionid' => $discussion->id)); // Delete the existing per-discussion subscriptions and replace them with the newly calculated ones.
/** * 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 twf. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE); $twf = $this->getDataGenerator()->create_module('twf', $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($twf->course)->instances['twf'][$twf->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_twf\subscriptions::is_subscribed($user->id, $twf)); $this->assertTrue(\mod_twf\subscriptions::is_subscribed($user->id, $twf)); // 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_twf\subscriptions::is_subscribed($user->id, $twf, 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_twf\subscriptions::is_subscribed($user->id, $twf)); $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); }
$context = context_module::instance($cm->id); if ($user) { require_sesskey(); if (!has_capability('mod/twf:managesubscriptions', $context)) { print_error('nopermissiontosubscribe', 'twf'); } $user = $DB->get_record('user', array('id' => $user), '*', MUST_EXIST); } else { $user = $USER; } if (isset($cm->groupmode) && empty($course->groupmodeforce)) { $groupmode = $cm->groupmode; } else { $groupmode = $course->groupmode; } $issubscribed = \mod_twf\subscriptions::is_subscribed($user->id, $twf, $discussionid, $cm); // For a user to subscribe when a groupmode is set, they must have access to at least one group. if ($groupmode && !$issubscribed && !has_capability('moodle/site:accessallgroups', $context)) { if (!groups_get_all_groups($course->id, $USER->id)) { print_error('cannotsubscribe', 'twf'); } } require_login($course, false, $cm); if (is_null($mode) and !is_enrolled($context, $USER, '', true)) { // Guests and visitors can't subscribe - only enrolled $PAGE->set_title($course->shortname); $PAGE->set_heading($course->fullname); if (isguestuser()) { echo $OUTPUT->header(); echo $OUTPUT->confirm(get_string('subscribeenrolledonly', 'twf') . '<br /><br />' . get_string('liketologin'), get_login_url(), new moodle_url('/mod/twf/view.php', array('f' => $id))); echo $OUTPUT->footer();
$includetext = optional_param('includetext', false, PARAM_BOOL); $twf = $DB->get_record('twf', array('id' => $twfid), '*', MUST_EXIST); $course = $DB->get_record('course', array('id' => $twf->course), '*', MUST_EXIST); $discussion = $DB->get_record('twf_discussions', array('id' => $discussionid), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('twf', $twf->id, $course->id, false, MUST_EXIST); $context = context_module::instance($cm->id); require_sesskey(); require_login($course, false, $cm); require_capability('mod/twf: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_twf'); } if (!\mod_twf\subscriptions::is_subscribable($twf)) { // Nothing to do. We won't actually output any content here though. echo json_encode($return); die; } if (\mod_twf\subscriptions::is_subscribed($USER->id, $twf, $discussion->id, $cm)) { // The user is subscribed, unsubscribe them. \mod_twf\subscriptions::unsubscribe_user_from_discussion($USER->id, $discussion, $context); } else { // The user is unsubscribed, subscribe them. \mod_twf\subscriptions::subscribe_user_to_discussion($USER->id, $discussion, $context); } // Now return the updated subscription icon. $return->icon = twf_get_discussion_subscription_icon($twf, $discussion->id, null, $includetext); echo json_encode($return); die;
public function test_automatic_with_unsubscribed_discussion() { $this->resetAfterTest(true); // Create a course, with a twf. $course = $this->getDataGenerator()->create_course(); $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE); $twf = $this->getDataGenerator()->create_module('twf', $options); // Create two users enrolled in the course as students. list($author, $recipient) = $this->helper_create_users($course, 2); // Post a discussion to the twf. list($discussion, $post) = $this->helper_post_to_twf($twf, $author); // Unsubscribe the 'author' user from the discussion. \mod_twf\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion); $this->assertFalse(\mod_twf\subscriptions::is_subscribed($author->id, $twf, $discussion->id)); $this->assertTrue(\mod_twf\subscriptions::is_subscribed($recipient->id, $twf, $discussion->id)); // We expect only one user to receive this post. $expected = 1; // Run cron and check that the expected number of users received the notification. $messages = $this->helper_run_cron_check_count($post, $expected); $seenauthor = false; $seenrecipient = false; foreach ($messages as $message) { // They should both be from our user. $this->assertEquals($author->id, $message->useridfrom); if ($message->useridto == $author->id) { $seenauthor = true; } else { if ($message->useridto = $recipient->id) { $seenrecipient = true; } } } // Check we only saw one user. $this->assertFalse($seenauthor); $this->assertTrue($seenrecipient); }
$draftid_editor = file_get_submitted_draft_itemid('message'); $currenttext = file_prepare_draft_area($draftid_editor, $modcontext->id, 'mod_twf', 'post', $postid, mod_twf_post_form::editor_options($modcontext, $postid), $post->message); $manageactivities = has_capability('moodle/course:manageactivities', $coursecontext); if (\mod_twf\subscriptions::subscription_disabled($twf) && !$manageactivities) { // User does not have permission to subscribe to this discussion at all. $discussionsubscribe = false; } else { if (\mod_twf\subscriptions::is_forcesubscribed($twf)) { // User does not have permission to unsubscribe from this discussion at all. $discussionsubscribe = true; } else { if (isset($discussion) && \mod_twf\subscriptions::is_subscribed($USER->id, $twf, $discussion->id, $cm)) { // User is subscribed to the discussion - continue the subscription. $discussionsubscribe = true; } else { if (!isset($discussion) && \mod_twf\subscriptions::is_subscribed($USER->id, $twf, null, $cm)) { // Starting a new discussion, and the user is subscribed to the twf - subscribe to the discussion. $discussionsubscribe = true; } else { // User is not subscribed to either twf 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) || $twf->type === 'qanda') { // Q and A twfs don't have a discussion page, so treat them like a new thread.. redirect(new moodle_url('/mod/twf/view.php', array('f' => $twf->id))); } else {
/** * Test subscription using disallow subscription on create. */ public function test_twf_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. $twf = $this->getDataGenerator()->create_module('twf', $options); $result = \mod_twf\subscriptions::fetch_subscribed_users($twf); // No subscriptions by default. $this->assertEquals(0, count($result)); foreach ($users as $user) { $this->assertFalse(\mod_twf\subscriptions::is_subscribed($user->id, $twf)); } }
// there should not be any links leading to this place, just redirect redirect(new moodle_url('/mod/twf/index.php', array('id' => $id)), get_string('subscribeenrolledonly', 'twf')); } // Can proceed now, the user is not guest and is enrolled foreach ($modinfo->get_instances_of('twf') as $twfid => $cm) { $twf = $twfs[$twfid]; $modcontext = context_module::instance($cm->id); $cansub = false; if (has_capability('mod/twf:viewdiscussion', $modcontext)) { $cansub = true; } if ($cansub && $cm->visible == 0 && !has_capability('mod/twf:managesubscriptions', $modcontext)) { $cansub = false; } if (!\mod_twf\subscriptions::is_forcesubscribed($twf)) { $subscribed = \mod_twf\subscriptions::is_subscribed($USER->id, $twf, null, $cm); $canmanageactivities = has_capability('moodle/course:manageactivities', $coursecontext, $USER->id); if (($canmanageactivities || \mod_twf\subscriptions::is_subscribable($twf)) && $subscribe && !$subscribed && $cansub) { \mod_twf\subscriptions::subscribe_user($USER->id, $twf, $modcontext, true); } else { if (!$subscribe && $subscribed) { \mod_twf\subscriptions::unsubscribe_user($USER->id, $twf, $modcontext, true); } } } } $returnto = twf_go_back_to("index.php?id={$course->id}"); $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); if ($subscribe) { redirect($returnto, get_string('nowallsubscribed', 'twf', $shortname), 1); } else {
/** * Adds module specific settings to the settings block * * @param settings_navigation $settings The settings navigation object * @param navigation_node $twfnode The node to add module settings to */ function twf_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $twfnode) { global $USER, $PAGE, $CFG, $DB, $OUTPUT; $twfobject = $DB->get_record("twf", array("id" => $PAGE->cm->instance)); if (empty($PAGE->cm->context)) { $PAGE->cm->context = context_module::instance($PAGE->cm->instance); } $params = $PAGE->url->params(); if (!empty($params['d'])) { $discussionid = $params['d']; } // 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/twf:managesubscriptions', $PAGE->cm->context); $subscriptionmode = \mod_twf\subscriptions::get_subscription_mode($twfobject); $cansubscribe = $activeenrolled && !\mod_twf\subscriptions::is_forcesubscribed($twfobject) && (!\mod_twf\subscriptions::subscription_disabled($twfobject) || $canmanage); if ($canmanage) { $mode = $twfnode->add(get_string('subscriptionmode', 'twf'), null, navigation_node::TYPE_CONTAINER); $allowchoice = $mode->add(get_string('subscriptionoptional', 'twf'), new moodle_url('/mod/twf/subscribe.php', array('id' => $twfobject->id, 'mode' => FORUM_CHOOSESUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); $forceforever = $mode->add(get_string("subscriptionforced", "twf"), new moodle_url('/mod/twf/subscribe.php', array('id' => $twfobject->id, 'mode' => FORUM_FORCESUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); $forceinitially = $mode->add(get_string("subscriptionauto", "twf"), new moodle_url('/mod/twf/subscribe.php', array('id' => $twfobject->id, 'mode' => FORUM_INITIALSUBSCRIBE, 'sesskey' => sesskey())), navigation_node::TYPE_SETTING); $disallowchoice = $mode->add(get_string('subscriptiondisabled', 'twf'), new moodle_url('/mod/twf/subscribe.php', array('id' => $twfobject->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 = $twfnode->add(get_string('subscriptionoptional', 'twf')); break; case FORUM_FORCESUBSCRIBE: // 1 $notenode = $twfnode->add(get_string('subscriptionforced', 'twf')); break; case FORUM_INITIALSUBSCRIBE: // 2 $notenode = $twfnode->add(get_string('subscriptionauto', 'twf')); break; case FORUM_DISALLOWSUBSCRIBE: // 3 $notenode = $twfnode->add(get_string('subscriptiondisabled', 'twf')); break; } } } if ($cansubscribe) { if (\mod_twf\subscriptions::is_subscribed($USER->id, $twfobject, null, $PAGE->cm)) { $linktext = get_string('unsubscribe', 'twf'); } else { $linktext = get_string('subscribe', 'twf'); } $url = new moodle_url('/mod/twf/subscribe.php', array('id' => $twfobject->id, 'sesskey' => sesskey())); $twfnode->add($linktext, $url, navigation_node::TYPE_SETTING); if (isset($discussionid)) { if (\mod_twf\subscriptions::is_subscribed($USER->id, $twfobject, $discussionid, $PAGE->cm)) { $linktext = get_string('unsubscribediscussion', 'twf'); } else { $linktext = get_string('subscribediscussion', 'twf'); } $url = new moodle_url('/mod/twf/subscribe.php', array('id' => $twfobject->id, 'sesskey' => sesskey(), 'd' => $discussionid, 'returnurl' => $PAGE->url->out())); $twfnode->add($linktext, $url, navigation_node::TYPE_SETTING); } } if (has_capability('mod/twf:viewsubscribers', $PAGE->cm->context)) { $url = new moodle_url('/mod/twf/subscribers.php', array('id' => $twfobject->id)); $twfnode->add(get_string('showsubscribers', 'twf'), $url, navigation_node::TYPE_SETTING); } if ($enrolled && twf_tp_can_track_twfs($twfobject)) { // keep tracking info for users with suspended enrolments if ($twfobject->trackingtype == FORUM_TRACKING_OPTIONAL || !$CFG->twf_allowforcedreadtracking && $twfobject->trackingtype == FORUM_TRACKING_FORCED) { if (twf_tp_is_tracked($twfobject)) { $linktext = get_string('notracktwf', 'twf'); } else { $linktext = get_string('tracktwf', 'twf'); } $url = new moodle_url('/mod/twf/settracking.php', array('id' => $twfobject->id, 'sesskey' => sesskey())); $twfnode->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->twf_enablerssfeeds); if ($enablerssfeeds && $twfobject->rsstype && $twfobject->rssarticles && $hascourseaccess) { if (!function_exists('rss_get_url')) { require_once "{$CFG->libdir}/rsslib.php"; } if ($twfobject->rsstype == 1) { $string = get_string('rsssubscriberssdiscussions', 'twf'); } else { $string = get_string('rsssubscriberssposts', 'twf'); } $url = new moodle_url(rss_get_url($PAGE->cm->context->id, $userid, "mod_twf", $twfobject->id)); $twfnode->add($string, $url, settings_navigation::TYPE_SETTING, null, null, new pix_icon('i/rss', '')); } }