Merge branch 'MDL-38359-master' of git://github.com/damyon/moodle

This commit is contained in:
Dan Poltawski
2013-06-11 15:31:20 +08:00
21 changed files with 989 additions and 35 deletions
@@ -64,7 +64,10 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
'blindmarking',
'revealidentities',
'attemptreopenmethod',
'maxattempts'));
'maxattempts',
'markingworkflow',
'markingallocation'));
$userflags = new backup_nested_element('userflags');
@@ -73,7 +76,9 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
'assignment',
'mailed',
'locked',
'extensionduedate'));
'extensionduedate',
'workflowstate',
'allocatedmarker'));
$submissions = new backup_nested_element('submissions');
@@ -87,6 +87,12 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
if (!isset($data->cutoffdate)) {
$data->cutoffdate = 0;
}
if (!isset($data->markingworkflow)) {
$data->markingworkflow = 0;
}
if (!isset($data->markingallocation)) {
$data->markingallocation = 0;
}
if (!empty($data->preventlatesubmissions)) {
$data->cutoffdate = $data->duedate;
@@ -0,0 +1,62 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the forms to set the allocated marker for selected submissions.
*
* @package mod_assign
* @copyright 2013 Catalyst IT {@link http://www.catalyst.net.nz}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once($CFG->libdir.'/formslib.php');
require_once($CFG->dirroot . '/mod/assign/feedback/file/locallib.php');
/**
* Set allocated marker form.
*
* @package mod_assign
* @copyright 2013 Catalyst IT {@link http://www.catalyst.net.nz}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_assign_batch_set_allocatedmarker_form extends moodleform {
/**
* Define this form - called by the parent constructor
*/
public function definition() {
$mform = $this->_form;
$params = $this->_customdata;
$mform->addElement('header', 'general', get_string('batchsetallocatedmarker', 'assign', count($params['users'])));
$mform->addElement('static', 'userslist', get_string('selectedusers', 'assign'), $params['usershtml']);
$options = $params['markers'];
$mform->addElement('select', 'allocatedmarker', get_string('allocatedmarker', 'assign'), $options);
$mform->addElement('hidden', 'id', $params['cm']);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'action', 'setbatchmarkingallocation');
$mform->setType('action', PARAM_ALPHA);
$mform->addElement('hidden', 'selectedusers', implode(',', $params['users']));
$mform->setType('selectedusers', PARAM_SEQUENCE);
$this->add_action_buttons(true, get_string('savechanges'));
}
}
@@ -0,0 +1,62 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the forms to set the marking workflow for selected submissions.
*
* @package mod_assign
* @copyright 2013 Catalyst IT {@link http://www.catalyst.net.nz}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once($CFG->libdir.'/formslib.php');
require_once($CFG->dirroot . '/mod/assign/feedback/file/locallib.php');
/**
* Set marking workflow form.
*
* @package mod_assign
* @copyright 2013 Catalyst IT {@link http://www.catalyst.net.nz}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_assign_batch_set_marking_workflow_state_form extends moodleform {
/**
* Define this form - called by the parent constructor
*/
public function definition() {
$mform = $this->_form;
$params = $this->_customdata;
$mform->addElement('header', 'general', get_string('batchsetmarkingworkflowstateforusers', 'assign', count($params['users'])));
$mform->addElement('static', 'userslist', get_string('selectedusers', 'assign'), $params['usershtml']);
$options = $params['markingworkflowstates'];
$mform->addElement('select', 'markingworkflowstate', get_string('markingworkflowstate', 'assign'), $options);
$mform->addElement('hidden', 'id', $params['cm']);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'action', 'setbatchmarkingworkflowstate');
$mform->setType('action', PARAM_ALPHA);
$mform->addElement('hidden', 'selectedusers', implode(',', $params['users']));
$mform->setType('selectedusers', PARAM_SEQUENCE);
$this->add_action_buttons(true, get_string('savechanges'));
}
}
+40 -1
View File
@@ -103,6 +103,45 @@ $capabilities = array(
),
'mod/assign:reviewgrades' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/grade:manage'
),
'mod/assign:releasegrades' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/grade:manage'
),
'mod/assign:managegrades' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/grade:manage'
),
'mod/assign:manageallocations' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/grade:manage'
),
);
+5 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/assign/db" VERSION="20130308" COMMENT="XMLDB file for Moodle mod/assign"
<XMLDB PATH="mod/assign/db" VERSION="20130314" COMMENT="XMLDB file for Moodle mod/assign"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@@ -30,6 +30,8 @@
<FIELD NAME="revealidentities" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Show identities for a blind marking assignment"/>
<FIELD NAME="attemptreopenmethod" TYPE="char" LENGTH="10" NOTNULL="true" DEFAULT="none" SEQUENCE="false" COMMENT="How to determine when students are allowed to open a new submission. Valid options are none, manual, untilpass"/>
<FIELD NAME="maxattempts" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="-1" SEQUENCE="false" COMMENT="What is the maximum number of student attempts allowed for this assignment? -1 means unlimited."/>
<FIELD NAME="markingworkflow" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking workflow features will be used in this assignment."/>
<FIELD NAME="markingallocation" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking allocation features will be used in this assignment"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment instance."/>
@@ -120,6 +122,8 @@
<FIELD NAME="locked" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Student cannot make any changes to their submission if this flag is set."/>
<FIELD NAME="mailed" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Has the student been sent a notification about this grade update?"/>
<FIELD NAME="extensionduedate" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="An extension date assigned to an individual student."/>
<FIELD NAME="workflowstate" TYPE="char" LENGTH="20" NOTNULL="false" SEQUENCE="false" COMMENT="The current workflow state of the grade"/>
<FIELD NAME="allocatedmarker" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The allocated marker to this submission"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+2
View File
@@ -32,6 +32,7 @@ $logs = array(
array('module'=>'assign', 'action'=>'lock submission', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'reveal identities', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'revert submission to draft', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'set marking workflow state', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'submission statement accepted', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'submit', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'submit for grading', 'mtable'=>'assign', 'field'=>'name'),
@@ -46,4 +47,5 @@ $logs = array(
array('module'=>'assign', 'action'=>'view submission grading table', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'view submit assignment form', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'view feedback', 'mtable'=>'assign', 'field'=>'name'),
array('module'=>'assign', 'action'=>'view batch set marking workflow state', 'mtable'=>'assign', 'field'=>'name'),
);
+33 -2
View File
@@ -424,8 +424,39 @@ function xmldb_assign_upgrade($oldversion) {
// Moodle v2.5.0 release upgrade line.
// Put any upgrade step following this.
if ($oldversion < 2013061101) {
// Define field markingworkflow to be added to assign
$table = new xmldb_table('assign');
$field = new xmldb_field('markingworkflow', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'maxattempts');
// Conditionally launch add field markingworkflow
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Define field markingallocation to be added to assign.
$field = new xmldb_field('markingallocation', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'markingworkflow');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Define field workflowstate to be added to assign_grades
$table = new xmldb_table('assign_user_flags');
$field = new xmldb_field('workflowstate', XMLDB_TYPE_CHAR, '20', null, null, null, null, 'extensionduedate');
// Conditionally launch add field workflowstate
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Define field allocatedmarker to be added to assign_grades.
$field = new xmldb_field('allocatedmarker', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'workflowstate');
// Conditionally launch add field workflowstate
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_mod_savepoint(true, 2013061101, 'assign');
}
return true;
}
@@ -64,6 +64,12 @@ class mod_assign_grading_batch_operations_form extends moodleform {
}
}
}
if ($instance['markingworkflow']) {
$options['setmarkingworkflowstate'] = get_string('setmarkingworkflowstate', 'assign');
}
if ($instance['markingallocation']) {
$options['setmarkingallocation'] = get_string('setmarkingallocation', 'assign');
}
$mform->addElement('hidden', 'action', 'gradingbatchoperation');
$mform->setType('action', PARAM_ALPHA);
+6 -1
View File
@@ -54,7 +54,12 @@ class mod_assign_grading_options_form extends moodleform {
if ($instance['submissionsenabled']) {
$mform->addElement('select', 'filter', get_string('filter', 'assign'), $options, $dirtyclass);
}
if (!empty($instance['markingallocationopt'])) {
$mform->addElement('select', 'markerfilter', get_string('markerfilter', 'assign'), $instance['markingallocationopt'], $dirtyclass);
}
if (!empty($instance['markingworkflowopt'])) {
$mform->addElement('select', 'workflowfilter', get_string('workflowfilter', 'assign'), $instance['markingworkflowopt'], $dirtyclass);
}
// Quickgrading.
if ($instance['showquickgrading']) {
$mform->addElement('checkbox', 'quickgrading', get_string('quickgrading', 'assign'), '', $dirtyclass);
+164 -13
View File
@@ -78,7 +78,7 @@ class assign_grading_table extends table_sql implements renderable {
$rowoffset,
$quickgrading,
$downloadfilename = null) {
global $CFG, $PAGE, $DB;
global $CFG, $PAGE, $DB, $USER;
parent::__construct('mod_assign_grading');
$this->assignment = $assignment;
@@ -135,7 +135,9 @@ class assign_grading_table extends table_sql implements renderable {
$fields .= 'g.timecreated as firstmarked, ';
$fields .= 'uf.mailed as mailed, ';
$fields .= 'uf.locked as locked, ';
$fields .= 'uf.extensionduedate as extensionduedate';
$fields .= 'uf.extensionduedate as extensionduedate, ';
$fields .= 'uf.workflowstate as workflowstate, ';
$fields .= 'uf.allocatedmarker as allocatedmarker ';
$submissionmaxattempt = 'SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
FROM {assign_submission} mxs
@@ -183,6 +185,39 @@ class assign_grading_table extends table_sql implements renderable {
}
}
if ($this->assignment->get_instance()->markingallocation) {
if (has_capability('mod/assign:manageallocations', $this->assignment->get_context())) {
//Check to see if marker filter is set
$markerfilter = (int)get_user_preferences('assign_markerfilter', '');
if (!empty($markerfilter)) {
$where .= ' AND uf.allocatedmarker = :markerid';
$params['markerid'] = $markerfilter;
}
} else { // Only show users allocated to this marker.
$where .= ' AND uf.allocatedmarker = :markerid';
$params['markerid'] = $USER->id;
}
}
if ($this->assignment->get_instance()->markingworkflow) {
$workflowstates = $this->assignment->get_marking_workflow_states_for_current_user();
if (!empty($workflowstates)) {
$workflowfilter = get_user_preferences('assign_workflowfilter', '');
if (array_key_exists($workflowfilter, $workflowstates) || $workflowfilter == ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED) {
if ($workflowfilter == ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED) {
$where .= ' AND (uf.workflowstate = :workflowstate OR uf.workflowstate IS NULL OR '.
$DB->sql_isempty('assign_user_flags', 'workflowstate', true, true).')';
echo $where;
$params['workflowstate'] = $workflowfilter;
} else {
$where .= ' AND uf.workflowstate = :workflowstate';
$params['workflowstate'] = $workflowfilter;
echo $where;
}
}
}
}
$this->set_sql($fields, $from, $where, $params);
if ($downloadfilename) {
@@ -228,6 +263,10 @@ class assign_grading_table extends table_sql implements renderable {
if ($assignment->is_any_submission_plugin_enabled()) {
$columns[] = 'status';
$headers[] = get_string('status');
} else if ($this->assignment->get_instance()->markingworkflow) {
$columns[] = 'workflowstatus';
$headers[] = get_string('status');
}
// Team submission columns.
@@ -238,7 +277,13 @@ class assign_grading_table extends table_sql implements renderable {
$columns[] = 'teamstatus';
$headers[] = get_string('teamsubmissionstatus', 'assign');
}
//allocated marker
if ($this->assignment->get_instance()->markingallocation &&
has_capability('mod/assign:manageallocations', $this->assignment->get_context())) {
// Add a column for the allocated marker.
$columns[] = 'allocatedmarker';
$headers[] = get_string('marker', 'assign');
}
// Grade.
$columns[] = 'grade';
$headers[] = get_string('grade');
@@ -251,6 +296,15 @@ class assign_grading_table extends table_sql implements renderable {
$columns[] = 'scale';
$headers[] = get_string('scale', 'assign');
}
if ($this->assignment->get_instance()->markingworkflow) {
// Add a column for the marking workflow state.
$columns[] = 'workflowstate';
$headers[] = get_string('markingworkflowstate', 'assign');
}
// Add a column for the list of valid marking workflow states.
$columns[] = 'gradecanbechanged';
$headers[] = get_string('gradecanbechanged', 'assign');
}
if (!$this->is_downloading()) {
// We have to call this column userid so we can use userid as a default sortable column.
@@ -413,6 +467,89 @@ class assign_grading_table extends table_sql implements renderable {
return $this->perpage;
}
/**
* list current marking workflow state
*
* @param stdClass $row
* @return string
*/
public function col_workflowstatus(stdClass $row) {
$o = '';
$gradingdisabled = $this->assignment->grading_disabled($row->id);
if ($this->assignment->get_instance()->markingworkflow) {
// The function in the assignment keeps a static cache of this list of states.
$workflowstates = $this->assignment->get_marking_workflow_states_for_current_user();
$workflowstate = $row->workflowstate;
if (empty($workflowstate)) {
$workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
}
if ($this->quickgrading && !$gradingdisabled) {
$name = 'quickgrade_' . $row->id . '_workflowstate';
$o .= html_writer::select($workflowstates, $name, $workflowstate, array('' => get_string('markingworkflowstatenotmarked', 'assign')));
} else {
$o .= $this->output->container(get_string('markingworkflowstate' . $workflowstate, 'assign'), $workflowstate);
}
}
return $o;
}
/**
* For download only - list current marking workflow state
*
* @param stdClass $row - The row of data
* @return string The current marking workflow state
*/
public function col_workflowstate($row) {
$state = $row->workflowstate;
if (empty($state)) {
$state = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
}
return get_string('markingworkflowstate' . $state, 'assign');
}
/**
* list current marker
*
* @param stdClass $row - The row of data
* @return id the user->id of the marker.
*/
function col_allocatedmarker(stdClass $row) {
static $markers = null;
static $markerlist = array();
if ($markers === null) {
$markers = get_users_by_capability($this->assignment->get_context(), 'mod/assign:grade');
$markerlist[0] = get_string('choosemarker', 'assign');
foreach ($markers as $marker) {
$markerlist[$marker->id] = fullname($marker);
}
}
if (empty($markerlist)) {
// TODO: add some form of notification here that no markers are available.
return '';
}
if ($this->is_downloading()) {
return $markers[$row->allocatedmarker];
}
if ($this->quickgrading && has_capability('mod/assign:manageallocations', $this->assignment->get_context()) &&
(empty($row->workflowstate) ||
$row->workflowstate == ASSIGN_MARKING_WORKFLOW_STATE_INMARKING ||
$row->workflowstate == ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED)) {
$name = 'quickgrade_' . $row->id . '_allocatedmarker';
return html_writer::select($markerlist, $name, $row->allocatedmarker, false);
} else if (!empty($row->allocatedmarker)) {
$output = '';
if ($this->quickgrading) { // Add hidden field for quickgrading page.
$name = 'quickgrade_' . $row->id . '_allocatedmarker';
$output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$name, 'value'=>$row->allocatedmarker));
}
$output .= $markerlist[$row->allocatedmarker];
return $output;
}
}
/**
* For download only - list all the valid options for this custom scale.
*
@@ -627,6 +764,21 @@ class assign_grading_table extends table_sql implements renderable {
* @param stdClass $row
* @return string
*/
public function col_gradecanbechanged(stdClass $row) {
$gradingdisabled = $this->assignment->grading_disabled($row->id);
if ($gradingdisabled) {
return get_string('no');
} else {
return get_string('yes');
}
}
/**
* Format a column of data for display
*
* @param stdClass $row
* @return string
*/
public function col_grademax(stdClass $row) {
return format_float($this->assignment->get_instance()->grade, 2);
}
@@ -641,7 +793,7 @@ class assign_grading_table extends table_sql implements renderable {
$o = '';
$link = '';
$separator = '';
$separator = $this->output->spacer(array(), true);
$grade = '';
$gradingdisabled = $this->assignment->grading_disabled($row->id);
@@ -659,14 +811,15 @@ class assign_grading_table extends table_sql implements renderable {
'action'=>'grade');
$url = new moodle_url('/mod/assign/view.php', $urlparams);
$link = $this->output->action_link($url, $icon);
$separator = $this->output->spacer(array(), true);
$grade .= $link . $separator;
}
$grade = $this->display_grade($row->grade,
$this->quickgrading && !$gradingdisabled,
$row->userid,
$row->timemarked);
return $link . $separator . $grade;
$grade .= $this->display_grade($row->grade,
$this->quickgrading && !$gradingdisabled,
$row->userid,
$row->timemarked);
return $grade;
}
/**
@@ -752,9 +905,7 @@ class assign_grading_table extends table_sql implements renderable {
$lockedstr = get_string('submissionslockedshort', 'assign');
$o .= $this->output->container($lockedstr, 'lockedsubmission');
}
if ($row->grade !== null && $row->grade >= 0) {
$o .= $this->output->container(get_string('graded', 'assign'), 'submissiongraded');
}
$o .= $this->col_workflowstatus($row);
if (!$row->timesubmitted) {
$now = time();
$due = $instance->duedate;
+37 -1
View File
@@ -29,6 +29,8 @@ $string['addnewattempt'] = 'Add a new attempt';
$string['addnewattempt_help'] = 'This will create a new blank submission for you to work on.';
$string['addnewattemptfromprevious'] = 'Add a new attempt based on previous submission';
$string['addnewattemptfromprevious_help'] = 'This will copy the contents of your previous submission to a new submission for you to work on.';
$string['allocatedmarker'] = 'Allocated Marker';
$string['allocatedmarker_help'] = 'Marker allocated to this submission';
$string['allowsubmissions'] = 'Allow the user to continue making submissions to this assignment.';
$string['allowsubmissionsshort'] = 'Allow submission changes';
$string['allowsubmissionsfromdate'] = 'Allow submissions from';
@@ -42,7 +44,11 @@ $string['assign:addinstance'] = 'Add a new assignment';
$string['assign:exportownsubmission'] = 'Export own submission';
$string['assign:grade'] = 'Grade assignment';
$string['assign:grantextension'] = 'Grant extension';
$string['assign:manageallocations'] = 'Manage markers allocated to submissions';
$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:submit'] = 'Submit assignment';
$string['assign:view'] = 'View assignment';
$string['assignfeedback'] = 'Feedback plugin';
@@ -81,13 +87,18 @@ $string['batchoperationconfirmgrantextension'] = 'Grant an extension to all sele
$string['batchoperationconfirmunlock'] = 'Unlock all selected submissions?';
$string['batchoperationconfirmreverttodraft'] = 'Revert selected submissions to draft?';
$string['batchoperationconfirmaddattempt'] = 'Allow another attempt for selected submissions?';
$string['batchoperationconfirmsetmarkingworkflowstate'] = 'Set marking workflow state for all selected submissions?';
$string['batchoperationconfirmsetmarkingallocation'] = 'Set marking allocation for all selected submissions?';
$string['batchoperationlock'] = 'lock submissions';
$string['batchoperationunlock'] = 'unlock submissions';
$string['batchoperationreverttodraft'] = 'revert submissions to draft';
$string['batchsetallocatedmarker'] = 'Set allocated marker for {$a} selected user(s).';
$string['batchsetmarkingworkflowstateforusers'] = 'Set marking workflow state for {$a} selected user(s).';
$string['blindmarking'] = 'Blind marking';
$string['blindmarking_help'] = 'Blind marking hides the identity of students to markers. Blind marking settings will be locked once a submission or grade has been made in relation to this assignment.';
$string['changegradewarning'] = 'This assignment has graded submissions and changing the grade will not automatically re-calculate existing submission grades. You must re-grade all existing submissions, if you wish to change the grade.';
$string['choosegradingaction'] = 'Grading action';
$string['choosemarker'] = 'Choose...';
$string['chooseoperation'] = 'Choose operation';
$string['comment'] = 'Comment';
$string['completionsubmit'] = 'Student must submit to this activity to complete it';
@@ -132,6 +143,7 @@ $string['editaction'] = 'Actions...';
$string['extensionduedate'] = 'Extension due date';
$string['extensionnotafterduedate'] = 'Extension date must be after the due date';
$string['extensionnotafterfromdate'] = 'Extension date must be after the allow submissions from date';
$string['gradecanbechanged'] = 'Grade can be changed';
$string['gradersubmissionupdatedtext'] = '{$a->username} has updated their assignment submission
for \'{$a->assignment}\' at {$a->timeupdated}
@@ -199,9 +211,24 @@ $string['locksubmissionforstudent'] = 'Prevent any more submissions for student:
$string['locksubmissions'] = 'Lock submissions';
$string['manageassignfeedbackplugins'] = 'Manage assignment feedback plugins';
$string['manageassignsubmissionplugins'] = 'Manage assignment submission plugins';
$string['marker'] = 'Marker';
$string['markerfilter'] = 'Marker filter';
$string['markingallocation'] = 'Use marking allocation';
$string['markingallocation_help'] = 'If enabled, allow markers to be allocated to individual students - requires marking workflow to be enabled.';
$string['markingworkflow'] = 'Use marking workflow';
$string['markingworkflow_help'] = 'If enabled, marks will go through a series of workflow stages before being released to students. This allows for multiple rounds of marking allows all the marks to be released to all students at one time.';
$string['markingworkflowstate'] = 'Marking workflow state';
$string['markingworkflowstate_help'] = 'The list of workflow states you can choose are controlled by your permissions in this assignment. The full list of valid states is:<br><ul><li>In marking - The submissions is currently being marked</li></ul>...';
$string['markingworkflowstateinmarking'] = 'In marking';
$string['markingworkflowstateinreview'] = 'In review';
$string['markingworkflowstatenotmarked'] = 'Not marked';
$string['markingworkflowstatereadyforreview'] = 'Marking completed';
$string['markingworkflowstatereadyforrelease'] = 'Ready for release';
$string['markingworkflowstatereleased'] = 'Released';
$string['maxattempts'] = 'Maximum attempts';
$string['maxattempts_help'] = 'The maximum number of submissions attempts that can be made by a student. After this number of attempts has been made the student&apos;s submission will not be able to be reopened.';
$string['maxgrade'] = 'Maximum grade';
$string['maxgrade'] = 'Maximum Grade';
$string['messageprovider:assign_notification'] = 'Assignment notifications';
$string['modulename'] = 'Assignment';
$string['modulename_help'] = 'The assignment activity module enables a teacher to communicate tasks, collect work and provide grades and feedback.
@@ -211,6 +238,7 @@ Students can submit any digital content (files), such as word-processed document
When reviewing assignments, teachers can leave feedback comments and upload files, such as marked-up student submissions, documents with comments or spoken audio feedback. Assignments can be graded using a numerical or custom scale or an advanced grading method such as a rubric. Final grades are recorded in the gradebook.';
$string['modulename_link'] = 'mod/assignment/view';
$string['modulenameplural'] = 'Assignments';
$string['moreusers'] = '{$a} more...';
$string['mysubmission'] = 'My submission: ';
$string['newsubmissions'] = 'Assignments submitted';
$string['noattempt'] = 'No attempt';
@@ -275,6 +303,11 @@ $string['sendlatenotifications'] = 'Notify graders about late submissions';
$string['sendlatenotifications_help'] = 'If enabled, graders (usually teachers) receive a message whenever a student submits an assignment late. Message methods are configurable.';
$string['sendsubmissionreceipts'] = 'Send submission receipt to students';
$string['sendsubmissionreceipts_help'] = 'This switch will enable submission receipts for students. Students will receive a notification every time they successfully submit an assignment';
$string['setmarkingallocation'] = 'Set allocated marker';
$string['setmarkingworkflowstate'] = 'Set marking workflow state';
$string['selectedusers'] = 'Selected users';
$string['setmarkingworkflowstateforlog'] = 'Set marking workflow state : (id={$a->id}, fullname={$a->fullname}, state={$a->state}). ';
$string['setmarkerallocationforlog'] = 'Set marking allocation : (id={$a->id}, fullname={$a->fullname}, marker={$a->marker}). ';
$string['settings'] = 'Assignment settings';
$string['showrecentsubmissions'] = 'Show recent submissions';
$string['submissioncopiedtext'] = 'You have made a copy of your previous
@@ -351,6 +384,9 @@ $string['upgradenotimplemented'] = 'Upgrade not implemented in plugin ({$a->type
$string['userextensiondate'] = 'Extension granted until: {$a}';
$string['userswhoneedtosubmit'] = 'Users who need to submit: {$a}';
$string['usergrade'] = 'User grade';
$string['validmarkingworkflowstates'] = 'Valid marking workflow states';
$string['viewbatchsetmarkingworkflowstate'] = 'View batch set marking workflow state page.';
$string['viewbatchmarkingallocation'] = 'View batch set marking allocation page.';
$string['viewfeedback'] = 'View feedback';
$string['viewfeedbackforuser'] = 'View feedback for user: {$a}';
$string['viewfullgradingpage'] = 'Open the full grading page to provide feedback';
@@ -365,7 +401,7 @@ $string['viewfull'] = 'View full';
$string['viewsummary'] = 'View summary';
$string['viewsubmissiongradingtable'] = 'View submission grading table.';
$string['viewrevealidentitiesconfirm'] = 'View reveal student identities confirmation page.';
$string['workflowfilter'] = 'Workflow filter';
$string['submissiontypes'] = 'Submission types';
$string['feedbacktypes'] = 'Feedback types';
$string['groupsubmissionsettings'] = 'Group submission settings';
+407 -12
View File
@@ -44,6 +44,14 @@ define('ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS', 'untilpass');
// Special value means allow unlimited attempts.
define('ASSIGN_UNLIMITED_ATTEMPTS', -1);
// Marking workflow states.
define('ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED', 'notmarked');
define('ASSIGN_MARKING_WORKFLOW_STATE_INMARKING', 'inmarking');
define('ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW', 'readyforreview');
define('ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW', 'inreview');
define('ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE', 'readyforrelease');
define('ASSIGN_MARKING_WORKFLOW_STATE_RELEASED', 'released');
require_once($CFG->libdir . '/accesslib.php');
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->dirroot . '/repository/lib.php');
@@ -111,6 +119,9 @@ class assign {
/** @var string modulenameplural prevents excessive calls to get_string */
private static $modulenameplural = null;
/** @var array of marking workflow states for the current user */
private $markingworkflowstates = null;
/**
* Constructor for the base assign class.
*
@@ -389,6 +400,14 @@ class assign {
$this->process_unlock();
$action = 'redirect';
$nextpageparams['action'] = 'grading';
} else if ($action == 'setbatchmarkingworkflowstate') {
$this->process_set_batch_marking_workflow_state();
$action = 'redirect';
$nextpageparams['action'] = 'grading';
} else if ($action == 'setbatchmarkingallocation') {
$this->process_set_batch_marking_allocation();
$action = 'redirect';
$nextpageparams['action'] = 'grading';
} else if ($action == 'confirmsubmit') {
$action = 'submit';
if ($this->process_submit_for_grading($mform)) {
@@ -490,6 +509,10 @@ class assign {
$o .= $this->view_plugin_page();
} else if ($action == 'viewcourseindex') {
$o .= $this->view_course_index();
} else if ($action == 'viewbatchsetmarkingworkflowstate') {
$o .= $this->view_batch_set_workflow_state($mform);
} else if ($action == 'viewbatchmarkingallocation') {
$o .= $this->view_batch_markingallocation($mform);
} else {
$o .= $this->view_submission_page();
}
@@ -540,6 +563,8 @@ class assign {
if (!empty($formdata->maxattempts)) {
$update->maxattempts = $formdata->maxattempts;
}
$update->markingworkflow = $formdata->markingworkflow;
$update->markingallocation = $formdata->markingallocation;
$returnid = $DB->insert_record('assign', $update);
$this->instance = $DB->get_record('assign', array('id'=>$returnid), '*', MUST_EXIST);
@@ -863,6 +888,8 @@ class assign {
if (!empty($formdata->maxattempts)) {
$update->maxattempts = $formdata->maxattempts;
}
$update->markingworkflow = $formdata->markingworkflow;
$update->markingallocation = $formdata->markingallocation;
$result = $DB->update_record('assign', $update);
$this->instance = $DB->get_record('assign', array('id'=>$update->id), '*', MUST_EXIST);
@@ -1677,6 +1704,13 @@ class assign {
$grade->timemodified = time();
if (!empty($grade->workflowstate)) {
$validstates = $this->get_marking_workflow_states_for_current_user();
if (!array_key_exists($grade->workflowstate, $validstates)) {
return false;
}
}
if ($grade->grade && $grade->grade != -1) {
if ($this->get_instance()->grade > 0) {
if (!is_numeric($grade->grade)) {
@@ -2477,6 +2511,8 @@ class assign {
$flags->userid = $userid;
$flags->locked = 0;
$flags->extensionduedate = 0;
$flags->workflowstate = '';
$flags->allocatedmarker = 0;
// The mailed flag can be one of 3 values: 0 is unsent, 1 is sent and 2 is do not send yet.
// This is because students only want to be notified about certain types of update (grades and feedback).
@@ -2696,6 +2732,12 @@ class assign {
if ($grade->grade !== null && $grade->grade >= 0) {
$data->grade = format_float($grade->grade, 2);
}
if (!empty($flags->workflowstate)) {
$data->workflowstate = $flags->workflowstate;
}
if (!empty($flags->allocatedmarker)) {
$data->allocatedmarker = $flags->allocatedmarker;
}
} else {
$data = new stdClass();
$data->grade = '';
@@ -2853,17 +2895,42 @@ class assign {
$perpage = get_user_preferences('assign_perpage', 10);
$filter = get_user_preferences('assign_filter', '');
$markerfilter = get_user_preferences('assign_markerfilter', '');
$workflowfilter = get_user_preferences('assign_workflowfilter', '');
$controller = $gradingmanager->get_active_controller();
$showquickgrading = empty($controller);
$quickgrading = get_user_preferences('assign_quickgrading', false);
$markingallocation = $this->get_instance()->markingallocation &&
has_capability('mod/assign:manageallocations', $this->context);
// Get markers to use in drop lists.
$markingallocationoptions = array();
if ($markingallocation) {
$markers = get_users_by_capability($this->context, 'mod/assign:grade');
$markingallocationoptions[''] = get_string('filternone', 'assign');
foreach ($markers as $marker) {
$markingallocationoptions[$marker->id] = fullname($marker);
}
}
$markingworkflow = $this->get_instance()->markingworkflow;
// Get marking states to show in form.
$markingworkflowoptions = array();
if ($markingworkflow) {
$markingworkflowoptions[''] = get_string('filternone', 'assign');
$markingworkflowoptions[ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED] = get_string('markingworkflowstatenotmarked', 'assign');
$markingworkflowoptions = array_merge($markingworkflowoptions, $this->get_marking_workflow_states_for_current_user());
}
// Print options for changing the filter and changing the number of results per page.
$gradingoptionsformparams = array('cm'=>$cmid,
'contextid'=>$this->context->id,
'userid'=>$USER->id,
'submissionsenabled'=>$this->is_any_submission_plugin_enabled(),
'showquickgrading'=>$showquickgrading,
'quickgrading'=>$quickgrading);
'quickgrading'=>$quickgrading,
'markingworkflowopt'=>$markingworkflowoptions,
'markingallocationopt'=>$markingallocationoptions);
$classoptions = array('class'=>'gradingoptionsform');
$gradingoptionsform = new mod_assign_grading_options_form(null,
@@ -2877,7 +2944,9 @@ class assign {
'duedate'=>$this->get_instance()->duedate,
'attemptreopenmethod'=>$this->get_instance()->attemptreopenmethod,
'feedbackplugins'=>$this->get_feedback_plugins(),
'context'=>$this->get_context());
'context'=>$this->get_context(),
'markingworkflow'=>$markingworkflow,
'markingallocation'=>$markingallocation);
$classoptions = array('class'=>'gradingbatchoperationsform');
$gradingbatchoperationsform = new mod_assign_grading_batch_operations_form(null,
@@ -2889,6 +2958,8 @@ class assign {
$gradingoptionsdata = new stdClass();
$gradingoptionsdata->perpage = $perpage;
$gradingoptionsdata->filter = $filter;
$gradingoptionsdata->markerfilter = $markerfilter;
$gradingoptionsdata->workflowfilter = $workflowfilter;
$gradingoptionsform->set_data($gradingoptionsdata);
$actionformtext = $this->get_renderer()->render($gradingactions);
@@ -3149,12 +3220,17 @@ class assign {
require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php');
require_sesskey();
$markingallocation = $this->get_instance()->markingallocation &&
has_capability('mod/assign:manageallocations', $this->context);
$batchformparams = array('cm'=>$this->get_course_module()->id,
'submissiondrafts'=>$this->get_instance()->submissiondrafts,
'duedate'=>$this->get_instance()->duedate,
'attemptreopenmethod'=>$this->get_instance()->attemptreopenmethod,
'feedbackplugins'=>$this->get_feedback_plugins(),
'context'=>$this->get_context());
'context'=>$this->get_context(),
'markingworkflow'=>$this->get_instance()->markingworkflow,
'markingallocation'=>$markingallocation);
$formclasses = array('class'=>'gradingbatchoperationsform');
$mform = new mod_assign_grading_batch_operations_form(null,
$batchformparams,
@@ -3173,6 +3249,10 @@ class assign {
// Reset the form so the grant extension page will create the extension form.
$mform = null;
return 'grantextension';
} else if ($data->operation == 'setmarkingworkflowstate') {
return 'viewbatchsetmarkingworkflowstate';
} else if ($data->operation == 'setmarkingallocation') {
return 'viewbatchmarkingallocation';
} else if (strpos($data->operation, $prefix) === 0) {
$tail = substr($data->operation, strlen($prefix));
list($plugintype, $action) = explode('_', $tail, 2);
@@ -3205,6 +3285,120 @@ class assign {
return 'grading';
}
/**
* Shows a form that allows the workflow state for selected submissions to be changed.
*
* @param moodleform $mform Set to a grading batch operations form
* @return string - the page to view after processing these actions
*/
private function view_batch_set_workflow_state($mform) {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/batchsetmarkingworkflowstateform.php');
$o = '';
$submitteddata = $mform->get_data();
$users = $submitteddata->selectedusers;
$userlist = explode(',', $users);
$formparams = array('cm'=>$this->get_course_module()->id,
'users'=>$userlist,
'context'=>$this->get_context());
$usershtml = '';
$usercount = 0;
$extrauserfields = get_extra_user_fields($this->get_context());
foreach ($userlist as $userid) {
if ($usercount >= 5) {
$usershtml .= get_string('moreusers', 'assign', count($userlist) - 5);
break;
}
$user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
$usershtml .= $this->get_renderer()->render(new assign_user_summary($user,
$this->get_course()->id,
has_capability('moodle/site:viewfullnames',
$this->get_course_context()),
$this->is_blind_marking(),
$this->get_uniqueid_for_user($user->id),
$extrauserfields));
$usercount += 1;
}
$formparams['usershtml'] = $usershtml;
$formparams['markingworkflowstates'] = $this->get_marking_workflow_states_for_current_user();
$mform = new mod_assign_batch_set_marking_workflow_state_form(null, $formparams);
$o .= $this->get_renderer()->header();
$o .= $this->get_renderer()->render(new assign_form('setworkflowstate', $mform));
$o .= $this->view_footer();
$this->add_to_log('view batch set marking workflow state', get_string('viewbatchsetmarkingworkflowstate', 'assign'));
return $o;
}
/**
* Shows a form that allows the allocated marker for selected submissions to be changed.
*
* @param moodleform $mform Set to a grading batch operations form
* @return string - the page to view after processing these actions
*/
private function view_batch_markingallocation($mform) {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/batchsetallocatedmarkerform.php');
$o = '';
$submitteddata = $mform->get_data();
$users = $submitteddata->selectedusers;
$userlist = explode(',', $users);
$formparams = array('cm'=>$this->get_course_module()->id,
'users'=>$userlist,
'context'=>$this->get_context());
$usershtml = '';
$usercount = 0;
$extrauserfields = get_extra_user_fields($this->get_context());
foreach ($userlist as $userid) {
if ($usercount >= 5) {
$usershtml .= get_string('moreusers', 'assign', count($userlist) - 5);
break;
}
$user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
$usershtml .= $this->get_renderer()->render(new assign_user_summary($user,
$this->get_course()->id,
has_capability('moodle/site:viewfullnames',
$this->get_course_context()),
$this->is_blind_marking(),
$this->get_uniqueid_for_user($user->id),
$extrauserfields));
$usercount += 1;
}
$formparams['usershtml'] = $usershtml;
$markers = get_users_by_capability($this->get_context(), 'mod/assign:grade');
$markerlist = array();
foreach ($markers as $marker) {
$markerlist[$marker->id] = fullname($marker);
}
$formparams['markers'] = $markerlist;
$mform = new mod_assign_batch_set_allocatedmarker_form(null, $formparams);
$o .= $this->get_renderer()->header();
$o .= $this->get_renderer()->render(new assign_form('setworkflowstate', $mform));
$o .= $this->view_footer();
$this->add_to_log('view batch set marker allocation', get_string('viewbatchmarkingallocation', 'assign'));
return $o;
}
/**
* Ask the user to confirm they want to submit their work for grading.
*
@@ -3296,7 +3490,7 @@ class assign {
($this->is_any_submission_plugin_enabled()) &&
$showlinks;
$gradelocked = ($flags && $flags->locked) || $this->grading_disabled($user->id);
$gradelocked = ($flags && $flags->locked) || $this->grading_disabled($user->id, false);
// Grading criteria preview.
$gradingmanager = get_grading_manager($this->context, 'mod_assign', 'submissions');
@@ -3381,9 +3575,16 @@ class assign {
}
}
$gradereleased = true;
if ($this->get_instance()->markingworkflow &&
(empty($grade) || $flags->workflowstate != ASSIGN_MARKING_WORKFLOW_STATE_RELEASED)) {
$gradereleased = false;
$emptyplugins = true; // Don't show feedback plugins until released either.
}
$cangrade = has_capability('mod/assign:grade', $this->get_context());
// If there is feedback or a visible grade, show the summary.
if ((!empty($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden)) ||
if ((!empty($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden) && $gradereleased) ||
!$emptyplugins) {
$gradefordisplay = null;
@@ -3654,6 +3855,14 @@ class assign {
if ($this->is_blind_marking()) {
return false;
}
// If marking workflow is enabled and grade is not released then don't send to gradebook yet.
if ($this->get_instance()->markingworkflow && !empty($grade)) {
$flags = $this->get_user_flags($grade->userid, false);
if (empty($flags->workflowstate) || $flags->workflowstate != ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
return false;
}
}
if ($submission != null) {
if ($submission->userid == 0) {
// This is a group submission update.
@@ -3846,7 +4055,7 @@ class assign {
}
}
if ($this->grading_disabled($userid)) {
if ($this->grading_disabled($userid, false)) {
return false;
}
@@ -4367,6 +4576,8 @@ class assign {
$record->userid = $userid;
if ($modified >= 0) {
$record->grade = unformat_float(optional_param('quickgrade_' . $record->userid, -1, PARAM_TEXT));
$record->workflowstate = optional_param('quickgrade_' . $record->userid.'_workflowstate', '', PARAM_TEXT);
$record->allocatedmarker = optional_param('quickgrade_' . $record->userid.'_allocatedmarker', '', PARAM_INT);
} else {
// This user was not in the grading table.
continue;
@@ -4389,13 +4600,14 @@ class assign {
FROM {assign_grades} mxg
WHERE mxg.assignment = :assignid1 GROUP BY mxg.userid';
$sql = 'SELECT u.id as userid, g.grade as grade, g.timemodified as lastmodified
$sql = 'SELECT u.id as userid, g.grade as grade, g.timemodified as lastmodified, uf.workflowstate, uf.allocatedmarker
FROM {user} u
LEFT JOIN ( ' . $grademaxattempt . ' ) gmx ON u.id = gmx.userid
LEFT JOIN {assign_grades} g ON
u.id = g.userid AND
g.assignment = :assignid2 AND
g.attemptnumber = gmx.maxattempt
LEFT JOIN {assign_user_flags} uf ON uf.assignment = g.assignment AND uf.userid = g.userid
WHERE u.id ' . $userids;
$currentgrades = $DB->get_recordset_sql($sql, $params);
@@ -4435,13 +4647,16 @@ class assign {
if (($current->grade < 0 || $current->grade === null) &&
($modified->grade < 0 || $modified->grade === null)) {
// Different ways to indicate no grade.
continue;
$modified->grade = $current->grade; // Keep existing grade.
}
// Treat 0 and null as different values.
if ($current->grade !== null) {
$current->grade = floatval($current->grade);
}
if ($current->grade !== $modified->grade) {
if ($current->grade !== $modified->grade ||
($this->get_instance()->markingallocation && $current->allocatedmarker != $modified->allocatedmarker ) ||
($this->get_instance()->markingworkflow && $current->workflowstate !== $modified->workflowstate )) {
// Grade changed.
if ($this->grading_disabled($modified->userid)) {
continue;
@@ -4463,6 +4678,7 @@ class assign {
// Ok - ready to process the updates.
foreach ($modifiedusers as $userid => $modified) {
$grade = $this->get_user_grade($userid, true);
$flags = $this->get_user_flags($userid, true);
$grade->grade= grade_floatval(unformat_float($modified->grade));
$grade->grader= $USER->id;
@@ -4479,6 +4695,13 @@ class assign {
}
$this->update_grade($grade);
if ($flags->workflowstate != $modified->workflowstate ||
$flags->allocatedmarker != $modified->allocatedmarker) {
$flags->workflowstate = $modified->workflowstate;
$flags->allocatedmarker = $modified->allocatedmarker;
$this->update_user_flags($flags);
}
$this->notify_grade_modified($grade);
// Save outcomes.
@@ -4575,12 +4798,34 @@ class assign {
$controller = $gradingmanager->get_active_controller();
$showquickgrading = empty($controller);
$markingallocation = $this->get_instance()->markingallocation &&
has_capability('mod/assign:manageallocations', $this->context);
// Get markers to use in drop lists.
$markingallocationoptions = array();
if ($markingallocation) {
$markingallocationoptions[''] = get_string('filternone', 'assign');
$markers = get_users_by_capability($this->context, 'mod/assign:grade');
foreach ($markers as $marker) {
$markingallocationoptions[$marker->id] = fullname($marker);
}
}
// Get marking states to show in form.
$markingworkflowoptions = array();
if ($this->get_instance()->markingworkflow) {
$markingworkflowoptions[''] = get_string('filternone', 'assign');
$markingworkflowoptions[ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED] = get_string('markingworkflowstatenotmarked', 'assign');
$markingworkflowoptions = array_merge($markingworkflowoptions, $this->get_marking_workflow_states_for_current_user());
}
$gradingoptionsparams = array('cm'=>$this->get_course_module()->id,
'contextid'=>$this->context->id,
'userid'=>$USER->id,
'submissionsenabled'=>$this->is_any_submission_plugin_enabled(),
'showquickgrading'=>$showquickgrading,
'quickgrading'=>false);
'quickgrading'=>false,
'markingworkflowopt' => $markingworkflowoptions,
'markingallocationopt' => $markingallocationoptions);
$mform = new mod_assign_grading_options_form(null, $gradingoptionsparams);
if ($formdata = $mform->get_data()) {
@@ -4588,6 +4833,12 @@ class assign {
if (isset($formdata->filter)) {
set_user_preference('assign_filter', $formdata->filter);
}
if (isset($formdata->markerfilter)) {
set_user_preference('assign_markerfilter', $formdata->markerfilter);
}
if (isset($formdata->workflowfilter)) {
set_user_preference('assign_workflowfilter', $formdata->workflowfilter);
}
if ($showquickgrading) {
set_user_preference('assign_quickgrading', isset($formdata->quickgrading));
}
@@ -4843,11 +5094,18 @@ class assign {
* Determine if this users grade is locked or overridden.
*
* @param int $userid - The student userid
* @param bool $checkworkflow - whether to include a check for the workflow state.
* @return bool $gradingdisabled
*/
public function grading_disabled($userid) {
public function grading_disabled($userid, $checkworkflow=true) {
global $CFG;
if ($checkworkflow && $this->get_instance()->markingworkflow) {
$grade = $this->get_user_grade($userid, false);
$validstates = $this->get_marking_workflow_states_for_current_user();
if (!empty($grade) && !empty($grade->workflowstate) && !array_key_exists($grade->workflowstate, $validstates)) {
return true;
}
}
$gradinginfo = grade_get_grades($this->get_course()->id,
'mod',
'assign',
@@ -5035,6 +5293,27 @@ class assign {
}
$gradestring = $usergrade;
}
if ($this->get_instance()->markingworkflow) {
$options = array('' => get_string('markingworkflowstatenotmarked', 'assign')) + $this->get_marking_workflow_states_for_current_user();
$mform->addElement('select', 'workflowstate', get_string('markingworkflowstate', 'assign'), $options);
$mform->addHelpButton('workflowstate', 'markingworkflowstate', 'assign');
}
if ($this->get_instance()->markingallocation && has_capability('mod/assign:manageallocations', $this->context)) {
$markers = get_users_by_capability($this->context, 'mod/assign:grade');
$markerlist = array('' => get_string('choosemarker', 'assign'));
foreach ($markers as $marker) {
$markerlist[$marker->id] = fullname($marker);
}
$mform->addElement('select', 'allocatedmarker', get_string('allocatedmarker', 'assign'), $markerlist);
$mform->addHelpButton('allocatedmarker', 'allocatedmarker', 'assign');
$mform->disabledIf('allocatedmarker', 'workflowstate', 'eq', ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW);
$mform->disabledIf('allocatedmarker', 'workflowstate', 'eq', ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW);
$mform->disabledIf('allocatedmarker', 'workflowstate', 'eq', ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE);
$mform->disabledIf('allocatedmarker', 'workflowstate', 'eq', ASSIGN_MARKING_WORKFLOW_STATE_RELEASED);
}
$mform->addElement('static', 'currentgrade', get_string('currentgrade', 'assign'), $gradestring);
if (count($useridlist) > 1) {
@@ -5310,6 +5589,89 @@ class assign {
$this->add_to_log('lock submission', $logmessage);
}
/**
* Set the workflow state for multiple users
*
* @return void
*/
private function process_set_batch_marking_workflow_state() {
global $DB;
require_sesskey();
$batchusers = required_param('selectedusers', PARAM_TEXT);
$state = required_param('markingworkflowstate', PARAM_ALPHA);
$useridlist = explode(',', $batchusers);
foreach ($useridlist as $userid) {
$flags = $this->get_user_flags($userid, true);
$flags->workflowstate = $state;
$gradingdisabled = $this->grading_disabled($userid);
// Will not apply update if user does not have permission to assign this workflow state.
if (!$gradingdisabled && $this->update_user_flags($flags)) {
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
$params = array('id'=>$user->id,
'fullname'=>fullname($user),
'state'=>$state);
$message = get_string('setmarkingworkflowstateforlog', 'assign', $params);
$this->add_to_log('set marking workflow state', $message);
}
}
}
/**
* Set the marking allocation for multiple users
*
* @return void
*/
private function process_set_batch_marking_allocation() {
global $DB;
require_sesskey();
require_capability('mod/assign:manageallocations', $this->context);
$batchusers = required_param('selectedusers', PARAM_TEXT);
$markerid = required_param('allocatedmarker', PARAM_INT);
$marker = $DB->get_record('user', array('id' => $markerid), '*', MUST_EXIST);
$useridlist = explode(',', $batchusers);
foreach ($useridlist as $userid) {
$flags = $this->get_user_flags($userid, true);
if ($flags->workflowstate == ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW ||
$flags->workflowstate == ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW ||
$flags->workflowstate == ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE ||
$flags->workflowstate == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
continue; // Allocated marker can only be changed in certain workflow states.
}
$flags->allocatedmarker = $marker->id;
if ($this->update_user_flags($flags)) {
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
$params = array('id'=>$user->id,
'fullname'=>fullname($user),
'marker'=>fullname($marker));
$message = get_string('setmarkerallocationforlog', 'assign', $params);
$this->add_to_log('set marking allocation', $message);
}
}
}
/**
* Unlock the process.
*
@@ -5363,6 +5725,12 @@ class assign {
$grade->grade = grade_floatval(unformat_float($formdata->grade));
}
}
if (isset($formdata->workflowstate) || isset($formdata->allocatedmarker)) {
$flags = $this->get_user_flags($userid, true);
$flags->workflowstate = isset($formdata->workflowstate) ? $formdata->workflowstate : $flags->workflowstate;
$flags->allocatedmarker = isset($formdata->allocatedmarker) ? $formdata->allocatedmarker : $flags->allocatedmarker;
$this->update_user_flags($flags);
}
}
$grade->grader= $USER->id;
@@ -5904,6 +6272,33 @@ class assign {
return false;
}
/**
* Get the list of marking_workflow states the current user has permission to transition a grade to.
*
* @return array of state => description
*/
public function get_marking_workflow_states_for_current_user() {
if (!empty($this->markingworkflowstates)) {
return $this->markingworkflowstates;
}
$states = array();
if (has_capability('mod/assign:grade', $this->context)) {
$states[ASSIGN_MARKING_WORKFLOW_STATE_INMARKING] = get_string('markingworkflowstateinmarking', 'assign');
$states[ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW] = get_string('markingworkflowstatereadyforreview', 'assign');
}
if (has_any_capability(array('mod/assign:reviewgrades',
'mod/assign:managegrades'), $this->context)) {
$states[ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW] = get_string('markingworkflowstateinreview', 'assign');
$states[ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE] = get_string('markingworkflowstatereadyforrelease', 'assign');
}
if (has_any_capability(array('mod/assign:releasegrades',
'mod/assign:managegrades'), $this->context)) {
$states[ASSIGN_MARKING_WORKFLOW_STATE_RELEASED] = get_string('markingworkflowstatereleased', 'assign');
}
$this->markingworkflowstates = $states;
return $this->markingworkflowstates;
}
}
/**
+9
View File
@@ -180,6 +180,15 @@ class mod_assign_mod_form extends moodleform_mod {
$mform->freeze('blindmarking');
}
$name = get_string('markingworkflow', 'assign');
$mform->addElement('selectyesno', 'markingworkflow', $name);
$mform->addHelpButton('markingworkflow', 'markingworkflow', 'assign');
$name = get_string('markingallocation', 'assign');
$mform->addElement('selectyesno', 'markingallocation', $name);
$mform->addHelpButton('markingallocation', 'markingallocation', 'assign');
$mform->disabledIf('markingallocation', 'markingworkflow', 'eq', 0);
$this->standard_coursemodule_elements();
$this->apply_admin_defaults();
+12
View File
@@ -131,6 +131,18 @@ M.mod_assign.init_grading_options = function(Y) {
Y.one('form.gradingoptionsform').submit();
});
}
var markerfilterelement = Y.one('#id_markerfilter');
if (markerfilterelement) {
markerfilterelement.on('change', function(e) {
Y.one('form.gradingoptionsform').submit();
});
}
var workflowfilterelement = Y.one('#id_workflowfilter');
if (workflowfilterelement) {
workflowfilterelement.on('change', function(e) {
Y.one('form.gradingoptionsform').submit();
});
}
var quickgradingelement = Y.one('#id_quickgrading');
if (quickgradingelement) {
quickgradingelement.on('change', function(e) {
+2
View File
@@ -957,6 +957,8 @@ class mod_assign_renderer extends plugin_renderer_base {
$this->page->requires->string_for_js('batchoperationconfirmreverttodraft', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmunlock', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmaddattempt', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmsetmarkingworkflowstate', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmsetmarkingallocation', 'assign');
$this->page->requires->string_for_js('editaction', 'assign');
foreach ($table->plugingradingbatchoperations as $plugin => $operations) {
foreach ($operations as $operation => $description) {
+19
View File
@@ -224,4 +224,23 @@ if ($ADMIN->fulltree) {
$setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
$settings->add($setting);
$name = new lang_string('markingworkflow', 'mod_assign');
$description = new lang_string('markingworkflow_help', 'mod_assign');
$setting = new admin_setting_configcheckbox('assign/markingworkflow',
$name,
$description,
0);
$setting->set_advanced_flag_options(admin_setting_flag::ENABLED, false);
$setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
$settings->add($setting);
$name = new lang_string('markingallocation', 'mod_assign');
$description = new lang_string('markingallocation_help', 'mod_assign');
$setting = new admin_setting_configcheckbox('assign/markingallocation',
$name,
$description,
0);
$setting->set_advanced_flag_options(admin_setting_flag::ENABLED, false);
$setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
$settings->add($setting);
}
+3 -1
View File
@@ -65,7 +65,9 @@ class mod_assign_generator extends testing_module_generator {
'blindmarking' => 0,
'cmidnumber' => '',
'attemptreopenmethod' => 'none',
'maxattempts' => -1
'maxattempts' => -1,
'markingworkflow' => 0,
'markingallocation' => 0,
);
foreach ($defaultsettings as $name => $value) {
+104
View File
@@ -743,5 +743,109 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
}
public function test_markingworkflow() {
global $PAGE;
$this->setUser($this->editingteachers[0]);
$assign = $this->create_instance(array('markingworkflow'=>1));
$PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
// Mark the submission and set to notmarked
$this->setUser($this->teachers[0]);
$data = new stdClass();
$data->grade = '50.0';
$data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the student can't see the grade.
$this->setUser($this->students[0]);
$output = $assign->view_student_summary($this->students[0], true);
$this->assertEquals(false, strpos($output, '50.0'));
// Mark the submission and set to inmarking
$this->setUser($this->teachers[0]);
$data = new stdClass();
$data->grade = '50.0';
$data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INMARKING;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the student can't see the grade.
$this->setUser($this->students[0]);
$output = $assign->view_student_summary($this->students[0], true);
$this->assertEquals(false, strpos($output, '50.0'));
// Mark the submission and set to readyforreview
$this->setUser($this->teachers[0]);
$data = new stdClass();
$data->grade = '50.0';
$data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORREVIEW;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the student can't see the grade.
$this->setUser($this->students[0]);
$output = $assign->view_student_summary($this->students[0], true);
$this->assertEquals(false, strpos($output, '50.0'));
// Mark the submission and set to inreview
$this->setUser($this->teachers[0]);
$data = new stdClass();
$data->grade = '50.0';
$data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the student can't see the grade.
$this->setUser($this->students[0]);
$output = $assign->view_student_summary($this->students[0], true);
$this->assertEquals(false, strpos($output, '50.0'));
// Mark the submission and set to readyforrelease
$this->setUser($this->teachers[0]);
$data = new stdClass();
$data->grade = '50.0';
$data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the student can't see the grade.
$this->setUser($this->students[0]);
$output = $assign->view_student_summary($this->students[0], true);
$this->assertEquals(false, strpos($output, '50.0'));
// Mark the submission and set to released
$this->setUser($this->teachers[0]);
$data = new stdClass();
$data->grade = '50.0';
$data->workflowstate = ASSIGN_MARKING_WORKFLOW_STATE_RELEASED;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the student can see the grade.
$this->setUser($this->students[0]);
$output = $assign->view_student_summary($this->students[0], true);
$this->assertNotEquals(false, strpos($output, '50.0'));
}
public function test_markerallocation() {
global $PAGE;
$this->setUser($this->editingteachers[0]);
$assign = $this->create_instance(array('markingworkflow'=>1,'markingallocation'=>1));
$PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
// Allocate marker to submission
$data = new stdClass();
$data->allocatedmarker = $this->teachers[0]->id;
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
// Check the allocated marker can view the submission
$this->setUser($this->teachers[0]);
$gradingtable = new assign_grading_table($assign, 100, '', 0, true);
$output = $assign->get_renderer()->render($gradingtable);
$this->assertEquals(true, strpos($output, $this->students[0]->lastname));
// Check that other teachers can't view this submission
$this->setUser($this->teachers[1]);
$gradingtable = new assign_grading_table($assign, 100, '', 0, true);
$output = $assign->get_renderer()->render($gradingtable);
$this->assertNotEquals(true, strpos($output, $this->students[0]->lastname));
}
}
+2
View File
@@ -90,6 +90,8 @@ class assign_upgrade_manager {
$data->grade = $oldassignment->grade;
$data->submissiondrafts = $oldassignment->resubmit;
$data->requiresubmissionstatement = 0;
$data->markingworkflow = 0;
$data->markingallocation = 0;
$data->cutoffdate = 0;
// New way to specify no late submissions.
if ($oldassignment->preventlate) {
+1 -1
View File
@@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die();
$module->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
$module->version = 2013061100; // The current module version (Date: YYYYMMDDXX).
$module->version = 2013061101; // The current module version (Date: YYYYMMDDXX).
$module->requires = 2013050100; // Requires this Moodle version.
$module->cron = 60;