MDL-50714 mod_forum: Correct use of movedicussions cap when posting

The ability to view the group dropdown was too closely related to the
movediscussions capability when posting, or editing a forum post.

The movedicussions capability should only be considered for some parts of
this logic. Users should be able to select the group to post to when
writing message, as long as they have access to that group.
This commit is contained in:
Andrew Nicols 2015-08-07 11:27:20 +08:00
parent 6d392b3027
commit 344e126378
2 changed files with 85 additions and 33 deletions

View File

@ -159,31 +159,67 @@ class mod_forum_post_form extends moodleform {
$mform->setConstants(array('timestart'=> 0, 'timeend'=>0));
}
if ($groupmode = groups_get_activity_groupmode($cm, $course)) { // hack alert
if ($groupmode = groups_get_activity_groupmode($cm, $course)) {
$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'));
$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++;
}
$contextcheck = has_capability('mod/forum:movediscussions', $modulecontext) && empty($post->parent) && $groupcount > 1;
if ($contextcheck) {
if (has_capability('mod/forum:canposttomygroups', $modulecontext)
&& !isset($post->edit)) {
$mform->addElement('checkbox', 'posttomygroups', get_string('posttomygroups', 'forum'));
$mform->addHelpButton('posttomygroups', 'posttomygroups', 'forum');
$mform->disabledIf('groupinfo', 'posttomygroups', 'checked');
}
// 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;
foreach ($groupdata as $grouptemp) {
$groupinfo[$grouptemp->id] = $grouptemp->name;
}
// 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);

View File

@ -697,8 +697,6 @@ if ($mform_post->is_cancelled()) {
// WARNING: the $fromform->message array has been overwritten, do not use it anymore!
$fromform->messagetrust = trusttext_trusted($modcontext);
$contextcheck = isset($fromform->groupinfo) && has_capability('mod/forum:movediscussions', $modcontext);
if ($fromform->edit) { // Updating a post
unset($fromform->groupid);
$fromform->id = $fromform->edit;
@ -722,10 +720,15 @@ if ($mform_post->is_cancelled()) {
}
// If the user has access to all groups and they are changing the group, then update the post.
if ($contextcheck) {
if (isset($fromform->groupinfo) && has_capability('mod/forum:movediscussions', $modcontext)) {
if (empty($fromform->groupinfo)) {
$fromform->groupinfo = -1;
}
if (!forum_user_can_post_discussion($forum, $fromform->groupinfo, null, $cm, $modcontext)) {
print_error('cannotupdatepost', 'forum');
}
$DB->set_field('forum_discussions' ,'groupid' , $fromform->groupinfo, array('firstpost' => $fromform->id));
}
@ -853,6 +856,9 @@ if ($mform_post->is_cancelled()) {
exit;
} else { // Adding a new discussion.
// The location to redirect to after successfully posting.
$redirectto = new moodle_url('view.php', array('f' => $fromform->forum));
$fromform->mailnow = empty($fromform->mailnow) ? 0 : 1;
$discussion = $fromform;
@ -870,17 +876,28 @@ if ($mform_post->is_cancelled()) {
// If we are posting a copy to all groups the user has access to.
if (isset($fromform->posttomygroups)) {
// Post to each of my groups.
require_capability('mod/forum:canposttomygroups', $modcontext);
// Fetch all of this user's groups.
// Note: all groups are returned when in visible groups mode so we must manually filter.
$allowedgroups = groups_get_activity_allowed_groups($cm);
$groupstopostto = array_keys($allowedgroups);
foreach ($allowedgroups as $groupid => $group) {
if (forum_user_can_post_discussion($forum, $groupid, -1, $cm, $modcontext)) {
$groupstopostto[] = $groupid;
}
}
} else if (isset($fromform->groupinfo)) {
// Use the value provided in the dropdown group selection.
$groupstopostto[] = $fromform->groupinfo;
$redirectto->param('group', $fromform->groupinfo);
} else if (isset($fromform->groupid) && !empty($fromform->groupid)) {
// Use the value provided in the hidden form element instead.
$groupstopostto[] = $fromform->groupid;
$redirectto->param('group', $fromform->groupid);
} else {
if ($contextcheck) {
$fromform->groupid = $fromform->groupinfo;
}
if (empty($fromform->groupid)) {
$fromform->groupid = -1;
}
$groupstopostto = array($fromform->groupid);
// Use the value for all participants instead.
$groupstopostto[] = -1;
}
// Before we post this we must check that the user will not exceed the blocking threshold.
@ -934,9 +951,8 @@ if ($mform_post->is_cancelled()) {
$completion->update_state($cm, COMPLETION_COMPLETE);
}
redirect(forum_go_back_to("view.php?f=$fromform->forum"), $message.$subscribemessage, $timemessage);
exit;
// Redirect back to the discussion.
redirect(forum_go_back_to($redirectto->out()), $message . $subscribemessage, $timemessage);
}
}