'capabilities' => 'mod/assign:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
),
+
+ 'mod_assign_get_submission_status' => array(
+ 'classname' => 'mod_assign_external',
+ 'methodname' => 'get_submission_status',
+ 'classpath' => 'mod/assign/externallib.php',
+ 'description' => 'Returns information about an assignment submission status for a given user.',
+ 'type' => 'read',
+ 'capabilities' => 'mod/assign:view',
+ 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
+ ),
);
defined('MOODLE_INTERNAL') || die;
require_once("$CFG->libdir/externallib.php");
+require_once("$CFG->dirroot/mod/assign/locallib.php");
/**
* Assign functions
return $result;
}
+ /**
+ * Creates a grade single structure.
+ *
+ * @return external_single_structure a grade single structure.
+ * @since Moodle 3.1
+ */
+ private static function get_grade_structure($required = VALUE_REQUIRED) {
+ return new external_single_structure(
+ array(
+ 'id' => new external_value(PARAM_INT, 'grade id'),
+ 'assignment' => new external_value(PARAM_INT, 'assignment id', VALUE_OPTIONAL),
+ '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'),
+ 'grade' => new external_value(PARAM_TEXT, 'grade'),
+ 'gradefordisplay' => new external_value(PARAM_RAW, 'grade rendered into a format suitable for display',
+ VALUE_OPTIONAL),
+ ), 'grade information', $required
+ );
+ }
+
/**
* Creates an assign_grades external_single_structure
* @return external_single_structure
private static function assign_grades() {
return new external_single_structure(
array (
- 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
- 'grades' => new external_multiple_structure(new external_single_structure(
- 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'),
- 'grade' => new external_value(PARAM_TEXT, 'grade')
- )
- )
- )
+ 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
+ 'grades' => new external_multiple_structure(self::get_grade_structure())
)
);
}
*/
public static function get_assignments($courseids = array(), $capabilities = array(), $includenotenrolledcourses = false) {
global $USER, $DB, $CFG;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(
self::get_assignments_parameters(),
);
}
+ /**
+ * Return information (files and text fields) for the given plugins in the assignment.
+ *
+ * @param assign $assign the assignment object
+ * @param array $assignplugins array of assignment plugins (submission or feedback)
+ * @param stdClass $item the item object (submission or grade)
+ * @return array an array containing the plugins returned information
+ */
+ private static function get_plugins_data($assign, $assignplugins, $item) {
+ global $CFG;
+
+ $plugins = array();
+ $fs = get_file_storage();
+
+ foreach ($assignplugins as $assignplugin) {
+
+ if (!$assignplugin->is_enabled() or !$assignplugin->is_visible()) {
+ continue;
+ }
+
+ $plugin = array(
+ 'name' => $assignplugin->get_name(),
+ 'type' => $assignplugin->get_type()
+ );
+ // Subtype is 'assignsubmission', type is currently 'file' or 'onlinetext'.
+ $component = $assignplugin->get_subtype().'_'.$assignplugin->get_type();
+
+ $fileareas = $assignplugin->get_file_areas();
+ foreach ($fileareas as $filearea => $name) {
+ $fileareainfo = array('area' => $filearea);
+ $files = $fs->get_area_files(
+ $assign->get_context()->id,
+ $component,
+ $filearea,
+ $item->id,
+ "timemodified",
+ false
+ );
+ foreach ($files as $file) {
+ $filepath = $file->get_filepath().$file->get_filename();
+ $fileurl = file_encode_url($CFG->wwwroot . '/webservice/pluginfile.php', '/' . $assign->get_context()->id .
+ '/' . $component. '/'. $filearea . '/' . $item->id . $filepath);
+ $fileinfo = array(
+ 'filepath' => $filepath,
+ 'fileurl' => $fileurl
+ );
+ $fileareainfo['files'][] = $fileinfo;
+ }
+ $plugin['fileareas'][] = $fileareainfo;
+ }
+
+ $editorfields = $assignplugin->get_editor_fields();
+ foreach ($editorfields as $name => $description) {
+ $editorfieldinfo = array(
+ 'name' => $name,
+ 'description' => $description,
+ 'text' => $assignplugin->get_editor_text($name, $item->id),
+ 'format' => $assignplugin->get_editor_format($name, $item->id)
+ );
+ $plugin['editorfields'][] = $editorfieldinfo;
+ }
+ $plugins[] = $plugin;
+ }
+ return $plugins;
+ }
+
/**
* Describes the parameters for get_submissions
*
*/
public static function get_submissions($assignmentids, $status = '', $since = 0, $before = 0) {
global $DB, $CFG;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
+
$params = self::validate_parameters(self::get_submissions_parameters(),
array('assignmentids' => $assignmentids,
'status' => $status,
foreach ($assigns as $assign) {
$submissions = array();
- $submissionplugins = $assign->get_submission_plugins();
$placeholders = array('assignid1' => $assign->get_instance()->id,
'assignid2' => $assign->get_instance()->id);
$submissionrecords = $DB->get_records_sql($sql, $placeholders);
if (!empty($submissionrecords)) {
- $fs = get_file_storage();
+ $submissionplugins = $assign->get_submission_plugins();
foreach ($submissionrecords as $submissionrecord) {
$submission = array(
'id' => $submissionrecord->id,
'timemodified' => $submissionrecord->timemodified,
'status' => $submissionrecord->status,
'attemptnumber' => $submissionrecord->attemptnumber,
- 'groupid' => $submissionrecord->groupid
+ 'groupid' => $submissionrecord->groupid,
+ 'plugins' => self::get_plugins_data($assign, $submissionplugins, $submissionrecord)
);
- foreach ($submissionplugins as $submissionplugin) {
- $plugin = array(
- 'name' => $submissionplugin->get_name(),
- 'type' => $submissionplugin->get_type()
- );
- // Subtype is 'assignsubmission', type is currently 'file' or 'onlinetext'.
- $component = $submissionplugin->get_subtype().'_'.$submissionplugin->get_type();
-
- $fileareas = $submissionplugin->get_file_areas();
- foreach ($fileareas as $filearea => $name) {
- $fileareainfo = array('area' => $filearea);
- $files = $fs->get_area_files(
- $assign->get_context()->id,
- $component,
- $filearea,
- $submissionrecord->id,
- "timemodified",
- false
- );
- foreach ($files as $file) {
- $filepath = $file->get_filepath().$file->get_filename();
- $fileurl = file_encode_url($CFG->wwwroot . '/webservice/pluginfile.php', '/' . $assign->get_context()->id .
- '/' . $component. '/'. $filearea . '/' . $submissionrecord->id . $filepath);
- $fileinfo = array(
- 'filepath' => $filepath,
- 'fileurl' => $fileurl
- );
- $fileareainfo['files'][] = $fileinfo;
- }
- $plugin['fileareas'][] = $fileareainfo;
- }
-
- $editorfields = $submissionplugin->get_editor_fields();
- foreach ($editorfields as $name => $description) {
- $editorfieldinfo = array(
- 'name' => $name,
- 'description' => $description,
- 'text' => $submissionplugin->get_editor_text($name, $submissionrecord->id),
- 'format' => $submissionplugin->get_editor_format($name, $submissionrecord->id)
- );
- $plugin['editorfields'][] = $editorfieldinfo;
- }
-
- $submission['plugins'][] = $plugin;
- }
$submissions[] = $submission;
}
} else {
}
/**
- * Creates an assign_submissions external_single_structure
+ * Creates an assignment plugin structure.
*
- * @return external_single_structure
- * @since Moodle 2.5
+ * @return external_single_structure the plugin structure
*/
- private static function get_submissions_structure() {
+ private static function get_plugin_structure() {
return new external_single_structure(
- array (
- 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
- 'submissions' => new external_multiple_structure(
+ array(
+ 'type' => new external_value(PARAM_TEXT, 'submission plugin type'),
+ 'name' => new external_value(PARAM_TEXT, 'submission plugin name'),
+ 'fileareas' => new external_multiple_structure(
new external_single_structure(
- 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'),
- 'groupid' => new external_value(PARAM_INT, 'group id'),
- 'plugins' => new external_multiple_structure(
+ array (
+ 'area' => new external_value (PARAM_TEXT, 'file area'),
+ 'files' => new external_multiple_structure(
new external_single_structure(
- array(
- 'type' => new external_value(PARAM_TEXT, 'submission plugin type'),
- 'name' => new external_value(PARAM_TEXT, 'submission plugin name'),
- 'fileareas' => new external_multiple_structure(
- new external_single_structure(
- array (
- 'area' => new external_value (PARAM_TEXT, 'file area'),
- 'files' => new external_multiple_structure(
- new external_single_structure(
- array (
- 'filepath' => new external_value (PARAM_TEXT, 'file path'),
- 'fileurl' => new external_value (PARAM_URL, 'file download url',
- VALUE_OPTIONAL)
- )
- ), 'files', VALUE_OPTIONAL
- )
- )
- ), 'fileareas', VALUE_OPTIONAL
- ),
- 'editorfields' => new external_multiple_structure(
- new external_single_structure(
- array(
- 'name' => new external_value(PARAM_TEXT, 'field name'),
- 'description' => new external_value(PARAM_TEXT, 'field description'),
- 'text' => new external_value (PARAM_RAW, 'field value'),
- 'format' => new external_format_value ('text')
- )
- )
- , 'editorfields', VALUE_OPTIONAL
- )
+ array (
+ 'filepath' => new external_value (PARAM_TEXT, 'file path'),
+ 'fileurl' => new external_value (PARAM_URL, 'file download url',
+ VALUE_OPTIONAL)
)
- )
- , 'plugins', VALUE_OPTIONAL
+ ), 'files', VALUE_OPTIONAL
)
)
+ ), 'fileareas', VALUE_OPTIONAL
+ ),
+ 'editorfields' => new external_multiple_structure(
+ new external_single_structure(
+ array(
+ 'name' => new external_value(PARAM_TEXT, 'field name'),
+ 'description' => new external_value(PARAM_TEXT, 'field description'),
+ 'text' => new external_value (PARAM_RAW, 'field value'),
+ 'format' => new external_format_value ('text')
+ )
)
+ , 'editorfields', VALUE_OPTIONAL
)
)
);
}
+ /**
+ * Creates a submission structure.
+ *
+ * @return external_single_structure the submission structure
+ */
+ private static function get_submission_structure($required = VALUE_REQUIRED) {
+ return new external_single_structure(
+ 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'),
+ 'groupid' => new external_value(PARAM_INT, 'group id'),
+ 'assignment' => new external_value(PARAM_INT, 'assignment id', VALUE_OPTIONAL),
+ 'latest' => new external_value(PARAM_INT, 'latest attempt', VALUE_OPTIONAL),
+ 'plugins' => new external_multiple_structure(self::get_plugin_structure(), 'plugins', VALUE_OPTIONAL)
+ ), 'submission info', $required
+ );
+ }
+
+ /**
+ * Creates an assign_submissions external_single_structure
+ *
+ * @return external_single_structure
+ * @since Moodle 2.5
+ */
+ private static function get_submissions_structure() {
+ return new external_single_structure(
+ array (
+ 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
+ 'submissions' => new external_multiple_structure(self::get_submission_structure())
+ )
+ );
+ }
+
/**
* Describes the get_submissions return value
*
*/
public static function set_user_flags($assignmentid, $userflags = array()) {
global $CFG, $DB;
- require_once($CFG->dirroot . "/mod/assign/locallib.php");
$params = self::validate_parameters(self::set_user_flags_parameters(),
array('assignmentid' => $assignmentid,
*/
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,
*/
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,
*/
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,
*/
public static function submit_for_grading($assignmentid, $acceptsubmissionstatement) {
global $CFG, $USER;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::submit_for_grading_parameters(),
array('assignmentid' => $assignmentid,
*/
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,
*/
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));
*/
public static function save_submission_parameters() {
global $CFG;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
$instance = new assign(null, null, null);
$pluginsubmissionparams = array();
*/
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,
*/
public static function save_grade_parameters() {
global $CFG;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
require_once("$CFG->dirroot/grade/grading/lib.php");
$instance = new assign(null, null, null);
$pluginfeedbackparams = array();
$plugindata = array(),
$advancedgradingdata = array()) {
global $CFG, $USER;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::save_grade_parameters(),
array('assignmentid' => $assignmentid,
*/
public static function save_grades_parameters() {
global $CFG;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
require_once("$CFG->dirroot/grade/grading/lib.php");
$instance = new assign(null, null, null);
$pluginfeedbackparams = array();
*/
public static function save_grades($assignmentid, $applytoall = false, $grades) {
global $CFG, $USER;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
$params = self::validate_parameters(self::save_grades_parameters(),
array('assignmentid' => $assignmentid,
*/
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));
*/
public static function view_grading_table($assignid) {
global $DB, $CFG;
- require_once($CFG->dirroot . "/mod/assign/locallib.php");
$params = self::validate_parameters(self::view_grading_table_parameters(),
array(
*/
public static function view_submission_status($assignid) {
global $DB, $CFG;
- require_once("$CFG->dirroot/mod/assign/locallib.php");
$warnings = array();
$params = array(
);
}
+ /**
+ * Describes the parameters for get_submission_status.
+ *
+ * @return external_external_function_parameters
+ * @since Moodle 3.1
+ */
+ public static function get_submission_status_parameters() {
+ return new external_function_parameters (
+ array(
+ 'assignid' => new external_value(PARAM_INT, 'assignment instance id'),
+ 'userid' => new external_value(PARAM_INT, 'user id (empty for current user)', VALUE_DEFAULT, 0),
+ )
+ );
+ }
+
+ /**
+ * Returns information about an assignment submission status for a given user.
+ *
+ * @param int $assignid assignment instance id
+ * @param int $userid user id (empty for current user)
+ * @return array of warnings and grading, status, feedback and previous attempts information
+ * @since Moodle 3.1
+ * @throws required_capability_exception
+ */
+ public static function get_submission_status($assignid, $userid = 0) {
+ global $USER, $DB;
+
+ $warnings = array();
+
+ $params = array(
+ 'assignid' => $assignid,
+ 'userid' => $userid,
+ );
+ $params = self::validate_parameters(self::get_submission_status_parameters(), $params);
+
+ // Request and permission validation.
+ $assign = $DB->get_record('assign', array('id' => $params['assignid']), 'id', MUST_EXIST);
+ list($course, $cm) = get_course_and_cm_from_instance($assign, 'assign');
+
+ $context = context_module::instance($cm->id);
+ self::validate_context($context);
+
+ $assign = new assign($context, $cm, $course);
+
+ // Default value for userid.
+ if (empty($params['userid'])) {
+ $params['userid'] = $USER->id;
+ }
+ $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
+ core_user::require_active_user($user);
+
+ if (!$assign->can_view_submission($user->id)) {
+ throw new required_capability_exception($context, 'mod/assign:viewgrades', 'nopermission', '');
+ }
+
+ $gradingsummary = $lastattempt = $feedback = $previousattempts = null;
+
+ // Get the renderable since it contais all the info we need.
+ if ($assign->can_view_grades()) {
+ $gradingsummary = $assign->get_assign_grading_summary_renderable();
+ }
+
+ // Retrieve the rest of the renderable objects.
+ if (has_capability('mod/assign:submit', $assign->get_context(), $user)) {
+ $lastattempt = $assign->get_assign_submission_status_renderable($user, true);
+ }
+
+ $feedback = $assign->get_assign_feedback_status_renderable($user);
+
+ $previousattempts = $assign->get_assign_attempt_history_renderable($user);
+
+ // Now, build the result.
+ $result = array();
+
+ // First of all, grading summary, this is suitable for teachers/managers.
+ if ($gradingsummary) {
+ $result['gradingsummary'] = $gradingsummary;
+ }
+
+ // Did we submit anything?
+ if ($lastattempt) {
+ $submissionplugins = $assign->get_submission_plugins();
+
+ if (empty($lastattempt->submission)) {
+ unset($lastattempt->submission);
+ } else {
+ $lastattempt->submission->plugins = self::get_plugins_data($assign, $submissionplugins, $lastattempt->submission);
+ }
+
+ if (empty($lastattempt->teamsubmission)) {
+ unset($lastattempt->teamsubmission);
+ } else {
+ $lastattempt->teamsubmission->plugins = self::get_plugins_data($assign, $submissionplugins,
+ $lastattempt->teamsubmission);
+ }
+
+ // We need to change the type of some of the structures retrieved from the renderable.
+ if (!empty($lastattempt->submissiongroup)) {
+ $lastattempt->submissiongroup = $lastattempt->submissiongroup->id;
+ }
+ if (!empty($lastattempt->usergroups)) {
+ $lastattempt->usergroups = array_keys($lastattempt->usergroups);
+ }
+ // We cannot use array_keys here.
+ if (!empty($lastattempt->submissiongroupmemberswhoneedtosubmit)) {
+ $lastattempt->submissiongroupmemberswhoneedtosubmit = array_map(
+ function($e){
+ return $e->id;
+ },
+ $lastattempt->submissiongroupmemberswhoneedtosubmit);
+ }
+
+ $result['lastattempt'] = $lastattempt;
+ }
+
+ // The feedback for our latest submission.
+ if ($feedback) {
+ if ($feedback->grade) {
+ $feedbackplugins = $assign->get_feedback_plugins();
+ $feedback->plugins = self::get_plugins_data($assign, $feedbackplugins, $feedback->grade);
+ } else {
+ unset($feedback->plugins);
+ unset($feedback->grade);
+ }
+
+ $result['feedback'] = $feedback;
+ }
+
+ // Retrieve only previous attempts.
+ if ($previousattempts and count($previousattempts->submissions) > 1) {
+ // Don't show the last one because it is the current submission.
+ array_pop($previousattempts->submissions);
+
+ // Show newest to oldest.
+ $previousattempts->submissions = array_reverse($previousattempts->submissions);
+
+ foreach ($previousattempts->submissions as $i => $submission) {
+ $attempt = array();
+
+ $grade = null;
+ foreach ($previousattempts->grades as $onegrade) {
+ if ($onegrade->attemptnumber == $submission->attemptnumber) {
+ $grade = $onegrade;
+ break;
+ }
+ }
+
+ $attempt['attemptnumber'] = $submission->attemptnumber;
+
+ if ($submission) {
+ $submission->plugins = self::get_plugins_data($assign, $previousattempts->submissionplugins, $submission);
+ $attempt['submission'] = $submission;
+ }
+
+ if ($grade) {
+ // From object to id.
+ $grade->grader = $grade->grader->id;
+ $feedbackplugins = self::get_plugins_data($assign, $previousattempts->feedbackplugins, $grade);
+
+ $attempt['grade'] = $grade;
+ $attempt['feedbackplugins'] = $feedbackplugins;
+ }
+ $result['previousattempts'][] = $attempt;
+ }
+ }
+
+ $result['warnings'] = $warnings;
+ return $result;
+ }
+
+ /**
+ * Describes the get_submission_status return value.
+ *
+ * @return external_single_structure
+ * @since Moodle 3.1
+ */
+ public static function get_submission_status_returns() {
+ return new external_single_structure(
+ array(
+ 'gradingsummary' => new external_single_structure(
+ array(
+ 'participantcount' => new external_value(PARAM_INT, 'Number of users who can submit.'),
+ 'submissiondraftscount' => new external_value(PARAM_INT, 'Number of submissions in draft status.'),
+ 'submissiondraftscount' => new external_value(PARAM_INT, 'Number of submissions in draft status.'),
+ 'submissionsenabled' => new external_value(PARAM_BOOL, 'Whether submissions are enabled or not.'),
+ 'submissionssubmittedcount' => new external_value(PARAM_INT, 'Number of submissions in submitted status.'),
+ 'submissionsneedgradingcount' => new external_value(PARAM_INT, 'Number of submissions that need grading.'),
+ 'warnofungroupedusers' => new external_value(PARAM_BOOL, 'Whether we need to warn people that there
+ are users without groups.'),
+ ), 'Grading information.', VALUE_OPTIONAL
+ ),
+ 'lastattempt' => new external_single_structure(
+ array(
+ 'submission' => self::get_submission_structure(VALUE_OPTIONAL),
+ 'teamsubmission' => self::get_submission_structure(VALUE_OPTIONAL),
+ 'submissiongroup' => new external_value(PARAM_INT, 'The submission group id (for group submissions only).',
+ VALUE_OPTIONAL),
+ 'submissiongroupmemberswhoneedtosubmit' => new external_multiple_structure(
+ new external_value(PARAM_INT, 'USER id.'),
+ 'List of users who still need to submit (for group submissions only).',
+ VALUE_OPTIONAL
+ ),
+ 'submissionsenabled' => new external_value(PARAM_BOOL, 'Whether submissions are enabled or not.'),
+ 'locked' => new external_value(PARAM_BOOL, 'Whether new submissions are locked.'),
+ 'graded' => new external_value(PARAM_BOOL, 'Whether the submission is graded.'),
+ 'canedit' => new external_value(PARAM_BOOL, 'Whether the user can edit the current submission.'),
+ 'cansubmit' => new external_value(PARAM_BOOL, 'Whether the user can submit.'),
+ 'extensionduedate' => new external_value(PARAM_INT, 'Extension due date.'),
+ 'blindmarking' => new external_value(PARAM_BOOL, 'Whether blind marking is enabled.'),
+ 'gradingstatus' => new external_value(PARAM_ALPHANUMEXT, 'Grading status.'),
+ 'usergroups' => new external_multiple_structure(
+ new external_value(PARAM_INT, 'Group id.'), 'User groups in the course.'
+ ),
+ ), 'Last attempt information.', VALUE_OPTIONAL
+ ),
+ 'feedback' => new external_single_structure(
+ array(
+ 'grade' => self::get_grade_structure(VALUE_OPTIONAL),
+ 'gradefordisplay' => new external_value(PARAM_RAW, 'Grade rendered into a format suitable for display.'),
+ 'gradeddate' => new external_value(PARAM_INT, 'The date the user was graded.'),
+ 'plugins' => new external_multiple_structure(self::get_plugin_structure(), 'Plugins info.', VALUE_OPTIONAL),
+ ), 'Feedback for the last attempt.', VALUE_OPTIONAL
+ ),
+ 'previousattempts' => new external_multiple_structure(
+ new external_single_structure(
+ array(
+ 'attemptnumber' => new external_value(PARAM_INT, 'Attempt number.'),
+ 'submission' => self::get_submission_structure(VALUE_OPTIONAL),
+ 'grade' => self::get_grade_structure(VALUE_OPTIONAL),
+ 'feedbackplugins' => new external_multiple_structure(self::get_plugin_structure(), 'Feedback info.',
+ VALUE_OPTIONAL),
+ )
+ ), 'List all the previous attempts did by the user.', VALUE_OPTIONAL
+ ),
+ 'warnings' => new external_warnings(),
+ )
+ );
+ }
+
}
public function is_configurable() {
return false;
}
+
+ /**
+ * Get file areas returns a list of areas this plugin stores files.
+ *
+ * @return array - An array of fileareas (keys) and descriptions (values)
+ */
+ public function get_file_areas() {
+ return array(document_services::FINAL_PDF_FILEAREA => $this->get_name());
+ }
}
public function get_return_action() {
global $PAGE;
- $params = $PAGE->url->params();
+ // Web services don't set a URL, we should avoid debugging when ussing the url object.
+ if (!WS_SERVER) {
+ $params = $PAGE->url->params();
+ }
if (!empty($params['action'])) {
return $params['action'];
}
/**
- * Print 2 tables of information with no action links -
- * the submission summary and the grading summary.
+ * Creates an assign_submission_status renderable.
*
- * @param stdClass $user the user to print the report for
- * @param bool $showlinks - Return plain text or links to the profile
- * @return string - the html summary
+ * @param stdClass $user the user to get the report for
+ * @param bool $showlinks return plain text or links to the profile
+ * @return assign_submission_status renderable object
*/
- public function view_student_summary($user, $showlinks) {
- global $CFG, $DB, $PAGE;
+ public function get_assign_submission_status_renderable($user, $showlinks) {
+ global $PAGE;
$instance = $this->get_instance();
- $grade = $this->get_user_grade($user->id, false);
$flags = $this->get_user_flags($user->id, false);
$submission = $this->get_user_submission($user->id, false);
- $o = '';
$teamsubmission = null;
$submissiongroup = null;
$notsubmitted = $this->get_submission_group_members_who_have_not_submitted($groupid, false);
}
- if ($this->can_view_submission($user->id)) {
- $showedit = $showlinks &&
- ($this->is_any_submission_plugin_enabled()) &&
- $this->can_edit_submission($user->id);
-
- $gradelocked = ($flags && $flags->locked) || $this->grading_disabled($user->id, false);
-
- // Grading criteria preview.
- $gradingmanager = get_grading_manager($this->context, 'mod_assign', 'submissions');
- $gradingcontrollerpreview = '';
- if ($gradingmethod = $gradingmanager->get_active_method()) {
- $controller = $gradingmanager->get_controller($gradingmethod);
- if ($controller->is_form_defined()) {
- $gradingcontrollerpreview = $controller->render_preview($PAGE);
- }
- }
+ $showedit = $showlinks &&
+ ($this->is_any_submission_plugin_enabled()) &&
+ $this->can_edit_submission($user->id);
- $showsubmit = ($showlinks && $this->submissions_open($user->id));
- $showsubmit = ($showsubmit && $this->show_submit_button($submission, $teamsubmission, $user->id));
+ $gradelocked = ($flags && $flags->locked) || $this->grading_disabled($user->id, false);
- $extensionduedate = null;
- if ($flags) {
- $extensionduedate = $flags->extensionduedate;
+ // Grading criteria preview.
+ $gradingmanager = get_grading_manager($this->context, 'mod_assign', 'submissions');
+ $gradingcontrollerpreview = '';
+ if ($gradingmethod = $gradingmanager->get_active_method()) {
+ $controller = $gradingmanager->get_controller($gradingmethod);
+ if ($controller->is_form_defined()) {
+ $gradingcontrollerpreview = $controller->render_preview($PAGE);
}
- $viewfullnames = has_capability('moodle/site:viewfullnames', $this->get_course_context());
+ }
- $gradingstatus = $this->get_grading_status($user->id);
- $usergroups = $this->get_all_groups($user->id);
- $submissionstatus = new assign_submission_status($instance->allowsubmissionsfromdate,
- $instance->alwaysshowdescription,
- $submission,
- $instance->teamsubmission,
- $teamsubmission,
- $submissiongroup,
- $notsubmitted,
- $this->is_any_submission_plugin_enabled(),
- $gradelocked,
- $this->is_graded($user->id),
- $instance->duedate,
- $instance->cutoffdate,
- $this->get_submission_plugins(),
- $this->get_return_action(),
- $this->get_return_params(),
- $this->get_course_module()->id,
- $this->get_course()->id,
- assign_submission_status::STUDENT_VIEW,
- $showedit,
- $showsubmit,
- $viewfullnames,
- $extensionduedate,
- $this->get_context(),
- $this->is_blind_marking(),
- $gradingcontrollerpreview,
- $instance->attemptreopenmethod,
- $instance->maxattempts,
- $gradingstatus,
- $instance->preventsubmissionnotingroup,
- $usergroups);
- if (has_capability('mod/assign:submit', $this->get_context(), $user)) {
- $o .= $this->get_renderer()->render($submissionstatus);
- }
+ $showsubmit = ($showlinks && $this->submissions_open($user->id));
+ $showsubmit = ($showsubmit && $this->show_submit_button($submission, $teamsubmission, $user->id));
- require_once($CFG->libdir.'/gradelib.php');
- require_once($CFG->dirroot.'/grade/grading/lib.php');
+ $extensionduedate = null;
+ if ($flags) {
+ $extensionduedate = $flags->extensionduedate;
+ }
+ $viewfullnames = has_capability('moodle/site:viewfullnames', $this->get_course_context());
+
+ $gradingstatus = $this->get_grading_status($user->id);
+ $usergroups = $this->get_all_groups($user->id);
+ $submissionstatus = new assign_submission_status($instance->allowsubmissionsfromdate,
+ $instance->alwaysshowdescription,
+ $submission,
+ $instance->teamsubmission,
+ $teamsubmission,
+ $submissiongroup,
+ $notsubmitted,
+ $this->is_any_submission_plugin_enabled(),
+ $gradelocked,
+ $this->is_graded($user->id),
+ $instance->duedate,
+ $instance->cutoffdate,
+ $this->get_submission_plugins(),
+ $this->get_return_action(),
+ $this->get_return_params(),
+ $this->get_course_module()->id,
+ $this->get_course()->id,
+ assign_submission_status::STUDENT_VIEW,
+ $showedit,
+ $showsubmit,
+ $viewfullnames,
+ $extensionduedate,
+ $this->get_context(),
+ $this->is_blind_marking(),
+ $gradingcontrollerpreview,
+ $instance->attemptreopenmethod,
+ $instance->maxattempts,
+ $gradingstatus,
+ $instance->preventsubmissionnotingroup,
+ $usergroups);
+ return $submissionstatus;
+ }
+
+
+ /**
+ * Creates an assign_feedback_status renderable.
+ *
+ * @param stdClass $user the user to get the report for
+ * @return assign_feedback_status renderable object
+ */
+ public function get_assign_feedback_status_renderable($user) {
+ global $CFG, $DB, $PAGE;
- $gradinginfo = grade_get_grades($this->get_course()->id,
- 'mod',
- 'assign',
- $instance->id,
- $user->id);
-
- $gradingitem = null;
- $gradebookgrade = null;
- if (isset($gradinginfo->items[0])) {
- $gradingitem = $gradinginfo->items[0];
- $gradebookgrade = $gradingitem->grades[$user->id];
- }
-
- // Check to see if all feedback plugins are empty.
- $emptyplugins = true;
- if ($grade) {
- foreach ($this->get_feedback_plugins() as $plugin) {
- if ($plugin->is_visible() && $plugin->is_enabled()) {
- if (!$plugin->is_empty($grade)) {
- $emptyplugins = false;
- }
+ require_once($CFG->libdir.'/gradelib.php');
+ require_once($CFG->dirroot.'/grade/grading/lib.php');
+
+ $instance = $this->get_instance();
+ $grade = $this->get_user_grade($user->id, false);
+ $gradingstatus = $this->get_grading_status($user->id);
+
+ $gradinginfo = grade_get_grades($this->get_course()->id,
+ 'mod',
+ 'assign',
+ $instance->id,
+ $user->id);
+
+ $gradingitem = null;
+ $gradebookgrade = null;
+ if (isset($gradinginfo->items[0])) {
+ $gradingitem = $gradinginfo->items[0];
+ $gradebookgrade = $gradingitem->grades[$user->id];
+ }
+
+ // Check to see if all feedback plugins are empty.
+ $emptyplugins = true;
+ if ($grade) {
+ foreach ($this->get_feedback_plugins() as $plugin) {
+ if ($plugin->is_visible() && $plugin->is_enabled()) {
+ if (!$plugin->is_empty($grade)) {
+ $emptyplugins = false;
}
}
}
+ }
+
+ if ($this->get_instance()->markingworkflow && $gradingstatus != ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
+ $emptyplugins = true; // Don't show feedback plugins until released either.
+ }
- if ($this->get_instance()->markingworkflow && $gradingstatus != ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
- $emptyplugins = true; // Don't show feedback plugins until released either.
+ $cangrade = has_capability('mod/assign:grade', $this->get_context());
+ // If there is a visible grade, show the summary.
+ if ((!is_null($gradebookgrade->grade) || !$emptyplugins)
+ && ($cangrade || !$gradebookgrade->hidden)) {
+
+ $gradefordisplay = null;
+ $gradeddate = null;
+ $grader = null;
+ $gradingmanager = get_grading_manager($this->get_context(), 'mod_assign', 'submissions');
+
+ // Only show the grade if it is not hidden in gradebook.
+ if (!is_null($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden)) {
+ if ($controller = $gradingmanager->get_active_controller()) {
+ $menu = make_grades_menu($this->get_instance()->grade);
+ $controller->set_grade_range($menu, $this->get_instance()->grade > 0);
+ $gradefordisplay = $controller->render_grade($PAGE,
+ $grade->id,
+ $gradingitem,
+ $gradebookgrade->str_long_grade,
+ $cangrade);
+ } else {
+ $gradefordisplay = $this->display_grade($gradebookgrade->grade, false);
+ }
+ $gradeddate = $gradebookgrade->dategraded;
+ if (isset($grade->grader)) {
+ $grader = $DB->get_record('user', array('id' => $grade->grader));
+ }
}
- $cangrade = has_capability('mod/assign:grade', $this->get_context());
- // If there is a visible grade, show the summary.
- if ((!is_null($gradebookgrade->grade) || !$emptyplugins)
- && ($cangrade || !$gradebookgrade->hidden)) {
+ $feedbackstatus = new assign_feedback_status($gradefordisplay,
+ $gradeddate,
+ $grader,
+ $this->get_feedback_plugins(),
+ $grade,
+ $this->get_course_module()->id,
+ $this->get_return_action(),
+ $this->get_return_params());
+ return $feedbackstatus;
+ }
+ return;
+ }
+
+ /**
+ * Creates an assign_attempt_history renderable.
+ *
+ * @param stdClass $user the user to get the report for
+ * @return assign_attempt_history renderable object
+ */
+ public function get_assign_attempt_history_renderable($user) {
- $gradefordisplay = null;
- $gradeddate = null;
- $grader = null;
- $gradingmanager = get_grading_manager($this->get_context(), 'mod_assign', 'submissions');
+ $allsubmissions = $this->get_all_submissions($user->id);
+ $allgrades = $this->get_all_grades($user->id);
- // Only show the grade if it is not hidden in gradebook.
- if (!is_null($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden)) {
- if ($controller = $gradingmanager->get_active_controller()) {
- $menu = make_grades_menu($this->get_instance()->grade);
- $controller->set_grade_range($menu, $this->get_instance()->grade > 0);
- $gradefordisplay = $controller->render_grade($PAGE,
- $grade->id,
- $gradingitem,
- $gradebookgrade->str_long_grade,
- $cangrade);
- } else {
- $gradefordisplay = $this->display_grade($gradebookgrade->grade, false);
- }
- $gradeddate = $gradebookgrade->dategraded;
- if (isset($grade->grader)) {
- $grader = $DB->get_record('user', array('id'=>$grade->grader));
- }
- }
+ $history = new assign_attempt_history($allsubmissions,
+ $allgrades,
+ $this->get_submission_plugins(),
+ $this->get_feedback_plugins(),
+ $this->get_course_module()->id,
+ $this->get_return_action(),
+ $this->get_return_params(),
+ false,
+ 0,
+ 0);
+ return $history;
+ }
- $feedbackstatus = new assign_feedback_status($gradefordisplay,
- $gradeddate,
- $grader,
- $this->get_feedback_plugins(),
- $grade,
- $this->get_course_module()->id,
- $this->get_return_action(),
- $this->get_return_params());
+ /**
+ * Print 2 tables of information with no action links -
+ * the submission summary and the grading summary.
+ *
+ * @param stdClass $user the user to print the report for
+ * @param bool $showlinks - Return plain text or links to the profile
+ * @return string - the html summary
+ */
+ public function view_student_summary($user, $showlinks) {
- $o .= $this->get_renderer()->render($feedbackstatus);
- }
+ $o = '';
- $allsubmissions = $this->get_all_submissions($user->id);
+ if ($this->can_view_submission($user->id)) {
- if (count($allsubmissions) > 1) {
- $allgrades = $this->get_all_grades($user->id);
- $history = new assign_attempt_history($allsubmissions,
- $allgrades,
- $this->get_submission_plugins(),
- $this->get_feedback_plugins(),
- $this->get_course_module()->id,
- $this->get_return_action(),
- $this->get_return_params(),
- false,
- 0,
- 0);
+ if (has_capability('mod/assign:submit', $this->get_context(), $user)) {
+ $submissionstatus = $this->get_assign_submission_status_renderable($user, $showlinks);
+ $o .= $this->get_renderer()->render($submissionstatus);
+ }
- $o .= $this->get_renderer()->render($history);
+ // If there is a visible grade, show the feedback.
+ $feedbackstatus = $this->get_assign_feedback_status_renderable($user);
+ if ($feedbackstatus) {
+ $o .= $this->get_renderer()->render($feedbackstatus);
}
+ // If there is more than one submission, show the history.
+ $history = $this->get_assign_attempt_history_renderable($user);
+ if (count($history->submissions) > 1) {
+ $o .= $this->get_renderer()->render($history);
+ }
}
return $o;
}
return $submissions;
}
+ /**
+ * Creates an assign_grading_summary renderable.
+ *
+ * @return assign_grading_summary renderable object
+ */
+ public function get_assign_grading_summary_renderable() {
+
+ $instance = $this->get_instance();
+
+ $draft = ASSIGN_SUBMISSION_STATUS_DRAFT;
+ $submitted = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+
+ $activitygroup = groups_get_activity_group($this->get_course_module());
+
+ if ($instance->teamsubmission) {
+ $defaultteammembers = $this->get_submission_group_members(0, true);
+ $warnofungroupedusers = (count($defaultteammembers) > 0 && $instance->preventsubmissionnotingroup);
+
+ $summary = new assign_grading_summary($this->count_teams($activitygroup),
+ $instance->submissiondrafts,
+ $this->count_submissions_with_status($draft),
+ $this->is_any_submission_plugin_enabled(),
+ $this->count_submissions_with_status($submitted),
+ $instance->cutoffdate,
+ $instance->duedate,
+ $this->get_course_module()->id,
+ $this->count_submissions_need_grading(),
+ $instance->teamsubmission,
+ $warnofungroupedusers);
+ } else {
+ // The active group has already been updated in groups_print_activity_menu().
+ $countparticipants = $this->count_participants($activitygroup);
+ $summary = new assign_grading_summary($countparticipants,
+ $instance->submissiondrafts,
+ $this->count_submissions_with_status($draft),
+ $this->is_any_submission_plugin_enabled(),
+ $this->count_submissions_with_status($submitted),
+ $instance->cutoffdate,
+ $instance->duedate,
+ $this->get_course_module()->id,
+ $this->count_submissions_need_grading(),
+ $instance->teamsubmission,
+ false);
+
+ }
+
+ return $summary;
+ }
+
/**
* View submissions page (contains details of current submission).
*
}
if ($this->can_view_grades()) {
- $draft = ASSIGN_SUBMISSION_STATUS_DRAFT;
- $submitted = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
-
// Group selector will only be displayed if necessary.
$currenturl = new moodle_url('/mod/assign/view.php', array('id' => $this->get_course_module()->id));
$o .= groups_print_activity_menu($this->get_course_module(), $currenturl->out(), true);
- $activitygroup = groups_get_activity_group($this->get_course_module());
-
- if ($instance->teamsubmission) {
- $defaultteammembers = $this->get_submission_group_members(0, true);
- $warnofungroupedusers = (count($defaultteammembers) > 0 && $instance->preventsubmissionnotingroup);
-
- $summary = new assign_grading_summary($this->count_teams($activitygroup),
- $instance->submissiondrafts,
- $this->count_submissions_with_status($draft),
- $this->is_any_submission_plugin_enabled(),
- $this->count_submissions_with_status($submitted),
- $instance->cutoffdate,
- $instance->duedate,
- $this->get_course_module()->id,
- $this->count_submissions_need_grading(),
- $instance->teamsubmission,
- $warnofungroupedusers);
- $o .= $this->get_renderer()->render($summary);
- } else {
- // The active group has already been updated in groups_print_activity_menu().
- $countparticipants = $this->count_participants($activitygroup);
- $summary = new assign_grading_summary($countparticipants,
- $instance->submissiondrafts,
- $this->count_submissions_with_status($draft),
- $this->is_any_submission_plugin_enabled(),
- $this->count_submissions_with_status($submitted),
- $instance->cutoffdate,
- $instance->duedate,
- $this->get_course_module()->id,
- $this->count_submissions_need_grading(),
- $instance->teamsubmission,
- false);
- $o .= $this->get_renderer()->render($summary);
- }
+ $summary = $this->get_assign_grading_summary_renderable();
+ $o .= $this->get_renderer()->render($summary);
}
$grade = $this->get_user_grade($USER->id, false);
$submission = $this->get_user_submission($USER->id, false);
$this->assertEquals(1, count($assignment['submissions']));
$submission = $assignment['submissions'][0];
$this->assertEquals($sid, $submission['id']);
- $this->assertGreaterThanOrEqual(3, count($submission['plugins']));
- $plugins = $submission['plugins'];
- foreach ($plugins as $plugin) {
- $foundonlinetext = false;
- if ($plugin['type'] == 'onlinetext') {
- $foundonlinetext = true;
- break;
- }
- }
- $this->assertTrue($foundonlinetext);
+ $this->assertCount(1, $submission['plugins']);
}
/**
}
}
+ /**
+ * Create a submission for testing the get_submission_status function.
+ * @param boolean $submitforgrading whether to submit for grading the submission
+ * @return array an array containing all the required data for testing
+ */
+ private function create_submission_for_testing_status($submitforgrading = false) {
+ global $DB, $CFG;
+ require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
+
+ // Create a course and assignment and users.
+ $course = self::getDataGenerator()->create_course();
+
+ $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+ $params = array(
+ 'course' => $course->id,
+ 'assignsubmission_file_maxfiles' => 1,
+ 'assignsubmission_file_maxsizebytes' => 1024 * 1024,
+ 'assignsubmission_onlinetext_enabled' => 1,
+ 'assignsubmission_file_enabled' => 1,
+ 'submissiondrafts' => 1,
+ 'assignfeedback_file_enabled' => 1,
+ 'assignfeedback_comments_enabled' => 1,
+ 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
+ 'sendnotifications' => 0
+ );
+
+ set_config('submissionreceipts', 0, 'assign');
+
+ $instance = $generator->create_instance($params);
+ $cm = get_coursemodule_from_instance('assign', $instance->id);
+ $context = context_module::instance($cm->id);
+
+ $assign = new testable_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);
+
+ $this->setUser($student1);
+
+ // Create a student1 with an online text submission.
+ // Simulate a submission.
+ $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);
+
+ $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' => 't.txt',
+ );
+ $fs = get_file_storage();
+ $fs->create_file_from_string($filerecord, 'text contents');
+
+ $data->files_filemanager = $draftidfile;
+
+ $notices = array();
+ $assign->save_submission($data, $notices);
+
+ if ($submitforgrading) {
+ // Now, submit the draft for grading.
+ $notices = array();
+
+ $data = new stdClass;
+ $data->userid = $student1->id;
+ $assign->submit_for_grading($data, $notices);
+ }
+
+ return array($assign, $instance, $student1, $student2, $teacher);
+ }
+
+ /**
+ * Test get_submission_status for a draft submission.
+ */
+ public function test_get_submission_status_in_draft_status() {
+ $this->resetAfterTest(true);
+
+ list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status();
+
+ $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
+ // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
+ $this->assertDebuggingCalled();
+
+ $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
+
+ // The submission is now in draft mode.
+ $this->assertCount(0, $result['warnings']);
+ $this->assertFalse(isset($result['gradingsummary']));
+ $this->assertFalse(isset($result['feedback']));
+ $this->assertFalse(isset($result['previousattempts']));
+
+ $this->assertTrue($result['lastattempt']['submissionsenabled']);
+ $this->assertTrue($result['lastattempt']['canedit']);
+ $this->assertTrue($result['lastattempt']['cansubmit']);
+ $this->assertFalse($result['lastattempt']['locked']);
+ $this->assertFalse($result['lastattempt']['graded']);
+ $this->assertEmpty($result['lastattempt']['extensionduedate']);
+ $this->assertFalse($result['lastattempt']['blindmarking']);
+ $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
+ $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
+
+ $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
+ $this->assertEquals(0, $result['lastattempt']['submission']['attemptnumber']);
+ $this->assertEquals('draft', $result['lastattempt']['submission']['status']);
+ $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
+ $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
+ $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
+ $this->assertEquals('Submission text', $result['lastattempt']['submission']['plugins'][0]['editorfields'][0]['text']);
+ $this->assertEquals('/t.txt', $result['lastattempt']['submission']['plugins'][1]['fileareas'][0]['files'][0]['filepath']);
+ }
+
+ /**
+ * Test get_submission_status for a submitted submission.
+ */
+ public function test_get_submission_status_in_submission_status() {
+ $this->resetAfterTest(true);
+
+ list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
+
+ $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
+ // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
+ $this->assertDebuggingCalled();
+ $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
+
+ $this->assertCount(0, $result['warnings']);
+ $this->assertFalse(isset($result['gradingsummary']));
+ $this->assertFalse(isset($result['feedback']));
+ $this->assertFalse(isset($result['previousattempts']));
+
+ $this->assertTrue($result['lastattempt']['submissionsenabled']);
+ $this->assertFalse($result['lastattempt']['canedit']);
+ $this->assertFalse($result['lastattempt']['cansubmit']);
+ $this->assertFalse($result['lastattempt']['locked']);
+ $this->assertFalse($result['lastattempt']['graded']);
+ $this->assertEmpty($result['lastattempt']['extensionduedate']);
+ $this->assertFalse($result['lastattempt']['blindmarking']);
+ $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
+ $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
+
+ }
+
+ /**
+ * Test get_submission_status using the teacher role.
+ */
+ public function test_get_submission_status_in_submission_status_for_teacher() {
+ $this->resetAfterTest(true);
+
+ list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
+
+ // Now, as teacher, see the grading summary.
+ $this->setUser($teacher);
+ $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
+ // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
+ $this->assertDebuggingCalled();
+ $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
+
+ $this->assertCount(0, $result['warnings']);
+ $this->assertFalse(isset($result['lastattempt']));
+ $this->assertFalse(isset($result['feedback']));
+ $this->assertFalse(isset($result['previousattempts']));
+
+ $this->assertEquals(2, $result['gradingsummary']['participantcount']);
+ $this->assertEquals(0, $result['gradingsummary']['submissiondraftscount']);
+ $this->assertEquals(1, $result['gradingsummary']['submissionsenabled']);
+ $this->assertEquals(1, $result['gradingsummary']['submissionssubmittedcount']);
+ $this->assertEquals(1, $result['gradingsummary']['submissionsneedgradingcount']);
+ $this->assertFalse($result['gradingsummary']['warnofungroupedusers']);
+ }
+
+ /**
+ * Test get_submission_status for a reopened submission.
+ */
+ public function test_get_submission_status_in_reopened_status() {
+ global $USER;
+
+ $this->resetAfterTest(true);
+
+ list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status(true);
+
+ $this->setUser($teacher);
+ // Grade and reopen.
+ $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,
+ false,
+ 'released',
+ false,
+ $feedbackpluginparams);
+ $USER->ignoresesskey = true;
+ $assign->testable_process_add_attempt($student1->id);
+
+ $this->setUser($student1);
+
+ $result = mod_assign_external::get_submission_status($assign->get_instance()->id);
+ // We expect debugging because of the $PAGE object, this won't happen in a normal WS request.
+ $this->assertDebuggingCalled();
+ $result = external_api::clean_returnvalue(mod_assign_external::get_submission_status_returns(), $result);
+
+ $this->assertCount(0, $result['warnings']);
+ $this->assertFalse(isset($result['gradingsummary']));
+
+ $this->assertTrue($result['lastattempt']['submissionsenabled']);
+ $this->assertTrue($result['lastattempt']['canedit']);
+ $this->assertFalse($result['lastattempt']['cansubmit']);
+ $this->assertFalse($result['lastattempt']['locked']);
+ $this->assertFalse($result['lastattempt']['graded']);
+ $this->assertEmpty($result['lastattempt']['extensionduedate']);
+ $this->assertFalse($result['lastattempt']['blindmarking']);
+ $this->assertCount(0, $result['lastattempt']['submissiongroupmemberswhoneedtosubmit']);
+ $this->assertEquals('notgraded', $result['lastattempt']['gradingstatus']);
+
+ // Check new attempt reopened.
+ $this->assertEquals($student1->id, $result['lastattempt']['submission']['userid']);
+ $this->assertEquals(1, $result['lastattempt']['submission']['attemptnumber']);
+ $this->assertEquals('reopened', $result['lastattempt']['submission']['status']);
+ $this->assertEquals(0, $result['lastattempt']['submission']['groupid']);
+ $this->assertEquals($assign->get_instance()->id, $result['lastattempt']['submission']['assignment']);
+ $this->assertEquals(1, $result['lastattempt']['submission']['latest']);
+ $this->assertCount(3, $result['lastattempt']['submission']['plugins']);
+
+ // Now see feedback and the attempts history (remember, is a submission reopened).
+ // Only 2 fields (no grade, no plugins data).
+ $this->assertCount(2, $result['feedback']);
+
+ // One previous attempt.
+ $this->assertCount(1, $result['previousattempts']);
+ $this->assertEquals(0, $result['previousattempts'][0]['attemptnumber']);
+ $this->assertEquals(50, $result['previousattempts'][0]['grade']['grade']);
+ $this->assertEquals($teacher->id, $result['previousattempts'][0]['grade']['grader']);
+ $this->assertEquals($student1->id, $result['previousattempts'][0]['grade']['userid']);
+ $this->assertEquals('Yeeha!', $result['previousattempts'][0]['feedbackplugins'][0]['editorfields'][0]['text']);
+ $submissionplugins = $result['previousattempts'][0]['submission']['plugins'];
+ $this->assertEquals('Submission text', $submissionplugins[0]['editorfields'][0]['text']);
+ $this->assertEquals('/t.txt', $submissionplugins[1]['fileareas'][0]['files'][0]['filepath']);
+ }
+
+ /**
+ * Test access control for get_submission_status.
+ */
+ public function test_get_submission_status_access_control() {
+ $this->resetAfterTest(true);
+
+ list($assign, $instance, $student1, $student2, $teacher) = $this->create_submission_for_testing_status();
+
+ $this->setUser($student2);
+
+ // Access control test.
+ $this->setExpectedException('required_capability_exception');
+ mod_assign_external::get_submission_status($assign->get_instance()->id, $student1->id);
+
+ }
}
defined('MOODLE_INTERNAL') || die();
-$version = 2016031700.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2016031700.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.