MDL-73626 mod_assign: release grades when assignment is anonymous

Adds a new setting, markinganonymous, which if enabled together
with anonymous submissions and marking workflow,
allows markers to release individual grades.
This commit is contained in:
Sumaiya Javed 2023-10-23 14:58:34 +01:00 committed by Mark Johnson
parent 6374475dc3
commit fac43ca0f2
14 changed files with 190 additions and 18 deletions

View File

@ -91,6 +91,7 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
'maxattempts',
'markingworkflow',
'markingallocation',
'markinganonymous',
'preventsubmissionnotingroup',
'activity',
'activityformat',

View File

@ -125,6 +125,9 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
if (!isset($data->markingallocation)) {
$data->markingallocation = 0;
}
if (!isset($data->markinganonymous)) {
$data->markinganonymous = 0;
}
if (!isset($data->preventsubmissionnotingroup)) {
$data->preventsubmissionnotingroup = 0;
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/assign/db" VERSION="20210930" COMMENT="XMLDB file for Moodle mod/assign"
<XMLDB PATH="mod/assign/db" VERSION="20231115" COMMENT="XMLDB file for Moodle mod/assign"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@ -34,6 +34,7 @@
<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"/>
<FIELD NAME="markinganonymous" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking anonymous features will be used in this assignment"/>
<FIELD NAME="sendstudentnotifications" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Default for send student notifications checkbox when grading."/>
<FIELD NAME="preventsubmissionnotingroup" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled a user will be unable to make a submission unless they are a member of a group."/>
<FIELD NAME="activity" TYPE="text" NOTNULL="false" SEQUENCE="false"/>

View File

@ -28,6 +28,8 @@
* @return bool
*/
function xmldb_assign_upgrade($oldversion) {
global $DB;
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
@ -37,5 +39,29 @@ function xmldb_assign_upgrade($oldversion) {
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
$dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
if ($oldversion < 2023103000) {
// Define field activity to be added to assign.
$table = new xmldb_table('assign');
$field = new xmldb_field(
'markinganonymous',
XMLDB_TYPE_INTEGER,
'2',
null,
XMLDB_NOTNULL,
null,
'0',
'markingallocation'
);
// Conditionally launch add field activity.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Assign savepoint reached.
upgrade_mod_savepoint(true, 2023103000, 'assign');
}
return true;
}

View File

@ -357,6 +357,7 @@ class mod_assign_external extends \mod_assign\external\external_api {
'm.maxattempts, ' .
'm.markingworkflow, ' .
'm.markingallocation, ' .
'm.markinganonymous, ' .
'm.requiresubmissionstatement, '.
'm.preventsubmissionnotingroup, '.
'm.intro, '.
@ -435,6 +436,7 @@ class mod_assign_external extends \mod_assign\external\external_api {
'maxattempts' => $module->maxattempts,
'markingworkflow' => $module->markingworkflow,
'markingallocation' => $module->markingallocation,
'markinganonymous' => $module->markinganonymous,
'requiresubmissionstatement' => $module->requiresubmissionstatement,
'preventsubmissionnotingroup' => $module->preventsubmissionnotingroup,
'timelimit' => $module->timelimit,
@ -553,6 +555,7 @@ class mod_assign_external extends \mod_assign\external\external_api {
'maxattempts' => new external_value(PARAM_INT, 'maximum number of attempts allowed'),
'markingworkflow' => new external_value(PARAM_INT, 'enable marking workflow'),
'markingallocation' => new external_value(PARAM_INT, 'enable marking allocation'),
'markinganonymous' => new external_value(PARAM_INT, 'enable marking anonymous'),
'requiresubmissionstatement' => new external_value(PARAM_INT, 'student must accept submission statement'),
'preventsubmissionnotingroup' => new external_value(PARAM_INT, 'Prevent submission not in group', VALUE_OPTIONAL),
'submissionstatement' => new external_value(PARAM_RAW, 'Submission statement formatted.', VALUE_OPTIONAL),

View File

@ -344,6 +344,8 @@ $string['markerfilter'] = 'Marker filter';
$string['markerfilternomarker'] = 'No marker';
$string['markingallocation'] = 'Use marking allocation';
$string['markingallocation_help'] = 'If enabled together with marking workflow, markers can be allocated to particular students.';
$string['markinganonymous'] = 'Allow partial release of grades while marking anonymously';
$string['markinganonymous_help'] = 'If enabled together with anonymous submissions and marking workflow, it allows partial release of grades while marking anonymously.';
$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 and allows marks to be released to all students at the same time.';
$string['markingworkflowstate'] = 'Marking workflow state';

View File

@ -768,7 +768,14 @@ class assign {
if (empty($update->markingworkflow)) { // If marking workflow is disabled, make sure allocation is disabled.
$update->markingallocation = 0;
}
if (isset($formdata->markinganonymous)) {
// If marking workflow is disabled, or anonymous submissions is disabled then make sure marking anonymous is disabled.
if (empty($update->markingworkflow) || empty($update->blindmarking)) {
$update->markinganonymous = 0;
} else {
$update->markinganonymous = $formdata->markinganonymous;
}
}
$returnid = $DB->insert_record('assign', $update);
$this->instance = $DB->get_record('assign', array('id'=>$returnid), '*', MUST_EXIST);
// Cache the course record.
@ -1536,6 +1543,11 @@ class assign {
if (empty($update->markingworkflow)) { // If marking workflow is disabled, make sure allocation is disabled.
$update->markingallocation = 0;
}
$update->markinganonymous = $formdata->markinganonymous;
// If marking workflow is disabled, or blindmarking is disabled then make sure marking anonymous is disabled.
if (empty($update->markingworkflow) || empty($update->blindmarking)) {
$update->markinganonymous = 0;
}
$result = $DB->update_record('assign', $update);
$this->instance = $DB->get_record('assign', array('id'=>$update->id), '*', MUST_EXIST);
@ -8371,6 +8383,10 @@ class assign {
// Set assign gradebook feedback plugin status.
$assign->gradefeedbackenabled = $this->is_gradebook_feedback_enabled();
// If markinganonymous is enabled then allow to release grades anonymously.
if (isset($assign->markinganonymous) && $assign->markinganonymous == 1) {
assign_update_grades($assign, $userid);
}
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
\mod_assign\event\workflow_state_updated::create_from_user($this, $user, $state)->trigger();
}

View File

@ -226,6 +226,12 @@ class mod_assign_mod_form extends moodleform_mod {
$mform->addHelpButton('markingallocation', 'markingallocation', 'assign');
$mform->hideIf('markingallocation', 'markingworkflow', 'eq', 0);
$name = get_string('markinganonymous', 'assign');
$mform->addElement('selectyesno', 'markinganonymous', $name);
$mform->addHelpButton('markinganonymous', 'markinganonymous', 'assign');
$mform->hideIf('markinganonymous', 'markingworkflow', 'eq', 0);
$mform->hideIf('markinganonymous', 'blindmarking', 'eq', 0);
$this->standard_coursemodule_elements();
$this->apply_admin_defaults();

View File

@ -329,6 +329,16 @@ if ($ADMIN->fulltree) {
$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('markinganonymous', 'mod_assign');
$description = new lang_string('markinganonymous_help', 'mod_assign');
$setting = new admin_setting_configcheckbox('assign/markinganonymous',
$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);
}
$ADMIN->add('modassignfolder', $settings);

View File

@ -81,6 +81,85 @@ class restore_date_test extends \restore_date_testcase {
// Assign grade time checks.
$this->assertEquals($grade->timecreated, $newgrade->timecreated);
$this->assertEquals($grade->timemodified, $newgrade->timemodified);
}
/**
* Test backup and restore of an assignment with non-default settings.
*
* @return void
*/
public function test_restore_settings() {
global $DB;
$generator = $this->getDataGenerator();
$course = $generator->create_course(['startdate' => $this->startdate]);
$record = [
'course' => $course->id,
'name' => random_string(),
'intro' => random_string(),
'introformat' => FORMAT_MARKDOWN,
'alwaysshowdescription' => 1,
'submissiondrafts' => 1,
'sendnotifications' => 1,
'sendlatenotifications' => 1,
'sendstudentnotifications' => 0,
'duedate' => time() + 1,
'cutoffdate' => time(),
'gradingduedate' => time() + 2,
'allowsubmissionsfromdate' => time() - 1,
'grade' => 10,
'timemodified' => time(),
'completionsubmit' => 1,
'requiresubmissionstatement' => 1,
'teamsubmission' => 1,
'requireallteammemberssubmit' => 1,
'teamsubmissiongroupingid' => $generator->create_grouping(['courseid' => $course->id])->id,
'blindmarking' => 1,
'hidegrader' => 1,
'revealidentities' => 1,
'attemptreopenmethod' => 'manual',
'maxattempts' => 2,
'markingworkflow' => 1,
'markingallocation' => 1,
'markinganonymous' => 1,
'preventsubmissionnotingroup' => 1,
'activityeditor' => [
'text' => random_string(),
'format' => FORMAT_MARKDOWN,
],
'timelimit' => DAYSECS,
'submissionattachments' => 1,
];
$this->getDataGenerator()->create_module('assign', $record);
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course, $this->startdate);
$newassign = $DB->get_record('assign', ['course' => $newcourseid]);
$newgrouping = $DB->get_record('groupings', ['courseid' => $newcourseid]);
// Verify that the settings of the restored assignment are correct.
foreach ($record as $setting => $value) {
$newsetting = $newassign->{$setting} ?? null;
switch ($setting) {
case 'course':
// Should match the new course.
$this->assertEquals($newcourseid, $newsetting);
break;
case 'teamsubmissiongroupingid':
// Should match the new grouping.
$this->assertEquals($newgrouping->id, $newsetting);
break;
case 'revealidentities':
// Reset to default for a restore without user data.
$this->assertEquals(0, $newsetting);
break;
case 'activityeditor':
$this->assertEquals($value['text'], $newassign->activity);
$this->assertEquals($value['format'], $newassign->activityformat);
break;
default:
// All other settings should match the original assignment.
$this->assertEquals($value, $newsetting);
}
}
}
}

View File

@ -27,25 +27,15 @@ Feature: Bulk released grades should not be sent to gradebook while submissions
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| markingworkflow | 1 |
| markinganonymous | 0 |
| blindmarking | 1 |
| assignfeedback_comments_enabled | 1 |
| assignfeedback_editpdf_enabled | 1 |
# Add a submission.
And I am on the "Test assignment name" "assign activity" page logged in as "student1"
Then I should not see "Feedback"
And I should see "Not marked" in the "Grading status" "table_row"
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm student1's submission |
And I press "Save changes"
# Add another submission.
And I am on the "Test assignment name" "assign activity" page logged in as "student2"
Then I should not see "Feedback"
And I should see "Not marked" in the "Grading status" "table_row"
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm student2's submission |
And I press "Save changes"
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm student1's submission |
| Test assignment name | student2 | I'm student2's submission |
# Mark the submissions.
And I am on the "Test assignment name" "assign activity" page logged in as "teacher1"
And I follow "View all submissions"
@ -125,3 +115,29 @@ Feature: Bulk released grades should not be sent to gradebook while submissions
And I am on the "Course 1" "grades > User report > View" page logged in as "student2"
Then I should see "50"
And I should see "Great job!"
@javascript @_alert
Scenario: Grades are released to the gradebook if markinganonymous is enabled
Given I follow "Settings"
And I expand all fieldsets
And I set the field "Allow partial release of grades while marking anonymously" to "Yes"
And I press "Save and display"
And I follow "View all submissions"
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
Then I should not see "Student 1 (student1@example.com)"
And I should not see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"
And I set the field "Notify student" to "No"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Released" in the "I'm student1's submission" "table_row"
And I should see "Released" in the "I'm student2's submission" "table_row"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should see "50"
And I should see "Great job!"
And I am on the "Course 1" "grades > User report > View" page logged in as "student2"
Then I should see "50"
And I should see "Great job!"

View File

@ -187,6 +187,8 @@ class externallib_test extends \mod_assign\externallib_advanced_testcase {
'introformat' => FORMAT_HTML,
'markingworkflow' => 1,
'markingallocation' => 1,
'blindmarking' => 1,
'markinganonymous' => 1,
'activityeditor' => [
'text' => 'Test activity',
'format' => 1,
@ -249,6 +251,8 @@ class externallib_test extends \mod_assign\externallib_advanced_testcase {
'@"' . $CFG->wwwroot . '/webservice/pluginfile.php/\d+/mod_assign/intro/intro\.txt"@', $assignment['intro']);
$this->assertEquals(1, $assignment['markingworkflow']);
$this->assertEquals(1, $assignment['markingallocation']);
$this->assertEquals(1, $assignment['blindmarking']);
$this->assertEquals(1, $assignment['markinganonymous']);
$this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
$this->assertEquals(0, $assignment['timelimit']);
$this->assertEquals(0, $assignment['submissionattachments']);
@ -280,6 +284,8 @@ class externallib_test extends \mod_assign\externallib_advanced_testcase {
$this->assertArrayNotHasKey('introattachments', $assignment);
$this->assertEquals(1, $assignment['markingworkflow']);
$this->assertEquals(1, $assignment['markingallocation']);
$this->assertEquals(1, $assignment['blindmarking']);
$this->assertEquals(1, $assignment['markinganonymous']);
$this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
$result = mod_assign_external::get_assignments(array($course2->id));
@ -318,6 +324,8 @@ class externallib_test extends \mod_assign\externallib_advanced_testcase {
$this->assertArrayNotHasKey('introattachments', $assignment);
$this->assertEquals(1, $assignment['markingworkflow']);
$this->assertEquals(1, $assignment['markingallocation']);
$this->assertEquals(1, $assignment['blindmarking']);
$this->assertEquals(1, $assignment['markinganonymous']);
$this->assertEquals(0, $assignment['preventsubmissionnotingroup']);
}

View File

@ -56,6 +56,7 @@ class mod_assign_generator extends testing_module_generator {
'maxattempts' => -1,
'markingworkflow' => 0,
'markingallocation' => 0,
'markinganonymous' => 0,
'activityformat' => 0,
'timelimit' => 0,
'submissionattachments' => 0,

View File

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