diff --git a/lib/form/submit.php b/lib/form/submit.php index 23c1ff718f2..d44b1a2a669 100644 --- a/lib/form/submit.php +++ b/lib/form/submit.php @@ -49,7 +49,11 @@ class MoodleQuickForm_submit extends HTML_QuickForm_submit implements templatabl protected $primary; /** - * Any class apart from 'btn' would be override with this content + * Any class apart from 'btn' would be overridden with this content. + * + * By default, submit buttons will utilize the btn-primary OR btn-secondary classes. However there are cases where we + * require a submit button with different stylings (e.g. btn-link). In these cases, $customclassoverride will override + * the defaults mentioned previously and utilize the provided class(es). * * @var string $customclassoverride Custom class override for the input element */ @@ -62,8 +66,11 @@ class MoodleQuickForm_submit extends HTML_QuickForm_submit implements templatabl * @param string $value (optional) field label * @param string $attributes (optional) Either a typical HTML attribute string or an associative array * @param bool|null $primary Is this button a primary button? + * @param array $options Options to further customise the submit button. Currently accepted options are: + * customclassoverride String The CSS class to use for the button instead of the standard + * btn-primary and btn-secondary classes. */ - public function __construct($elementName=null, $value=null, $attributes=null, $primary = null) { + public function __construct($elementName=null, $value=null, $attributes=null, $primary = null, $options = []) { parent::__construct($elementName, $value, $attributes); // Fallback to legacy behaviour if no value specified. @@ -73,11 +80,7 @@ class MoodleQuickForm_submit extends HTML_QuickForm_submit implements templatabl $this->primary = $primary; } - $class = $this->getAttribute('customclassoverride'); - if ($class) { - $this->removeAttribute('customclassoverride'); - $this->customclassoverride = $class; - } + $this->customclassoverride = $options['customclassoverride'] ?? false; } /** @@ -146,7 +149,7 @@ class MoodleQuickForm_submit extends HTML_QuickForm_submit implements templatabl } if ($this->customclassoverride) { - $context['customclass'] = $this->customclassoverride; + $context['customclassoverride'] = $this->customclassoverride; } return $context; } diff --git a/lib/form/templates/element-submit-inline.mustache b/lib/form/templates/element-submit-inline.mustache index d576e572783..8c2c04742d8 100644 --- a/lib/form/templates/element-submit-inline.mustache +++ b/lib/form/templates/element-submit-inline.mustache @@ -3,12 +3,12 @@ {{^element.frozen}} forum; $forumrecord = $this->legacydatamapperfactory->get_forum_data_mapper()->to_legacy_object($forum); $modcontext = \context_module::instance($cm->id); @@ -221,7 +219,7 @@ class discussion_list { 'messagetrust' => 0, 'groupid' => $groupid, ]; - $thresholdwarning = forum_check_throttling($forum, $cm); + $thresholdwarning = forum_check_throttling($forumrecord, $cm); $formparams = array( 'course' => $forum->get_course_record(), @@ -237,6 +235,7 @@ class discussion_list { 'edit' => 0 ); $mformpost = new \mod_forum_post_form('post.php', $formparams, 'post', '', array('id' => 'mformforum')); + $discussionsubscribe = \mod_forum\subscriptions::get_user_default_subscription($forumrecord, $coursecontext, $cm, null); $params = array('reply' => 0, 'forum' => $forumrecord->id, 'edit' => 0) + (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) + @@ -244,7 +243,8 @@ class discussion_list { 'userid' => $post->userid, 'parent' => $post->parent, 'discussion' => $post->discussion, - 'course' => $forum->get_course_id() + 'course' => $forum->get_course_id(), + 'discussionsubscribe' => $discussionsubscribe ); $mformpost->set_data($params); diff --git a/mod/forum/classes/post_form.php b/mod/forum/classes/post_form.php index 40b421dcb69..bea04eb5824 100644 --- a/mod/forum/classes/post_form.php +++ b/mod/forum/classes/post_form.php @@ -95,9 +95,9 @@ class mod_forum_post_form extends moodleform { $thresholdwarning = $this->_customdata['thresholdwarning']; $canreplyprivately = array_key_exists('canreplyprivately', $this->_customdata) ? $this->_customdata['canreplyprivately'] : false; - $stripped = isset($this->_customdata['inpagereply']) ? $this->_customdata['inpagereply'] : false; + $inpagereply = $this->_customdata['inpagereply'] ?? false; - if (!$stripped) { + if (!$inpagereply) { // Fill in the data depending on page params later using set_data. $mform->addElement('header', 'general', ''); } @@ -120,23 +120,23 @@ class mod_forum_post_form extends moodleform { $mform->setType('message', PARAM_RAW); $mform->addRule('message', get_string('required'), 'required', null, 'client'); - if (!$stripped) { + if (!$inpagereply) { $manageactivities = has_capability('moodle/course:manageactivities', $coursecontext); if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { - $mform->addElement('advcheckbox', 'discussionsubscribe', get_string('discussionsubscription', '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('advcheckbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); + $mform->addElement('checkbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); $mform->freeze('discussionsubscribe'); $mform->setDefaults('discussionsubscribe', 0); $mform->addHelpButton('discussionsubscribe', 'disallowsubscription', 'forum'); } else { - $mform->addElement('advcheckbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); + $mform->addElement('checkbox', 'discussionsubscribe', get_string('discussionsubscription', 'forum')); $mform->addHelpButton('discussionsubscribe', 'discussionsubscription', 'forum'); } @@ -168,80 +168,76 @@ class mod_forum_post_form extends moodleform { $mform->addElement('checkbox', 'mailnow', get_string('mailnow', 'forum')); } - 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); + $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 { - if (empty($post->groupid)) { - $groupname = get_string('allparticipants'); - } else { - $groupname = format_string($groupdata[$post->groupid]->name); - } - $mform->addElement('static', 'groupinfo', get_string('group'), $groupname); + 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); + } } if (!empty($CFG->forum_enabletimedposts) && !$post->parent && @@ -284,7 +280,10 @@ class mod_forum_post_form extends moodleform { $mform->registerNoSubmitButton('advancedadddiscussion'); // This is an inpage add discussion which requires custom buttons. - if ($stripped) { + if ($inpagereply) { + $mform->addElement('hidden', 'discussionsubscribe'); + $mform->setType('discussionsubscribe', PARAM_INT); + $mform->disable_form_change_checker(); $buttonarray = array(); $buttonarray[] = &$mform->createElement('submit', 'submitbutton', $submitstring); $buttonarray[] = &$mform->createElement('button', 'cancelbtn', @@ -292,7 +291,7 @@ class mod_forum_post_form extends moodleform { // Additional attribs to handle collapsible div. ['data-toggle' => 'collapse', 'data-target' => "#collapseAddForm"]); $buttonarray[] = &$mform->createElement('submit', 'advancedadddiscussion', - get_string('advanced'), ['customclassoverride' => 'btn-link']); + get_string('advanced'), null, null, ['customclassoverride' => 'btn-link']); $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); $mform->closeHeaderBefore('buttonar'); diff --git a/mod/forum/classes/subscriptions.php b/mod/forum/classes/subscriptions.php index 8f7aa2fea65..5f50eb8de25 100644 --- a/mod/forum/classes/subscriptions.php +++ b/mod/forum/classes/subscriptions.php @@ -825,4 +825,38 @@ class subscriptions { return true; } + /** + * Gets the default subscription value for the logged in user. + * + * @param \stdClass $forum The forum record + * @param \context $context The course context + * @param \cm_info $cm cm_info + * @param int|null $discussionid The discussion we are checking against + * @return bool Default subscription + * @throws coding_exception + */ + public static function get_user_default_subscription($forum, $context, $cm, ?int $discussionid) { + global $USER; + $manageactivities = has_capability('moodle/course:manageactivities', $context); + 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, $discussionid, $cm)) { + // User is subscribed to the discussion - continue the subscription. + $discussionsubscribe = true; + } else if (!isset($discussionid) && \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 ?? false; + } + } + + return $discussionsubscribe; + } } diff --git a/mod/forum/post.php b/mod/forum/post.php index fdea9c05ef0..d01153a4028 100644 --- a/mod/forum/post.php +++ b/mod/forum/post.php @@ -720,26 +720,8 @@ $postid = empty($post->id) ? null : $post->id; $draftideditor = file_get_submitted_draft_itemid('message'); $editoropts = mod_forum_post_form::editor_options($modcontext, $postid); $currenttext = file_prepare_draft_area($draftideditor, $modcontext->id, 'mod_forum', 'post', $postid, $editoropts, $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; - } -} +$discussionid = isset($discussion) ? $discussion->id : null; +$discussionsubscribe = \mod_forum\subscriptions::get_user_default_subscription($forum, $coursecontext, $cm, $discussionid); $mformpost->set_data( array( diff --git a/mod/forum/tests/subscriptions_test.php b/mod/forum/tests/subscriptions_test.php index 65479bafd45..823140ac536 100644 --- a/mod/forum/tests/subscriptions_test.php +++ b/mod/forum/tests/subscriptions_test.php @@ -1378,4 +1378,48 @@ class mod_forum_subscriptions_testcase extends advanced_testcase { $this->assertEquals($expect, \mod_forum\subscriptions::is_subscribable($forum)); } + + public function test_get_user_default_subscription() { + global $DB; + $this->resetAfterTest(true); + + // Create a course, with a forum. + $course = $this->getDataGenerator()->create_course(); + $context = \context_course::instance($course->id); + $options['course'] = $course->id; + $forum = $this->getDataGenerator()->create_module('forum', $options); + $cm = get_coursemodule_from_instance("forum", $forum->id, $course->id); + + // Create a user enrolled in the course as a student. + list($author, $student) = $this->helper_create_users($course, 2, 'student'); + // Post a discussion to the forum. + list($discussion, $post) = $this->helper_post_to_forum($forum, $author); + + // A guest user. + $this->setUser(0); + $this->assertFalse((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, $discussion->id)); + $this->assertFalse((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, null)); + + // A user enrolled in the course. + $this->setUser($author->id); + $this->assertTrue((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, $discussion->id)); + $this->assertTrue((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, null)); + + // Subscribption disabled. + $this->setUser($student->id); + \mod_forum\subscriptions::set_subscription_mode($forum->id, FORUM_DISALLOWSUBSCRIBE); + $forum = $DB->get_record('forum', array('id' => $forum->id)); + $this->assertFalse((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, $discussion->id)); + $this->assertFalse((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, null)); + + \mod_forum\subscriptions::set_subscription_mode($forum->id, FORUM_FORCESUBSCRIBE); + $forum = $DB->get_record('forum', array('id' => $forum->id)); + $this->assertTrue((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, $discussion->id)); + $this->assertTrue((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, null)); + + // Admin user. + $this->setAdminUser(); + $this->assertTrue((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, $discussion->id)); + $this->assertTrue((boolean)\mod_forum\subscriptions::get_user_default_subscription($forum, $context, $cm, null)); + } }