MDL-37148 Assignment: Lots more webservices

This patch adds lots of webservices to the assignment module.
* mod_assign_revert_submissions_to_draft
* mod_assign_lock_submissions
* mod_assign_unlock_submissions
* mod_assign_save_submission
* mod_assign_submit_for_grading
* mod_assign_save_grade
* mod_assign_save_user_extensions
* mod_assign_reveal_identities
* mod_assign_copy_previous_attempt

All features such as reopening attempts and marking workflow are supported through
the save_grade and save_submission functions.

Uploading files is supported by sending draft item ids for the files_filemanager param the same functions.
This commit is contained in:
Damyon Wiese
2013-09-13 13:29:51 +08:00
parent e2e9cb6a14
commit 05a6445a14
14 changed files with 1776 additions and 302 deletions
+9 -1
View File
@@ -627,5 +627,13 @@ abstract class assign_plugin {
return true;
}
/**
* If this plugin can participate in a webservice (save_submission or save_grade),
* return a list of external_params to be included in the definition of that webservice.
*
* @return external_description|null
*/
public function get_external_parameters() {
return null;
}
}
+65
View File
@@ -63,5 +63,70 @@ $functions = array(
'classpath' => 'mod/assign/externallib.php',
'description' => 'Returns the blind marking mappings for assignments',
'type' => 'read'
),
'mod_assign_revert_submissions_to_draft' => array(
'classname' => 'mod_assign_external',
'methodname' => 'revert_submissions_to_draft',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Reverts the list of submissions to draft status',
'type' => 'write'
),
'mod_assign_lock_submissions' => array(
'classname' => 'mod_assign_external',
'methodname' => 'lock_submissions',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Prevent students from making changes to a list of submissions',
'type' => 'write'
),
'mod_assign_unlock_submissions' => array(
'classname' => 'mod_assign_external',
'methodname' => 'unlock_submissions',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Allow students to make changes to a list of submissions',
'type' => 'write'
),
'mod_assign_save_submission' => array(
'classname' => 'mod_assign_external',
'methodname' => 'save_submission',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Update the current students submission',
'type' => 'write'
),
'mod_assign_submit_for_grading' => array(
'classname' => 'mod_assign_external',
'methodname' => 'submit_for_grading',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Submit the current students assignment for grading',
'type' => 'write'
),
'mod_assign_save_grade' => array(
'classname' => 'mod_assign_external',
'methodname' => 'save_grade',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Save a grade update for a single student.',
'type' => 'write'
),
'mod_assign_save_user_extensions' => array(
'classname' => 'mod_assign_external',
'methodname' => 'save_user_extensions',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Save a list of assignment extensions',
'type' => 'write'
),
'mod_assign_reveal_identities' => array(
'classname' => 'mod_assign_external',
'methodname' => 'reveal_identities',
'classpath' => 'mod/assign/externallib.php',
'description' => 'Reveal the identities for a blind marking assignment',
'type' => 'write'
)
);
+633 -2
View File
@@ -32,6 +32,38 @@ require_once("$CFG->libdir/externallib.php");
*/
class mod_assign_external extends external_api {
/**
* Generate a warning in a standard structure for a known failure.
*
* @param int $assignmentid - The assignment
* @param string $warningcode - The key for the warning message (@see $warningmessages)
* @param string $detail - A description of the error
* @return array - Warning structure containing item, itemid, warningcode, message
*/
private static function generate_warning($assignmentid, $warningcode, $detail) {
$warningmessages = array(
'couldnotlock'=>'Could not lock the submission for this user.',
'couldnotunlock'=>'Could not unlock the submission for this user.',
'couldnotsubmitforgrading'=>'Could not submit assignment for grading.',
'couldnotrevealidentities'=>'Could not reveal identities.',
'couldnotgrantextensions'=>'Could not grant submission date extensions.',
'couldnotrevert'=>'Could not revert submission to draft.',
'invalidparameters'=>'Invalid parameters.',
'couldnotsavesubmission'=>'Could not save submission.',
'couldnotsavegrade'=>'Could not save grade.'
);
$message = $warningmessages[$warningcode];
if (empty($message)) {
$message = 'Unknown warning type.';
}
return array('item'=>$detail,
'itemid'=>$assignmentid,
'warningcode'=>$warningcode,
'message'=>$message);
}
/**
* Describes the parameters for get_grades
* @return external_external_function_parameters
@@ -102,7 +134,7 @@ class mod_assign_external extends external_api {
WHERE mxg.assignment ' . $inorequalsql2 . ' GROUP BY mxg.userid';
$sql = "SELECT ag.id,ag.assignment,ag.userid,ag.timecreated,ag.timemodified,".
"ag.grader,ag.grade ".
"ag.grader,ag.grade,ag.attemptnumber ".
"FROM {assign_grades} ag ".
"JOIN ( " . $grademaxattempt . " ) gmx ON ag.userid = gmx.userid".
" WHERE ag.assignment ".$inorequalsql.
@@ -122,6 +154,7 @@ class mod_assign_external extends external_api {
$grade['timecreated'] = $rd->timecreated;
$grade['timemodified'] = $rd->timemodified;
$grade['grader'] = $rd->grader;
$grade['attemptnumber'] = $rd->attemptnumber;
$grade['grade'] = (string)$rd->grade;
if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
@@ -170,6 +203,7 @@ class mod_assign_external extends external_api {
array(
'id' => new external_value(PARAM_INT, 'grade id'),
'userid' => new external_value(PARAM_INT, 'student id'),
'attemptnumber' => new external_value(PARAM_INT, 'attempt number'),
'timecreated' => new external_value(PARAM_INT, 'grade creation time'),
'timemodified' => new external_value(PARAM_INT, 'grade last modified time'),
'grader' => new external_value(PARAM_INT, 'grader'),
@@ -528,7 +562,7 @@ class mod_assign_external extends external_api {
WHERE mxs.assignment = :assignid1 GROUP BY mxs.userid';
$sql = "SELECT mas.id, mas.assignment,mas.userid,".
"mas.timecreated,mas.timemodified,mas.status,mas.groupid ".
"mas.timecreated,mas.timemodified,mas.status,mas.groupid,mas.attemptnumber ".
"FROM {assign_submission} mas ".
"JOIN ( " . $submissionmaxattempt . " ) smx ON mas.userid = smx.userid ".
"WHERE mas.assignment = :assignid2 AND mas.attemptnumber = smx.maxattempt";
@@ -557,6 +591,7 @@ class mod_assign_external extends external_api {
'timecreated' => $submissionrecord->timecreated,
'timemodified' => $submissionrecord->timemodified,
'status' => $submissionrecord->status,
'attemptnumber' => $submissionrecord->attemptnumber,
'groupid' => $submissionrecord->groupid
);
foreach ($submissionplugins as $submissionplugin) {
@@ -638,6 +673,7 @@ class mod_assign_external extends external_api {
array(
'id' => new external_value(PARAM_INT, 'submission id'),
'userid' => new external_value(PARAM_INT, 'student id'),
'attemptnumber' => new external_value(PARAM_INT, 'attempt number'),
'timecreated' => new external_value(PARAM_INT, 'submission creation time'),
'timemodified' => new external_value(PARAM_INT, 'submission last modified time'),
'status' => new external_value(PARAM_TEXT, 'submission status'),
@@ -995,4 +1031,599 @@ class mod_assign_external extends external_api {
);
}
/**
* Describes the parameters for lock_submissions
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function lock_submissions_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
'userids' => new external_multiple_structure(
new external_value(PARAM_INT, 'user id'),
'1 or more user ids',
VALUE_REQUIRED),
)
);
}
/**
* Locks (prevent updates to) submissions in this assignment.
*
* @param int $assignmentid The id of the assignment
* @param array $userids Array of user ids to lock
* @return array of warnings for each submission that could not be locked.
* @since Moodle 2.6
*/
public static function lock_submissions($assignmentid, $userids) {
global $CFG;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::lock_submissions_parameters(),
array('assignmentid' => $assignmentid,
'userids' => $userids));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$warnings = array();
foreach ($userids as $userid) {
if (!$assignment->lock_submission($userid)) {
$detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid;
$warnings[] = self::generate_warning($assignmentid,
'couldnotlock',
$detail);
}
}
return $warnings;
}
/**
* Describes the return value for lock_submissions
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function lock_submissions_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for revert_submissions_to_draft
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function revert_submissions_to_draft_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
'userids' => new external_multiple_structure(
new external_value(PARAM_INT, 'user id'),
'1 or more user ids',
VALUE_REQUIRED),
)
);
}
/**
* Reverts a list of user submissions to draft for a single assignment.
*
* @param int $assignmentid The id of the assignment
* @param array $userids Array of user ids to revert
* @return array of warnings for each submission that could not be reverted.
* @since Moodle 2.6
*/
public static function revert_submissions_to_draft($assignmentid, $userids) {
global $CFG;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::revert_submissions_to_draft_parameters(),
array('assignmentid' => $assignmentid,
'userids' => $userids));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$warnings = array();
foreach ($userids as $userid) {
if (!$assignment->revert_to_draft($userid)) {
$detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid;
$warnings[] = self::generate_warning($assignmentid,
'couldnotrevert',
$detail);
}
}
return $warnings;
}
/**
* Describes the return value for revert_submissions_to_draft
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function revert_submissions_to_draft_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for unlock_submissions
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function unlock_submissions_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
'userids' => new external_multiple_structure(
new external_value(PARAM_INT, 'user id'),
'1 or more user ids',
VALUE_REQUIRED),
)
);
}
/**
* Locks (prevent updates to) submissions in this assignment.
*
* @param int $assignmentid The id of the assignment
* @param array $userids Array of user ids to lock
* @return array of warnings for each submission that could not be locked.
* @since Moodle 2.6
*/
public static function unlock_submissions($assignmentid, $userids) {
global $CFG;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::unlock_submissions_parameters(),
array('assignmentid' => $assignmentid,
'userids' => $userids));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$warnings = array();
foreach ($userids as $userid) {
if (!$assignment->unlock_submission($userid)) {
$detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid;
$warnings[] = self::generate_warning($assignmentid,
'couldnotunlock',
$detail);
}
}
return $warnings;
}
/**
* Describes the return value for unlock_submissions
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function unlock_submissions_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for unlock_submissions
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function submit_for_grading_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on')
)
);
}
/**
* Submit the logged in users assignment for grading.
*
* @param int $assignmentid The id of the assignment
* @return array of warnings to indicate any errors.
* @since Moodle 2.6
*/
public static function submit_for_grading($assignmentid) {
global $CFG, $USER;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::submit_for_grading_parameters(),
array('assignmentid' => $assignmentid));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$warnings = array();
if (!$assignment->submit_for_grading()) {
$detail = 'User id: ' . $USER->id . ', Assignment id: ' . $assignmentid;
$warnings[] = self::generate_warning($assignmentid,
'couldnotsubmitforgrading',
$detail);
}
return $warnings;
}
/**
* Describes the return value for submit_for_grading
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function submit_for_grading_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for save_user_extensions
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function save_user_extensions_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
'userids' => new external_multiple_structure(
new external_value(PARAM_INT, 'user id'),
'1 or more user ids',
VALUE_REQUIRED),
'dates' => new external_multiple_structure(
new external_value(PARAM_INT, 'dates'),
'1 or more extension dates (timestamp)',
VALUE_REQUIRED),
)
);
}
/**
* Grant extension dates to students for an assignment.
*
* @param int $assignmentid The id of the assignment
* @param array $userids Array of user ids to grant extensions to
* @param array $dates Array of extension dates
* @return array of warnings for each extension date that could not be granted
* @since Moodle 2.6
*/
public static function save_user_extensions($assignmentid, $userids, $dates) {
global $CFG;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::save_user_extensions_parameters(),
array('assignmentid' => $assignmentid,
'userids' => $userids,
'dates' => $dates));
if (count($userids) != count($dates)) {
$detail = 'Length of userids and dates parameters differ.';
$warnings[] = self::generate_warning($assignmentid,
'invalidparameters',
$detail);
return $warnings;
}
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$warnings = array();
foreach ($userids as $idx => $userid) {
$duedate = $dates[$idx];
if (!$assignment->save_user_extension($userid, $duedate)) {
$detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid . ', Extension date: ' . $duedate;
$warnings[] = self::generate_warning($assignmentid,
'couldnotgrantextensions',
$detail);
}
}
return $warnings;
}
/**
* Describes the return value for save_user_extensions
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function save_user_extensions_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for reveal_identities
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function reveal_identities_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on')
)
);
}
/**
* Reveal the identities of anonymous students to markers for a single assignment.
*
* @param int $assignmentid The id of the assignment
* @return array of warnings to indicate any errors.
* @since Moodle 2.6
*/
public static function reveal_identities($assignmentid) {
global $CFG, $USER;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::reveal_identities_parameters(),
array('assignmentid' => $assignmentid));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$warnings = array();
if (!$assignment->reveal_identities()) {
$detail = 'User id: ' . $USER->id . ', Assignment id: ' . $assignmentid;
$warnings[] = self::generate_warning($assignmentid,
'couldnotrevealidentities',
$detail);
}
return $warnings;
}
/**
* Describes the return value for reveal_identities
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function reveal_identities_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for save_submission
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function save_submission_parameters() {
global $CFG;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$instance = new assign(null, null, null);
$pluginsubmissionparams = array();
foreach ($instance->get_submission_plugins() as $plugin) {
$pluginparams = $plugin->get_external_parameters();
if (!empty($pluginparams)) {
$pluginsubmissionparams = array_merge($pluginsubmissionparams, $pluginparams);
}
}
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
'plugindata' => new external_single_structure(
$pluginsubmissionparams
)
)
);
}
/**
* Save a student submission for a single assignment.
*
* @param int $assignmentid The id of the assignment
* @return array of warnings to indicate any errors.
* @since Moodle 2.6
*/
public static function save_submission($assignmentid, $plugindata) {
global $CFG, $USER;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::save_submission_parameters(),
array('assignmentid' => $assignmentid,
'plugindata' => $plugindata));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$notices = array();
$submissiondata = (object)$plugindata;
$assignment->save_submission($submissiondata, $notices);
$warnings = array();
foreach ($notices as $notice) {
$warnings[] = self::generate_warning($assignmentid,
'couldnotsavesubmission',
$notice);
}
return $warnings;
}
/**
* Describes the return value for save_submission
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function save_submission_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
/**
* Describes the parameters for save_grade
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function save_grade_parameters() {
global $CFG;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$instance = new assign(null, null, null);
$pluginfeedbackparams = array();
foreach ($instance->get_feedback_plugins() as $plugin) {
$pluginparams = $plugin->get_external_parameters();
if (!empty($pluginparams)) {
$pluginfeedbackparams = array_merge($pluginfeedbackparams, $pluginparams);
}
}
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
'userid' => new external_value(PARAM_INT, 'The student id to operate on'),
'grade' => new external_value(PARAM_FLOAT, 'The new grade for this user'),
'attemptnumber' => new external_value(PARAM_INT, 'The attempt number (-1 means latest attempt)'),
'addattempt' => new external_value(PARAM_BOOL, 'Allow another attempt if the attempt reopen method is manual'),
'workflowstate' => new external_value(PARAM_ALPHA, 'The next marking workflow state'),
'applytoall' => new external_value(PARAM_BOOL, 'If true, this grade will be applied ' .
'to all members ' .
'of the group (for group assignments).'),
'plugindata' => new external_single_structure(
$pluginfeedbackparams
)
)
);
}
/**
* Save a student grade for a single assignment.
*
* @param int $assignmentid The id of the assignment
* @return null
* @since Moodle 2.6
*/
public static function save_grade($assignmentid, $userid, $grade, $attemptnumber, $addattempt, $workflowstate, $applytoall, $plugindata) {
global $CFG, $USER;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::save_grade_parameters(),
array('assignmentid' => $assignmentid,
'userid' => $userid,
'grade' => $grade,
'attemptnumber' => $attemptnumber,
'workflowstate' => $workflowstate,
'addattempt' => $addattempt,
'applytoall' => $applytoall,
'plugindata' => $plugindata));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$gradedata = (object)$plugindata;
$gradedata->addattempt = $addattempt;
$gradedata->attemptnumber = $attemptnumber;
$gradedata->workflowstate = $workflowstate;
$gradedata->applytoall = $applytoall;
$gradedata->grade = $grade;
$assignment->save_grade($userid, $gradedata);
return null;
}
/**
* Describes the return value for save_grade
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function save_grade_returns() {
return null;
}
/**
* Describes the parameters for copy_previous_attempt
* @return external_external_function_parameters
* @since Moodle 2.6
*/
public static function copy_previous_attempt_parameters() {
return new external_function_parameters(
array(
'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
)
);
}
/**
* Copy a students previous attempt to a new attempt.
*
* @return array of warnings to indicate any errors.
* @since Moodle 2.6
*/
public static function copy_previous_attempt($assignmentid) {
global $CFG, $USER;
require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::copy_previous_attempt_parameters(),
array('assignmentid' => $assignmentid));
$cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
$assignment = new assign($context, $cm, null);
$notices = array();
$assignment->copy_previous_attempt($submissiondata, $notices);
$warnings = array();
foreach ($notices as $notice) {
$warnings[] = self::generate_warning($assignmentid,
'couldnotcopyprevioussubmission',
$notice);
}
return $warnings;
}
/**
* Describes the return value for save_submission
*
* @return external_single_structure
* @since Moodle 2.6
*/
public static function copy_previous_attempt_returns() {
return new external_multiple_structure(
new external_warnings()
);
}
}
+12
View File
@@ -390,4 +390,16 @@ class assign_feedback_comments extends assign_feedback_plugin {
return $this->view($grade) == '';
}
/**
* Return a description of external params suitable for uploading an feedback comment from a webservice.
*
* @return external_description|null
*/
public function get_external_parameters() {
$editorparams = array('text' => new external_value(PARAM_TEXT, 'The text for this feedback.'),
'format' => new external_value(PARAM_INT, 'The format for this feedback'));
$editorstructure = new external_single_structure($editorparams);
return array('assignfeedbackcomments_editor' => $editorstructure);
}
}
+10
View File
@@ -609,4 +609,14 @@ class assign_feedback_file extends assign_feedback_plugin {
public function get_grading_actions() {
return array('uploadzip'=>get_string('uploadzip', 'assignfeedback_file'));
}
/**
* Return a description of external params suitable for uploading a feedback file from a webservice.
*
* @return external_description|null
*/
public function get_external_parameters() {
return array('files_filemanager' => new external_value(PARAM_INT, 'The id of a draft area containing files for this feedback.'));
}
}
+405 -260
View File
@@ -389,7 +389,7 @@ class assign {
$nextpageparams['action'] = 'editsubmission';
}
} else if ($action == 'lock') {
$this->process_lock();
$this->process_lock_submission();
$action = 'redirect';
$nextpageparams['action'] = 'grading';
} else if ($action == 'addattempt') {
@@ -401,7 +401,7 @@ class assign {
$action = 'redirect';
$nextpageparams['action'] = 'grading';
} else if ($action == 'unlock') {
$this->process_unlock();
$this->process_unlock_submission();
$action = 'redirect';
$nextpageparams['action'] = 'grading';
} else if ($action == 'setbatchmarkingworkflowstate') {
@@ -3314,9 +3314,9 @@ class assign {
foreach ($userlist as $userid) {
if ($data->operation == 'lock') {
$this->process_lock($userid);
$this->process_lock_submission($userid);
} else if ($data->operation == 'unlock') {
$this->process_unlock($userid);
$this->process_unlock_submission($userid);
} else if ($data->operation == 'reverttodraft') {
$this->process_revert_to_draft($userid);
} else if ($data->operation == 'addattempt') {
@@ -4462,6 +4462,71 @@ class assign {
}
}
/**
* Submit a submission for grading.
*
* @return bool Return false if the submission was not submitted.
*/
public function submit_for_grading() {
global $USER;
// Need submit permission to submit an assignment.
require_capability('mod/assign:submit', $this->context);
$instance = $this->get_instance();
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($USER->id, 0, true);
} else {
$submission = $this->get_user_submission($USER->id, true);
}
if (!$this->submissions_open($USER->id)) {
return false;
}
if ($submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
// Give each submission plugin a chance to process the submission.
$plugins = $this->get_submission_plugins();
foreach ($plugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
$plugin->submit_for_grading($submission);
}
}
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
$this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
$completion = new completion_info($this->get_course());
if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
$completion->update_state($this->get_course_module(), COMPLETION_COMPLETE, $USER->id);
}
if (isset($data->submissionstatement)) {
$logmessage = get_string('submissionstatementacceptedlog',
'mod_assign',
fullname($USER));
$this->add_to_log('submission statement accepted', $logmessage);
}
$logdata = $this->add_to_log('submit for grading', $this->format_submission_for_log($submission), '', true);
$this->notify_graders($submission);
$this->notify_student_submission_receipt($submission);
// Trigger assessable_submitted event on submission.
$params = array(
'context' => context_module::instance($this->get_course_module()->id),
'objectid' => $submission->id,
'other' => array(
'submission_editable' => false
)
);
$event = \mod_assign\event\assessable_submitted::create($params);
$event->set_legacy_logdata($logdata);
$event->trigger();
return true;
}
return false;
}
/**
* Assignment submission is processed before grading.
*
@@ -4472,8 +4537,6 @@ class assign {
protected function process_submit_for_grading($mform) {
global $USER, $CFG;
// Need submit permission to submit an assignment.
require_capability('mod/assign:submit', $this->context);
require_once($CFG->dirroot . '/mod/assign/submissionconfirmform.php');
require_sesskey();
@@ -4503,57 +4566,7 @@ class assign {
if ($mform->get_data() == false) {
return false;
}
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($USER->id, 0, true);
} else {
$submission = $this->get_user_submission($USER->id, true);
}
if ($submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
// Give each submission plugin a chance to process the submission.
$plugins = $this->get_submission_plugins();
foreach ($plugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
$plugin->submit_for_grading($submission);
}
}
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
$this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
$completion = new completion_info($this->get_course());
if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
$completion->update_state($this->get_course_module(), COMPLETION_COMPLETE, $USER->id);
}
if (isset($data->submissionstatement)) {
$logmessage = get_string('submissionstatementacceptedlog',
'mod_assign',
fullname($USER));
$addtolog = $this->add_to_log('submission statement accepted', $logmessage, '', true);
$params = array(
'context' => $this->context,
'objectid' => $submission->id
);
$event = \mod_assign\event\statement_accepted::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
}
$logdata = $this->add_to_log('submit for grading', $this->format_submission_for_log($submission), '', true);
$this->notify_graders($submission);
$this->notify_student_submission_receipt($submission);
// Trigger assessable_submitted event on submission.
$params = array(
'context' => context_module::instance($this->get_course_module()->id),
'objectid' => $submission->id,
'other' => array(
'submission_editable' => false
)
);
$event = \mod_assign\event\assessable_submitted::create($params);
$event->set_legacy_logdata($logdata);
$event->trigger();
}
return $this->submit_for_grading();
}
return true;
}
@@ -4565,9 +4578,30 @@ class assign {
* @param mixed $extensionduedate Either an integer date or null
* @return boolean
*/
protected function save_user_extension($userid, $extensionduedate) {
public function save_user_extension($userid, $extensionduedate) {
global $DB;
// Need submit permission to submit an assignment.
require_capability('mod/assign:grantextension', $this->context);
if (!is_enrolled($this->get_course_context(), $userid)) {
return false;
}
if (!has_capability('mod/assign:submit', $this->context, $userid)) {
return false;
}
if ($this->get_instance()->duedate && $extensionduedate) {
if ($this->get_instance()->duedate > $extensionduedate) {
return false;
}
}
if ($this->get_instance()->allowsubmissionsfromdate && $extensionduedate) {
if ($this->get_instance()->allowsubmissionsfromdate > $extensionduedate) {
return false;
}
}
$flags = $this->get_user_flags($userid, true);
$flags->extensionduedate = $extensionduedate;
@@ -4599,9 +4633,6 @@ class assign {
// Include extension form.
require_once($CFG->dirroot . '/mod/assign/extensionform.php');
// Need submit permission to submit an assignment.
require_capability('mod/assign:grantextension', $this->context);
$batchusers = optional_param('selectedusers', '', PARAM_SEQUENCE);
$userid = 0;
if (!$batchusers) {
@@ -4834,11 +4865,12 @@ class assign {
*
* @return void
*/
protected function process_reveal_identities() {
global $DB, $CFG;
public function reveal_identities() {
global $DB;
require_capability('mod/assign:revealidentities', $this->context);
if (!confirm_sesskey()) {
if ($this->get_instance()->revealidentities || empty($this->get_instance()->blindmarking)) {
return false;
}
@@ -4882,6 +4914,20 @@ class assign {
$event->trigger();
}
/**
* Reveal student identities to markers (and the gradebook).
*
* @return void
*/
protected function process_reveal_identities() {
if (!confirm_sesskey()) {
return false;
}
return $this->reveal_identities();
}
/**
* Save grading options.
@@ -5009,15 +5055,30 @@ class assign {
}
/**
* Copy the current assignment submission from the last submitted attempt.
* Require a valid sess key and then call copy_previous_attempt.
*
* @param array $notices Any error messages that should be shown
* to the user at the top of the edit submission form.
* @return bool
*/
protected function process_copy_previous_attempt(&$notices) {
require_sesskey();
return copy_previous_attempt($notices);
}
/**
* Copy the current assignment submission from the last submitted attempt.
*
* @param array $notices Any error messages that should be shown
* to the user at the top of the edit submission form.
* @return bool
*/
public function copy_previous_attempt(&$notices) {
global $USER, $CFG;
require_capability('mod/assign:submit', $this->context);
$instance = $this->get_instance();
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($USER->id, 0, true);
@@ -5127,6 +5188,108 @@ class assign {
return $allempty;
}
/**
* Save assignment submission for the current user.
*
* @param stdClass $data
* @param array $notices Any error messages that should be shown
* to the user.
* @return bool
*/
public function save_submission(stdClass $data, & $notices) {
global $CFG, $USER;
require_capability('mod/assign:submit', $this->context);
$instance = $this->get_instance();
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($USER->id, 0, true);
} else {
$submission = $this->get_user_submission($USER->id, true);
}
if ($instance->submissiondrafts) {
$submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
} else {
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
}
$flags = $this->get_user_flags($USER->id, false);
// Get the flags to check if it is locked.
if ($flags && $flags->locked) {
print_error('submissionslocked', 'assign');
return true;
}
$pluginerror = false;
foreach ($this->submissionplugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
if (!$plugin->save($submission, $data)) {
$notices[] = $plugin->get_error();
$pluginerror = true;
}
}
}
$allempty = $this->submission_empty($submission);
if ($pluginerror || $allempty) {
if ($allempty) {
$notices[] = get_string('submissionempty', 'mod_assign');
}
return false;
}
$this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
// Logging.
if (isset($data->submissionstatement)) {
$logmessage = get_string('submissionstatementacceptedlog',
'mod_assign',
fullname($USER));
$this->add_to_log('submission statement accepted', $logmessage);
$addtolog = $this->add_to_log('submission statement accepted', $logmessage, '', true);
$params = array(
'context' => $this->context,
'objectid' => $submission->id
);
$event = \mod_assign\event\statement_accepted::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
}
$addtolog = $this->add_to_log('submit', $this->format_submission_for_log($submission), '', true);
$params = array(
'context' => $this->context,
'objectid' => $submission->id
);
$event = \mod_assign\event\submission_updated::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
$complete = COMPLETION_INCOMPLETE;
if ($submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
$complete = COMPLETION_COMPLETE;
}
$completion = new completion_info($this->get_course());
if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
$completion->update_state($this->get_course_module(), $complete, $USER->id);
}
if (!$instance->submissiondrafts) {
$this->notify_student_submission_receipt($submission);
$this->notify_graders($submission);
// Trigger assessable_submitted event on submission.
$params = array(
'context' => context_module::instance($this->get_course_module()->id),
'objectid' => $submission->id,
'other' => array(
'submission_editable' => true
)
);
$event = \mod_assign\event\assessable_submitted::create($params);
$event->trigger();
}
return true;
}
/**
* Save assignment submission.
*
@@ -5136,13 +5299,12 @@ class assign {
* @return bool
*/
protected function process_save_submission(&$mform, &$notices) {
global $USER, $CFG;
global $CFG;
// Include submission form.
require_once($CFG->dirroot . '/mod/assign/submission_form.php');
// Need submit permission to submit an assignment.
require_capability('mod/assign:submit', $this->context);
require_sesskey();
if (!$this->submissions_open()) {
$notices[] = get_string('duedatereached', 'assign');
@@ -5156,92 +5318,7 @@ class assign {
return true;
}
if ($data = $mform->get_data()) {
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($USER->id, 0, true);
} else {
$submission = $this->get_user_submission($USER->id, true);
}
if ($instance->submissiondrafts) {
$submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
} else {
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
}
$flags = $this->get_user_flags($USER->id, false);
// Get the flags to check if it is locked.
if ($flags && $flags->locked) {
print_error('submissionslocked', 'assign');
return true;
}
$pluginerror = false;
foreach ($this->submissionplugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
if (!$plugin->save($submission, $data)) {
$notices[] = $plugin->get_error();
$pluginerror = true;
}
}
}
$allempty = $this->submission_empty($submission);
if ($pluginerror || $allempty) {
if ($allempty) {
$notices[] = get_string('submissionempty', 'mod_assign');
}
return false;
}
$this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
// Logging.
if (isset($data->submissionstatement)) {
$logmessage = get_string('submissionstatementacceptedlog',
'mod_assign',
fullname($USER));
$addtolog = $this->add_to_log('submission statement accepted', $logmessage, '', true);
$params = array(
'context' => $this->context,
'objectid' => $submission->id
);
$event = \mod_assign\event\statement_accepted::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
}
$addtolog = $this->add_to_log('submit', $this->format_submission_for_log($submission), '', true);
$params = array(
'context' => $this->context,
'objectid' => $submission->id
);
$event = \mod_assign\event\submission_updated::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
$complete = COMPLETION_INCOMPLETE;
if ($submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
$complete = COMPLETION_COMPLETE;
}
$completion = new completion_info($this->get_course());
if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
$completion->update_state($this->get_course_module(), $complete, $USER->id);
}
if (!$instance->submissiondrafts) {
$this->notify_student_submission_receipt($submission);
$this->notify_graders($submission);
// Trigger assessable_submitted event on submission.
$params = array(
'context' => context_module::instance($this->get_course_module()->id),
'objectid' => $submission->id,
'other' => array(
'submission_editable' => true
)
);
$event = \mod_assign\event\assessable_submitted::create($params);
$event->trigger();
}
return true;
return $this->save_submission($data, $notices);
}
return false;
}
@@ -5677,21 +5754,15 @@ class assign {
/**
* Revert to draft.
* Uses url parameter userid
*
* @param int $userid
* @return void
* @return boolean
*/
protected function process_revert_to_draft($userid = 0) {
public function revert_to_draft($userid) {
global $DB, $USER;
// Need grade permission.
require_capability('mod/assign:grade', $this->context);
require_sesskey();
if (!$userid) {
$userid = required_param('userid', PARAM_INT);
}
if ($this->get_instance()->teamsubmission) {
$submission = $this->get_group_submission($userid, 0, false);
@@ -5700,7 +5771,7 @@ class assign {
}
if (!$submission) {
return;
return false;
}
$submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
$this->update_submission($submission, $userid, true, $this->get_instance()->teamsubmission);
@@ -5739,39 +5810,51 @@ class assign {
$event = \mod_assign\event\submission_status_updated::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
return true;
}
/**
* Lock the process.
* Uses url parameter userid
* Revert to draft.
* Uses url parameter userid if userid not supplied as a parameter.
*
* @param int $userid
* @return void
* @return boolean
*/
protected function process_lock($userid = 0) {
global $USER, $DB;
// Need grade permission.
require_capability('mod/assign:grade', $this->context);
protected function process_revert_to_draft($userid = 0) {
require_sesskey();
if (!$userid) {
$userid = required_param('userid', PARAM_INT);
}
return $this->revert_to_draft($userid);
}
/**
* Prevent student updates to this submission
*
* @param int $userid
* @return bool
*/
public function lock_submission($userid) {
global $USER, $DB;
// Need grade permission.
require_capability('mod/assign:grade', $this->context);
// Give each submission plugin a chance to process the locking.
$plugins = $this->get_submission_plugins();
$submission = $this->get_user_submission($userid, false);
foreach ($plugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
$plugin->lock($submission);
}
}
$flags = $this->get_user_flags($userid, true);
$flags->locked = 1;
$this->update_user_flags($flags);
foreach ($plugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
$plugin->lock($submission, $flags);
}
}
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
$logmessage = get_string('locksubmissionforstudent',
@@ -5786,6 +5869,7 @@ class assign {
$event = \mod_assign\event\submission_locked::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
return true;
}
@@ -5896,34 +5980,50 @@ class assign {
/**
* Unlock the process.
* Prevent student updates to this submission.
* Uses url parameter userid.
*
* @param int $userid
* @return void
*/
protected function process_unlock($userid = 0) {
global $USER, $DB;
protected function process_lock_submission($userid = 0) {
// Need grade permission.
require_capability('mod/assign:grade', $this->context);
require_sesskey();
if (!$userid) {
$userid = required_param('userid', PARAM_INT);
}
return $this->lock_submission($userid);
}
/**
* Unlock the student submission.
*
* @param int $userid
* @return bool
*/
public function unlock_submission($userid) {
global $USER, $DB;
// Need grade permission.
require_capability('mod/assign:grade', $this->context);
// Give each submission plugin a chance to process the unlocking.
$plugins = $this->get_submission_plugins();
$submission = $this->get_user_submission($userid, false);
foreach ($plugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
$plugin->unlock($submission);
}
}
$flags = $this->get_user_flags($userid, true);
$flags->locked = 0;
$this->update_user_flags($flags);
foreach ($plugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
$plugin->unlock($submission, $flags);
}
}
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
$logmessage = get_string('unlocksubmissionforstudent',
@@ -5938,6 +6038,25 @@ class assign {
$event = \mod_assign\event\submission_unlocked::create($params);
$event->set_legacy_logdata($addtolog);
$event->trigger();
return true;
}
/**
* Unlock the student submission.
* Uses url parameter userid.
*
* @param int $userid
* @return bool
*/
protected function process_unlock_submission($userid = 0) {
require_sesskey();
if (!$userid) {
$userid = required_param('userid', PARAM_INT);
}
return $this->unlock_submission($userid);
}
/**
@@ -6051,6 +6170,93 @@ class assign {
}
/**
* Save grade update.
*
* @param int $userid
* @param stdClass $data
* @param int $attemptnumber - -1 means latest attempt
* @return bool - was the grade saved
*/
public function save_grade($userid, $data) {
// Need grade permission.
require_capability('mod/assign:grade', $this->context);
$instance = $this->get_instance();
$submission = null;
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($userid, 0, false, $data->attemptnumber);
} else {
$submission = $this->get_user_submission($userid, false, $data->attemptnumber);
}
if ($instance->teamsubmission && $data->applytoall) {
$groupid = 0;
if ($this->get_submission_group($userid)) {
$group = $this->get_submission_group($userid);
if ($group) {
$groupid = $group->id;
}
}
$members = $this->get_submission_group_members($groupid, true);
foreach ($members as $member) {
// User may exist in multple groups (which should put them in the default group).
$this->apply_grade_to_user($data, $member->id, $data->attemptnumber);
$this->process_outcomes($member->id, $data);
}
} else {
$this->apply_grade_to_user($data, $userid, $data->attemptnumber);
$this->process_outcomes($userid, $data);
}
$maxattemptsreached = !empty($submission) &&
$submission->attemptnumber >= ($instance->maxattempts - 1) &&
$instance->maxattempts != ASSIGN_UNLIMITED_ATTEMPTS;
$shouldreopen = false;
if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
// Check the gradetopass from the gradebook.
$gradinginfo = grade_get_grades($this->get_course()->id,
'mod',
'assign',
$instance->id,
$userid);
// What do we do if the grade has not been added to the gradebook (e.g. blind marking)?
$gradingitem = null;
$gradebookgrade = null;
if (isset($gradinginfo->items[0])) {
$gradingitem = $gradinginfo->items[0];
$gradebookgrade = $gradingitem->grades[$userid];
}
if ($gradebookgrade) {
// TODO: This code should call grade_grade->is_passed().
$shouldreopen = true;
if (is_null($gradebookgrade->grade)) {
$shouldreopen = false;
}
if (empty($gradingitem->gradepass) || $gradingitem->gradepass == $gradingitem->grademin) {
$shouldreopen = false;
}
if ($gradebookgrade->grade >= $gradingitem->gradepass) {
$shouldreopen = false;
}
}
}
if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL &&
!empty($data->addattempt)) {
$shouldreopen = true;
}
// Never reopen if we are editing a previous attempt.
if ($data->attemptnumber != -1) {
$shouldreopen = false;
}
if ($shouldreopen && !$maxattemptsreached) {
$this->add_attempt($userid);
}
return true;
}
/**
* Save grade.
*
@@ -6062,8 +6268,6 @@ class assign {
// Include grade form.
require_once($CFG->dirroot . '/mod/assign/gradeform.php');
// Need submit permission to submit an assignment.
require_capability('mod/assign:grade', $this->context);
require_sesskey();
$instance = $this->get_instance();
@@ -6102,80 +6306,10 @@ class assign {
array('class'=>'gradeform'));
if ($formdata = $mform->get_data()) {
$submission = null;
if ($instance->teamsubmission) {
$submission = $this->get_group_submission($userid, 0, false, $attemptnumber);
} else {
$submission = $this->get_user_submission($userid, false, $attemptnumber);
}
if ($instance->teamsubmission && $formdata->applytoall) {
$groupid = 0;
if ($this->get_submission_group($userid)) {
$group = $this->get_submission_group($userid);
if ($group) {
$groupid = $group->id;
}
}
$members = $this->get_submission_group_members($groupid, true);
foreach ($members as $member) {
// User may exist in multple groups (which should put them in the default group).
$this->apply_grade_to_user($formdata, $member->id, $attemptnumber);
$this->process_outcomes($member->id, $formdata);
}
} else {
$this->apply_grade_to_user($formdata, $userid, $attemptnumber);
$this->process_outcomes($userid, $formdata);
}
$maxattemptsreached = !empty($submission) &&
$submission->attemptnumber >= ($instance->maxattempts - 1) &&
$instance->maxattempts != ASSIGN_UNLIMITED_ATTEMPTS;
$shouldreopen = false;
if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
// Check the gradetopass from the gradebook.
$gradinginfo = grade_get_grades($this->get_course()->id,
'mod',
'assign',
$instance->id,
$userid);
// What do we do if the grade has not been added to the gradebook (e.g. blind marking)?
$gradingitem = null;
$gradebookgrade = null;
if (isset($gradinginfo->items[0])) {
$gradingitem = $gradinginfo->items[0];
$gradebookgrade = $gradingitem->grades[$userid];
}
if ($gradebookgrade) {
// TODO: This code should call grade_grade->is_passed().
$shouldreopen = true;
if (is_null($gradebookgrade->grade)) {
$shouldreopen = false;
}
if (empty($gradingitem->gradepass) || $gradingitem->gradepass == $gradingitem->grademin) {
$shouldreopen = false;
}
if ($gradebookgrade->grade >= $gradingitem->gradepass) {
$shouldreopen = false;
}
}
}
if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL &&
!empty($formdata->addattempt)) {
$shouldreopen = true;
}
// Never reopen if we are editing a previous attempt.
if ($attemptnumber != -1) {
$shouldreopen = false;
}
if ($shouldreopen && !$maxattemptsreached) {
$this->process_add_attempt($userid);
}
return $this->save_grade($userid, $formdata);
} else {
return false;
}
return true;
}
/**
@@ -6288,15 +6422,26 @@ class assign {
}
/**
* Add a new attempt for a user.
* Check for a sess key and then call add_attempt.
*
* @param int $userid int The user to add the attempt for
* @return bool - true if successful.
*/
protected function process_add_attempt($userid) {
require_capability('mod/assign:grade', $this->context);
require_sesskey();
return $this->add_attempt($userid);
}
/**
* Add a new attempt for a user.
*
* @param int $userid int The user to add the attempt for
* @return bool - true if successful.
*/
protected function add_attempt($userid) {
require_capability('mod/assign:grade', $this->context);
if ($this->get_instance()->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) {
return false;
}
+9
View File
@@ -477,4 +477,13 @@ class assign_submission_file extends assign_submission_plugin {
}
return true;
}
/**
* Return a description of external params suitable for uploading a file submission from a webservice.
*
* @return external_description|null
*/
public function get_external_parameters() {
return array('files_filemanager' => new external_value(PARAM_INT, 'The id of a draft area containing files for this submission.'));
}
}
@@ -495,6 +495,20 @@ class assign_submission_onlinetext extends assign_submission_plugin {
}
return true;
}
/**
* Return a description of external params suitable for uploading an onlinetext submission from a webservice.
*
* @return external_description|null
*/
public function get_external_parameters() {
$editorparams = array('text' => new external_value(PARAM_TEXT, 'The text for this submission.'),
'format' => new external_value(PARAM_INT, 'The format for this submission'),
'itemid' => new external_value(PARAM_INT, 'The draft area id for files attached to the submission'));
$editorstructure = new external_single_structure($editorparams);
return array('onlinetext_editor' => $editorstructure);
}
}
+6 -4
View File
@@ -88,19 +88,21 @@ abstract class assign_submission_plugin extends assign_plugin {
/*
* Carry out any extra processing required when the work is locked.
*
* @param stdClass $submission - assign_submission data
* @param stdClass|false $submission - assign_submission data if any
* @param stdClass $flags - User flags record
* @return void
*/
public function lock(stdClass $submission) {
public function lock($submission, stdClass $flags) {
}
/**
* Carry out any extra processing required when the work is unlocked.
*
* @param stdClass $submission - assign_submission data
* @param stdClass $submission|false - assign_submission data if any
* @param stdClass $flags - User flags record
* @return void
*/
public function unlock(stdClass $submission) {
public function unlock($submission, stdClass $flags) {
}
/**
-20
View File
@@ -223,10 +223,6 @@ class mod_assign_base_testcase extends advanced_testcase {
*/
class testable_assign extends assign {
public function testable_process_reveal_identities() {
return parent::process_reveal_identities();
}
public function testable_show_intro() {
return parent::show_intro();
}
@@ -259,10 +255,6 @@ class testable_assign extends assign {
return parent::process_add_attempt($userid);
}
public function testable_process_lock($userid = 0) {
return parent::process_lock($userid);
}
public function testable_process_save_quick_grades($postdata) {
// Ugly hack to get something into the method.
global $_POST;
@@ -270,18 +262,6 @@ class testable_assign extends assign {
return parent::process_save_quick_grades();
}
public function testable_process_unlock($userid = 0) {
return parent::process_unlock($userid);
}
public function testable_process_copy_previous_attempt(&$notices) {
return parent::process_copy_previous_attempt($notices);
}
public function testable_process_revert_to_draft($userid = 0) {
return parent::process_revert_to_draft($userid);
}
public function testable_process_set_batch_marking_allocation($selectedusers, $markerid) {
// Ugly hack to get something into the method.
global $_POST;
+593 -5
View File
@@ -41,7 +41,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
/**
* Test get_grades
*/
public function test_get_grades () {
public function test_get_grades() {
global $DB, $USER;
$this->resetAfterTest(true);
@@ -118,7 +118,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
/**
* Test get_assignments
*/
public function test_get_assignments () {
public function test_get_assignments() {
global $DB, $USER;
$this->resetAfterTest(true);
@@ -218,7 +218,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
/**
* Test get_submissions
*/
public function test_get_submissions () {
public function test_get_submissions() {
global $DB, $USER;
$this->resetAfterTest(true);
@@ -307,7 +307,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
/**
* Test get_user_flags
*/
public function test_get_user_flags () {
public function test_get_user_flags() {
global $DB, $USER;
$this->resetAfterTest(true);
@@ -378,7 +378,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
/**
* Test get_user_mappings
*/
public function test_get_user_mappings () {
public function test_get_user_mappings() {
global $DB, $USER;
$this->resetAfterTest(true);
@@ -436,4 +436,592 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
$this->assertEquals($student->id, $mapping['userid']);
}
/**
* Test lock_submissions
*/
public function test_lock_submissions() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id,
$course->id,
$studentrole->id);
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
// Create a student1 with an online text submission.
// Simulate a submission.
$this->setUser($student1);
$submission = $assign->get_user_submission($student1->id, true);
$data = new stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
'format'=>FORMAT_MOODLE);
$plugin = $assign->get_submission_plugin_by_type('onlinetext');
$plugin->save($submission, $data);
// Ready to test
$this->setUser($teacher);
$students = array($student1->id, $student2->id);
$result = mod_assign_external::lock_submissions($instance->id, $students);
// Check for 0 warnings.
$this->assertEquals(0, count($result));
$this->setUser($student2);
$submission = $assign->get_user_submission($student2->id, true);
$data = new stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
'format'=>FORMAT_MOODLE);
$notices = array();
$this->setExpectedException('moodle_exception');
$assign->save_submission($data, $notices);
}
/**
* Test unlock_submissions
*/
public function test_unlock_submissions() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id,
$course->id,
$studentrole->id);
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
// Create a student1 with an online text submission.
// Simulate a submission.
$this->setUser($student1);
$submission = $assign->get_user_submission($student1->id, true);
$data = new stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
'format'=>FORMAT_MOODLE);
$plugin = $assign->get_submission_plugin_by_type('onlinetext');
$plugin->save($submission, $data);
// Ready to test
$this->setUser($teacher);
$students = array($student1->id, $student2->id);
$result = mod_assign_external::lock_submissions($instance->id, $students);
// Check for 0 warnings.
$this->assertEquals(0, count($result));
$result = mod_assign_external::unlock_submissions($instance->id, $students);
// Check for 0 warnings.
$this->assertEquals(0, count($result));
$this->setUser($student2);
$submission = $assign->get_user_submission($student2->id, true);
$data = new stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
'format'=>FORMAT_MOODLE);
$notices = array();
$assign->save_submission($data, $notices);
}
/**
* Test submit_for_grading
*/
public function test_submit_for_grading() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
set_config('submissionreceipts', 0, 'assign');
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$params['submissiondrafts'] = 1;
$params['sendnotifications'] = 0;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
// Create a student1 with an online text submission.
// Simulate a submission.
$this->setUser($student1);
$submission = $assign->get_user_submission($student1->id, true);
$data = new stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
'format'=>FORMAT_MOODLE);
$plugin = $assign->get_submission_plugin_by_type('onlinetext');
$plugin->save($submission, $data);
$result = mod_assign_external::submit_for_grading($instance->id);
// Check for 0 warnings.
$this->assertEquals(0, count($result));
$submission = $assign->get_user_submission($student1->id, false);
$this->assertEquals(ASSIGN_SUBMISSION_STATUS_SUBMITTED, $submission->status);
}
/**
* Test save_user_extensions
*/
public function test_save_user_extensions() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
$this->setUser($teacher);
$now = time();
$yesterday = $now - 24*60*60;
$tomorrow = $now + 24*60*60;
set_config('submissionreceipts', 0, 'assign');
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['submissiondrafts'] = 1;
$params['sendnotifications'] = 0;
$params['duedate'] = $yesterday;
$params['cutoffdate'] = $now - 10;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->setUser($student1);
$result = mod_assign_external::submit_for_grading($instance->id);
// Check for 0 warnings.
$this->assertEquals(1, count($result));
$this->setUser($teacher);
$result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
$this->assertEquals(1, count($result));
$this->setUser($teacher);
$result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($yesterday - 10));
$this->assertEquals(1, count($result));
$this->setUser($teacher);
$result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($tomorrow));
$this->assertEquals(0, count($result));
$this->setUser($student1);
$result = mod_assign_external::submit_for_grading($instance->id);
$this->assertEquals(0, count($result));
$this->setUser($student1);
$result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
}
/**
* Test reveal_identities
*/
public function test_reveal_identities() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
$this->setUser($teacher);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['submissiondrafts'] = 1;
$params['sendnotifications'] = 0;
$params['blindmarking'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->setUser($student1);
$this->setExpectedException('required_capability_exception');
$result = mod_assign_external::reveal_identities($instance->id);
$this->assertEquals(1, count($result));
$this->assertEquals(true, $assign->is_blind_marking());
$this->setUser($teacher);
$result = mod_assign_external::reveal_identities($instance->id);
$this->assertEquals(0, count($result));
$this->assertEquals(false, $assign->is_blind_marking());
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['submissiondrafts'] = 1;
$params['sendnotifications'] = 0;
$params['blindmarking'] = 0;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$result = mod_assign_external::reveal_identities($instance->id);
$this->assertEquals(1, count($result));
$this->assertEquals(false, $assign->is_blind_marking());
}
/**
* Test revert_submissions_to_draft
*/
public function test_revert_submissions_to_draft() {
global $DB, $USER;
$this->resetAfterTest(true);
set_config('submissionreceipts', 0, 'assign');
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['sendnotifications'] = 0;
$params['submissiondrafts'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id,
$course->id,
$studentrole->id);
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
// Create a student1 with an online text submission.
// Simulate a submission.
$this->setUser($student1);
$result = mod_assign_external::submit_for_grading($instance->id);
$this->assertEquals(0, count($result));
// Ready to test
$this->setUser($teacher);
$students = array($student1->id, $student2->id);
$result = mod_assign_external::revert_submissions_to_draft($instance->id, array($student1->id));
// Check for 0 warnings.
$this->assertEquals(0, count($result));
}
/**
* Test save_submission
*/
public function test_save_submission() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
$this->setUser($teacher);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$params['assignsubmission_file_enabled'] = 1;
$params['assignsubmission_file_maxfiles'] = 5;
$params['assignsubmission_file_maxsizebytes'] = 1024*1024;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id,
$course->id,
$studentrole->id);
// Create a student1 with an online text submission.
// Simulate a submission.
$this->setUser($student1);
// Create a file in a draft area.
$draftidfile = file_get_unused_draft_itemid();
$usercontext = context_user::instance($student1->id);
$filerecord = array(
'contextid' => $usercontext->id,
'component' => 'user',
'filearea' => 'draft',
'itemid' => $draftidfile,
'filepath' => '/',
'filename' => 'testtext.txt',
);
$fs = get_file_storage();
$fs->create_file_from_string($filerecord, 'text contents');
// Create another file in a different draft area.
$draftidonlinetext = file_get_unused_draft_itemid();
$filerecord = array(
'contextid' => $usercontext->id,
'component' => 'user',
'filearea' => 'draft',
'itemid' => $draftidonlinetext,
'filepath' => '/',
'filename' => 'shouldbeanimage.txt',
);
$fs->create_file_from_string($filerecord, 'image contents (not really)');
// Now try a submission
$submissionpluginparams = array();
$submissionpluginparams['files_filemanager'] = $draftidfile;
$onlinetexteditorparams = array('text'=>'Yeeha!',
'format'=>1,
'itemid'=>$draftidonlinetext);
$submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
$result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
$this->assertEquals(0, count($result));
}
/**
* Test save_grade
*/
public function test_save_grade() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
$this->setUser($teacher);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['assignfeedback_file_enabled'] = 1;
$params['assignfeedback_comments_enabled'] = 1;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id,
$course->id,
$studentrole->id);
// Simulate a grade.
$this->setUser($teacher);
// Create a file in a draft area.
$draftidfile = file_get_unused_draft_itemid();
$usercontext = context_user::instance($teacher->id);
$filerecord = array(
'contextid' => $usercontext->id,
'component' => 'user',
'filearea' => 'draft',
'itemid' => $draftidfile,
'filepath' => '/',
'filename' => 'testtext.txt',
);
$fs = get_file_storage();
$fs->create_file_from_string($filerecord, 'text contents');
// Now try a grade
$feedbackpluginparams = array();
$feedbackpluginparams['files_filemanager'] = $draftidfile;
$feedbackeditorparams = array('text'=>'Yeeha!',
'format'=>1);
$feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
$result = mod_assign_external::save_grade($instance->id, $student1->id, 50.0, -1, true, 'released', false, $feedbackpluginparams);
// No warnings.
$this->assertEquals(0, count($result));
$result = mod_assign_external::get_grades(array($instance->id));
$this->assertEquals($result['assignments'][0]['grades'][0]['grade'], '50.0');
}
/**
* Test copy_previous_attempt
*/
public function test_copy_previous_attempt() {
global $DB, $USER;
$this->resetAfterTest(true);
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course();
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$teacherrole->id);
$this->setUser($teacher);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params['course'] = $course->id;
$params['assignsubmission_onlinetext_enabled'] = 1;
$params['assignsubmission_file_enabled'] = 0;
$params['assignfeedback_file_enabled'] = 0;
$params['attemptreopenmethod'] = 'manual';
$params['maxattempts'] = 5;
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->getDataGenerator()->enrol_user($student1->id,
$course->id,
$studentrole->id);
// Now try a submission
$this->setUser($student1);
$draftidonlinetext = file_get_unused_draft_itemid();
$submissionpluginparams = array();
$onlinetexteditorparams = array('text'=>'Yeeha!',
'format'=>1,
'itemid'=>$draftidonlinetext);
$submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
$submissionpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
$result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
$this->setUser($teacher);
// Add a grade and reopen the attempt.
// Now try a grade
$feedbackpluginparams = array();
$feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
$feedbackeditorparams = array('text'=>'Yeeha!',
'format'=>1);
$feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
$result = mod_assign_external::save_grade($instance->id, $student1->id, 50.0, -1, true, 'released', false, $feedbackpluginparams);
$this->setUser($student1);
// Now copy the previous attempt.
$result = mod_assign_external::copy_previous_attempt($instance->id);
// No warnings.
$this->assertEquals(0, count($result));
$this->setUser($teacher);
$result = mod_assign_external::get_submissions(array($instance->id));
// Check we are now on the second attempt.
$this->assertEquals($result['assignments'][0]['submissions'][0]['attemptnumber'], 1);
// Check the plugins data is not empty.
$this->assertNotEmpty($result['assignments'][0]['submissions'][0]['plugins']);
}
}
+14 -9
View File
@@ -83,26 +83,31 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
// Test students cannot reveal identities.
$nopermission = false;
$this->students[0]->ignoresesskey = true;
$this->setUser($this->students[0]);
$this->setExpectedException('required_capability_exception');
$assign->testable_process_reveal_identities();
$assign->reveal_identities();
$this->students[0]->ignoresesskey = false;
// Test teachers cannot reveal identities.
$nopermission = false;
$this->teachers[0]->ignoresesskey = true;
$this->setUser($this->teachers[0]);
$this->setExpectedException('required_capability_exception');
$assign->testable_process_reveal_identities();
$assign->reveal_identities();
$this->teachers[0]->ignoresesskey = false;
// Test sesskey is required.
$this->setUser($this->editingteachers[0]);
$this->setExpectedException('moodle_exception');
$assign->testable_process_reveal_identities();
$assign->reveal_identities();
// Test editingteacher can reveal identities if sesskey is ignored.
$this->editingteachers[0]->ignoresesskey = true;
$this->setUser($this->editingteachers[0]);
$assign->testable_process_reveal_identities();
$assign->reveal_identities();
$this->assertEquals(false, $assign->is_blind_marking());
$this->editingteachers[0]->ignoresesskey = false;
// Test student names are visible.
$gradingtable = new assign_grading_table($assign, 1, '', 0, true);
@@ -1016,7 +1021,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$assign = $this->create_instance();
$sink = $this->redirectEvents();
$assign->testable_process_lock($this->students[0]->id);
$assign->lock_submission($this->students[0]->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
@@ -1049,7 +1054,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$assign = $this->create_instance(array('blindmarking'=>1));
$sink = $this->redirectEvents();
$assign->testable_process_reveal_identities();
$assign->reveal_identities();
$events = $sink->get_events();
$this->assertCount(1, $events);
@@ -1083,7 +1088,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$assign->testable_update_submission($submission, $this->students[0]->id, true, false);
$sink = $this->redirectEvents();
$assign->testable_process_revert_to_draft($this->students[0]->id);
$assign->revert_to_draft($this->students[0]->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
@@ -1191,7 +1196,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$sink = $this->redirectEvents();
$notices = null;
$assign->testable_process_copy_previous_attempt($notices);
$assign->copy_previous_attempt($notices);
$events = $sink->get_events();
$this->assertCount(1, $events);
@@ -1221,7 +1226,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$assign = $this->create_instance();
$sink = $this->redirectEvents();
$assign->testable_process_unlock($this->students[0]->id);
$assign->unlock_submission($this->students[0]->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
+5
View File
@@ -3,6 +3,11 @@ This files describes API changes in the assign code.
=== 2.6 ===
* To see submission/grades of inactive users, user should have moodle/course:viewsuspendedusers capability.
* count_* functions will return only active participants.
* assign_submission_plugin->lock and unlock methods have an additional parameter for user flags. A user will not
always have a submission record when the submission is locked/unlocked.
* Submission and feedback plugins can now participate in webservices. The plugin must implement get_external_parameters()
to describe the parameters it is expecting from the mod_assign_save_grade or mod_assign_save_submission functions. The
plugin will then handle the webservice via it's normal save() method with the extra data supplied in the $data argument.
=== 2.5 ===
+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 = 2013070902; // The current module version (Date: YYYYMMDDXX).
$module->version = 2013080800; // The current module version (Date: YYYYMMDDXX).
$module->requires = 2013050100; // Requires this Moodle version.
$module->cron = 60;