MDL-42585 Assign: Add capability to only view grades

AMOS BEGIN
    CPY [viewgrades,grades],[assign:viewgrades,mod_assign]
AMOS END
This commit is contained in:
Damyon Wiese 2013-12-13 14:45:56 +08:00
parent bdd5a6c5c2
commit 4a47008ca6
8 changed files with 111 additions and 36 deletions

View File

@ -143,5 +143,16 @@ $capabilities = array(
'clonepermissionsfrom' => 'moodle/grade:manage'
),
'mod/assign:viewgrades' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW,
'teacher' => CAP_ALLOW
)
),
);

View File

@ -52,6 +52,8 @@ class assign_grading_table extends table_sql implements renderable {
private $quickgrading = false;
/** @var boolean $hasgrantextension - Only do the capability check once for the entire table */
private $hasgrantextension = false;
/** @var boolean $hasgrade - Only do the capability check once for the entire table */
private $hasgrade = false;
/** @var array $groupsubmissions - A static cache of group submissions */
private $groupsubmissions = array();
/** @var array $submissiongroups - A static cache of submission groups */
@ -83,6 +85,11 @@ class assign_grading_table extends table_sql implements renderable {
parent::__construct('mod_assign_grading');
$this->assignment = $assignment;
// Check permissions up front.
$this->hasgrantextension = has_capability('mod/assign:grantextension',
$this->assignment->get_context());
$this->hasgrade = $this->assignment->can_grade();
foreach ($assignment->get_feedback_plugins() as $plugin) {
if ($plugin->is_visible() && $plugin->is_enabled()) {
foreach ($plugin->get_grading_batch_operations() as $action => $description) {
@ -94,7 +101,7 @@ class assign_grading_table extends table_sql implements renderable {
}
}
$this->perpage = $perpage;
$this->quickgrading = $quickgrading;
$this->quickgrading = $quickgrading && $this->hasgrade;
$this->output = $PAGE->get_renderer('mod_assign');
$urlparams = array('action'=>'grading', 'id'=>$assignment->get_course_module()->id);
@ -225,7 +232,7 @@ class assign_grading_table extends table_sql implements renderable {
$headers = array();
// Select.
if (!$this->is_downloading()) {
if (!$this->is_downloading() && $this->hasgrade) {
$columns[] = 'select';
$headers[] = get_string('select') .
'<div class="selectall"><label class="accesshide" for="selectall">' . get_string('selectall') . '</label>
@ -302,7 +309,7 @@ class assign_grading_table extends table_sql implements renderable {
$columns[] = 'gradecanbechanged';
$headers[] = get_string('gradecanbechanged', 'assign');
}
if (!$this->is_downloading()) {
if (!$this->is_downloading() && $this->hasgrade) {
// We have to call this column userid so we can use userid as a default sortable column.
$columns[] = 'userid';
$headers[] = get_string('edit');
@ -370,8 +377,6 @@ class assign_grading_table extends table_sql implements renderable {
'assign',
$this->assignment->get_instance()->id,
$users);
$this->hasgrantextension = has_capability('mod/assign:grantextension',
$this->assignment->get_context());
if (!empty($CFG->enableoutcomes) && !empty($this->gradinginfo->outcomes)) {
$columns[] = 'outcomes';
@ -809,7 +814,7 @@ class assign_grading_table extends table_sql implements renderable {
$grade = '';
$gradingdisabled = $this->assignment->grading_disabled($row->id);
if (!$this->is_downloading()) {
if (!$this->is_downloading() && $this->hasgrade) {
$name = fullname($row);
if ($this->assignment->is_blind_marking()) {
$name = get_string('hiddenuser', 'assign') .
@ -1288,7 +1293,7 @@ class assign_grading_table extends table_sql implements renderable {
* @return string HTML fragment.
*/
protected function show_hide_link($column, $index) {
if ($index > 0) {
if ($index > 0 || !$this->hasgrade) {
return parent::show_hide_link($column, $index);
}
return '';

View File

@ -49,6 +49,7 @@ $string['assign:managegrades'] = 'Review and release grades';
$string['assign:releasegrades'] = 'Release grades';
$string['assign:revealidentities'] = 'Reveal student identities';
$string['assign:reviewgrades'] = 'Review grades';
$string['assign:viewgrades'] = 'View grades';
$string['assign:submit'] = 'Submit assignment';
$string['assign:view'] = 'View assignment';
$string['assignfeedback'] = 'Feedback plugin';

View File

@ -223,7 +223,7 @@ function assign_extend_settings_navigation(settings_navigation $settings, naviga
}
// Link to download all submissions.
if (has_capability('mod/assign:grade', $context)) {
if (has_any_capability(array('mod/assign:grade', 'mod/assign:viewgrades'), $context)) {
$link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id, 'action'=>'grading'));
$node = $navref->add(get_string('viewgrading', 'assign'), $link, navigation_node::TYPE_SETTING);

View File

@ -2129,9 +2129,7 @@ class assign {
$item = $this->get_submission($submissionid);
// Check permissions.
if ($item->userid != $USER->id) {
require_capability('mod/assign:grade', $this->context);
}
$this->require_view_submission($item->userid);
$o .= $this->get_renderer()->render(new assign_header($this->get_instance(),
$this->get_context(),
$this->show_intro(),
@ -2153,9 +2151,7 @@ class assign {
}
$item = $this->get_grade($gradeid);
// Check permissions.
if ($item->userid != $USER->id) {
require_capability('mod/assign:grade', $this->context);
}
$this->require_view_submission($item->userid);
$o .= $this->get_renderer()->render(new assign_header($this->get_instance(),
$this->get_context(),
$this->show_intro(),
@ -2317,6 +2313,44 @@ class assign {
return $this->get_renderer()->render_footer();
}
/**
* Throw an error if the permissions to view this users submission are missing.
*
* @throws required_capability_exception
* @return none
*/
public function require_view_submission($userid) {
if (!$this->can_view_submission($userid)) {
throw new required_capability_exception($this->context, 'mod/assign:viewgrades', 'nopermission', '');
}
}
/**
* Throw an error if the permissions to view grades in this assignment are missing.
*
* @throws required_capability_exception
* @return none
*/
public function require_view_grades() {
if (!$this->can_view_grades()) {
throw new required_capability_exception($this->context, 'mod/assign:viewgrades', 'nopermission', '');
}
}
/**
* Does this user have view grade or grade permission for this assignment?
*
* @return bool
*/
public function can_view_grades() {
// Permissions check.
if (!has_any_capability(array('mod/assign:viewgrades', 'mod/assign:grade'), $this->context)) {
return false;
}
return true;
}
/**
* Does this user have grade permission for this assignment?
*
@ -2342,7 +2376,7 @@ class assign {
// More efficient to load this here.
require_once($CFG->libdir.'/filelib.php');
require_capability('mod/assign:grade', $this->context);
$this->require_view_grades();
// Load all users with submit.
$students = get_enrolled_users($this->context, "mod/assign:submit", null, 'u.*', null, null, null,
@ -2965,7 +2999,7 @@ class assign {
$markerfilter = get_user_preferences('assign_markerfilter', '');
$workflowfilter = get_user_preferences('assign_workflowfilter', '');
$controller = $gradingmanager->get_active_controller();
$showquickgrading = empty($controller);
$showquickgrading = empty($controller) && $this->can_grade();
$quickgrading = get_user_preferences('assign_quickgrading', false);
$showonlyactiveenrolopt = has_capability('moodle/course:viewsuspendedusers', $this->context);
@ -3070,7 +3104,7 @@ class assign {
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
$users = array_keys($this->list_participants($currentgroup, true));
if (count($users) != 0) {
if (count($users) != 0 && $this->can_grade()) {
// If no enrolled user in a course then don't display the batch operations feature.
$assignform = new assign_form('gradingbatchoperationsform', $gradingbatchoperationsform);
$o .= $this->get_renderer()->render($assignform);
@ -3092,7 +3126,7 @@ class assign {
$o = '';
// Need submit permission to submit an assignment.
require_capability('mod/assign:grade', $this->context);
$this->require_view_grades();
require_once($CFG->dirroot . '/mod/assign/gradeform.php');
// Only load this if it is.
@ -3244,7 +3278,7 @@ class assign {
if (!$this->is_active_user($userid) && !has_capability('moodle/course:viewsuspendedusers', $this->context)) {
return false;
}
if (has_capability('mod/assign:grade', $this->context)) {
if (has_any_capability(array('mod/assign:viewgrades', 'mod/assign:grade'), $this->context)) {
return true;
}
if (!is_enrolled($this->get_course_context(), $userid)) {
@ -3861,7 +3895,7 @@ class assign {
$this->show_intro(),
$this->get_course_module()->id));
if ($this->can_grade()) {
if ($this->can_view_grades()) {
$draft = ASSIGN_SUBMISSION_STATUS_DRAFT;
$submitted = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
if ($instance->teamsubmission) {

View File

@ -48,21 +48,14 @@ function assignsubmission_comments_comment_validate(stdClass $options) {
if ($assignment->get_instance()->id != $submission->assignment) {
throw new comment_exception('invalidcontext');
}
if (!has_capability('mod/assign:grade', $context)) {
if (!has_capability('mod/assign:submit', $context)) {
throw new comment_exception('nopermissiontocomment');
} else if ($assignment->get_instance()->teamsubmission) {
$group = $assignment->get_submission_group($USER->id);
$groupid = 0;
if ($group) {
$groupid = $group->id;
}
if ($groupid != $submission->groupid) {
throw new comment_exception('nopermissiontocomment');
}
} else if ($submission->userid != $USER->id) {
throw new comment_exception('nopermissiontocomment');
}
$canview = false;
if ($submission->userid) {
$canview = $assignment->can_view_submission($submission->userid);
} else {
$canview = $assignment->can_view_group_submission($submission->groupid);
}
if (!$canview) {
throw new comment_exception('nopermissiontocomment');
}
return true;

View File

@ -533,7 +533,29 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
}
public function test_can_grade() {
global $DB;
$this->setUser($this->editingteachers[0]);
$assign = $this->create_instance();
$this->setUser($this->students[0]);
$this->assertEquals(false, $assign->can_grade());
$this->setUser($this->editingteachers[0]);
$this->assertEquals(true, $assign->can_grade());
$this->setUser($this->teachers[0]);
$this->assertEquals(true, $assign->can_grade());
// Test the viewgrades capability - without mod/assign:grade.
$this->setUser($this->students[0]);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
$this->assertEquals(false, $assign->can_grade());
}
public function test_can_view_submission() {
global $DB;
$this->create_extra_users();
$this->setUser($this->editingteachers[0]);
$assign = $this->create_instance();
@ -552,6 +574,15 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
$this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
$this->assertEquals(true, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
// Test the viewgrades capability - without mod/assign:grade.
$this->setUser($this->students[0]);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
assign_capability('mod/assign:viewgrades', CAP_ALLOW, $studentrole->id, $assign->get_context()->id);
$this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
$this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
$this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
$this->assertEquals(false, $assign->can_view_submission($this->extrasuspendedstudents[0]->id));
}

View File

@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die();
$module->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
$module->version = 2013110500; // The current module version (Date: YYYYMMDDXX).
$module->version = 2013121300; // The current module version (Date: YYYYMMDDXX).
$module->requires = 2013110500; // Requires this Moodle version.
$module->cron = 60;