mirror of
https://github.com/moodle/moodle.git
synced 2025-03-14 04:30:15 +01:00
Merge branch 'MDL-36804-master' of git://github.com/damyon/moodle
This commit is contained in:
commit
5e45f6a569
@ -627,4 +627,5 @@ abstract class assign_plugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -62,7 +62,18 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
|
||||
'requireallteammemberssubmit',
|
||||
'teamsubmissiongroupingid',
|
||||
'blindmarking',
|
||||
'revealidentities'));
|
||||
'revealidentities',
|
||||
'attemptreopenmethod',
|
||||
'maxattempts'));
|
||||
|
||||
$userflags = new backup_nested_element('userflags');
|
||||
|
||||
$userflag = new backup_nested_element('userflag', array('id'),
|
||||
array('userid',
|
||||
'assignment',
|
||||
'mailed',
|
||||
'locked',
|
||||
'extensionduedate'));
|
||||
|
||||
$submissions = new backup_nested_element('submissions');
|
||||
|
||||
@ -71,7 +82,8 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
|
||||
'timecreated',
|
||||
'timemodified',
|
||||
'status',
|
||||
'groupid'));
|
||||
'groupid',
|
||||
'attemptnumber'));
|
||||
|
||||
$grades = new backup_nested_element('grades');
|
||||
|
||||
@ -81,9 +93,7 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
|
||||
'timemodified',
|
||||
'grader',
|
||||
'grade',
|
||||
'locked',
|
||||
'mailed',
|
||||
'extensionduedate'));
|
||||
'attemptnumber'));
|
||||
|
||||
$pluginconfigs = new backup_nested_element('plugin_configs');
|
||||
|
||||
@ -94,7 +104,8 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
|
||||
'value'));
|
||||
|
||||
// Build the tree.
|
||||
|
||||
$assign->add_child($userflags);
|
||||
$userflags->add_child($userflag);
|
||||
$assign->add_child($submissions);
|
||||
$submissions->add_child($submission);
|
||||
$assign->add_child($grades);
|
||||
@ -108,6 +119,9 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
|
||||
array('assignment' => backup::VAR_PARENTID));
|
||||
|
||||
if ($userinfo) {
|
||||
$userflag->set_source_table('assign_user_flags',
|
||||
array('assignment' => backup::VAR_PARENTID));
|
||||
|
||||
$submission->set_source_table('assign_submission',
|
||||
array('assignment' => backup::VAR_PARENTID));
|
||||
|
||||
@ -120,6 +134,7 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
|
||||
}
|
||||
|
||||
// Define id annotations.
|
||||
$userflag->annotate_ids('user', 'userid');
|
||||
$submission->annotate_ids('user', 'userid');
|
||||
$submission->annotate_ids('group', 'groupid');
|
||||
$grade->annotate_ids('user', 'userid');
|
||||
|
@ -130,6 +130,30 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
|
||||
$this->set_mapping('submission', $oldid, $newitemid, false, null, $this->task->get_old_contextid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a user_flags restore
|
||||
* @param object $data The data in object form
|
||||
* @return void
|
||||
*/
|
||||
protected function process_assign_userflags($data) {
|
||||
global $DB;
|
||||
|
||||
$data = (object)$data;
|
||||
$oldid = $data->id;
|
||||
|
||||
$data->assignment = $this->get_new_parentid('assign');
|
||||
|
||||
$data->userid = $this->get_mappingid('user', $data->userid);
|
||||
if (!empty($data->extensionduedate)) {
|
||||
$data->extensionduedate = $this->apply_date_offset($data->extensionduedate);
|
||||
} else {
|
||||
$data->extensionduedate = 0;
|
||||
}
|
||||
// Flags mailed and locked need no translation on restore.
|
||||
|
||||
$newitemid = $DB->insert_record('assign_user_flags', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a grade restore
|
||||
* @param object $data The data in object form
|
||||
@ -147,11 +171,20 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
|
||||
$data->timecreated = $this->apply_date_offset($data->timecreated);
|
||||
$data->userid = $this->get_mappingid('user', $data->userid);
|
||||
$data->grader = $this->get_mappingid('user', $data->grader);
|
||||
|
||||
// Handle flags restore to a different table.
|
||||
$flags = new stdClass();
|
||||
$flags->assignment = $this->get_new_parentid('assign');
|
||||
if (!empty($data->extensionduedate)) {
|
||||
$data->extensionduedate = $this->apply_date_offset($data->extensionduedate);
|
||||
} else {
|
||||
$data->extensionduedate = 0;
|
||||
$flags->extensionduedate = $this->apply_date_offset($data->extensionduedate);
|
||||
}
|
||||
if (!empty($data->mailed)) {
|
||||
$flags->mailed = $data->mailed;
|
||||
}
|
||||
if (!empty($data->locked)) {
|
||||
$flags->locked = $data->locked;
|
||||
}
|
||||
$DB->insert_record('assign_user_flags', $flags);
|
||||
|
||||
$newitemid = $DB->insert_record('assign_grades', $data);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="mod/assign/db" VERSION="20120830" COMMENT="XMLDB file for Moodle mod/assign"
|
||||
<XMLDB PATH="mod/assign/db" VERSION="20130308" COMMENT="XMLDB file for Moodle mod/assign"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@ -23,11 +23,13 @@
|
||||
<FIELD NAME="requiresubmissionstatement" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Forces the student to accept a submission statement when submitting an assignment"/>
|
||||
<FIELD NAME="completionsubmit" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If this field is set to 1, then the activity will be automatically marked as 'complete' once the user submits their assignment."/>
|
||||
<FIELD NAME="cutoffdate" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The final date after which submissions will no longer be accepted for this assignment without an extensions."/>
|
||||
<FIELD NAME="teamsubmission" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Do students submit in teams?"/>
|
||||
<FIELD NAME="requireallteammemberssubmit" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, a submission will not be accepted until all team members have submitted it."/>
|
||||
<FIELD NAME="teamsubmissiongroupingid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="A grouping id to get groups for team submissions"/>
|
||||
<FIELD NAME="teamsubmission" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Do students submit in teams?"/>
|
||||
<FIELD NAME="requireallteammemberssubmit" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, a submission will not be accepted until all team members have submitted it."/>
|
||||
<FIELD NAME="teamsubmissiongroupingid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="A grouping id to get groups for team submissions"/>
|
||||
<FIELD NAME="blindmarking" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Hide student/grader identities until the reveal identities action is performed"/>
|
||||
<FIELD NAME="revealidentities" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Show identities for a blind marking assignment"/>
|
||||
<FIELD NAME="attemptreopenmethod" TYPE="char" LENGTH="10" NOTNULL="true" DEFAULT="none" SEQUENCE="false" COMMENT="How to determine when students are allowed to open a new submission. Valid options are none, manual, untilpass"/>
|
||||
<FIELD NAME="maxattempts" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="-1" SEQUENCE="false" COMMENT="What is the maximum number of student attempts allowed for this assignment? -1 means unlimited."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment instance."/>
|
||||
@ -45,7 +47,8 @@
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The time of the first student submission to this assignment."/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The last time this assignment submission was modified by a student."/>
|
||||
<FIELD NAME="status" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="The status of this assignment submission. The current statuses are DRAFT and SUBMITTED."/>
|
||||
<FIELD NAME="groupid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The group id for team submissions"/>
|
||||
<FIELD NAME="groupid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The group id for team submissions"/>
|
||||
<FIELD NAME="attemptnumber" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Used to track attempts for an assignment"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment submission."/>
|
||||
@ -53,6 +56,8 @@
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="userid" UNIQUE="false" FIELDS="userid"/>
|
||||
<INDEX NAME="attemptnumber" UNIQUE="false" FIELDS="attemptnumber"/>
|
||||
<INDEX NAME="uniqueattemptsubmission" UNIQUE="true" FIELDS="assignment, userid, groupid, attemptnumber"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="assign_grades" COMMENT="Grading information about a single assignment submission.">
|
||||
@ -64,9 +69,7 @@
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The most recent modification time for the assignment submission by a grader."/>
|
||||
<FIELD NAME="grader" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="grade" TYPE="number" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" DECIMALS="5" COMMENT="The numerical grade for this assignment submission. Can be determined by scales/advancedgradingforms etc but will always be converted back to a floating point number."/>
|
||||
<FIELD NAME="locked" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="A flag to prevent changes for a single student submission."/>
|
||||
<FIELD NAME="mailed" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Has the student been sent a notification about this grade update?"/>
|
||||
<FIELD NAME="extensionduedate" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="An extension date assigned to an individual student"/>
|
||||
<FIELD NAME="attemptnumber" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The attempt number that this grade relates to"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this grade."/>
|
||||
@ -74,7 +77,8 @@
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="userid" UNIQUE="false" FIELDS="userid" COMMENT="The userid for the submission relating to this grade."/>
|
||||
<INDEX NAME="mailed" UNIQUE="false" FIELDS="mailed" COMMENT="True if notifications have been sent about the most recent grader update about this submission."/>
|
||||
<INDEX NAME="attemptnumber" UNIQUE="false" FIELDS="attemptnumber"/>
|
||||
<INDEX NAME="uniqueattemptgrade" UNIQUE="true" FIELDS="assignment, userid, attemptnumber" COMMENT="This is a grade for a unique attempt."/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="assign_plugin_config" COMMENT="Config data for an instance of a plugin in an assignment.">
|
||||
@ -108,5 +112,23 @@
|
||||
<KEY NAME="user" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id" COMMENT="The user to map to an id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="assign_user_flags" COMMENT="List of flags that can be set for a single user in a single assignment.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The id of the user these flags apply to."/>
|
||||
<FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The assignment these flags apply to."/>
|
||||
<FIELD NAME="locked" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Student cannot make any changes to their submission if this flag is set."/>
|
||||
<FIELD NAME="mailed" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Has the student been sent a notification about this grade update?"/>
|
||||
<FIELD NAME="extensionduedate" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="An extension date assigned to an individual student."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id" COMMENT="The id field of the user table."/>
|
||||
<KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assign" REFFIELDS="id" COMMENT="The assignment id these flags apply to."/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="mailed" UNIQUE="false" FIELDS="mailed" COMMENT="Has this user been mailed yet?"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
|
@ -208,6 +208,145 @@ function xmldb_assign_upgrade($oldversion) {
|
||||
// Moodle v2.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2013030600) {
|
||||
// Define table assign_user_flags to be created.
|
||||
$table = new xmldb_table('assign_user_flags');
|
||||
|
||||
// Adding fields to table assign_user_flags.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
|
||||
$table->add_field('assignment', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
|
||||
$table->add_field('locked', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
|
||||
$table->add_field('mailed', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
|
||||
$table->add_field('extensionduedate', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
|
||||
|
||||
// Adding keys to table assign_user_flags.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
|
||||
$table->add_key('assignment', XMLDB_KEY_FOREIGN, array('assignment'), 'assign', array('id'));
|
||||
|
||||
// Adding indexes to table assign_user_flags.
|
||||
$table->add_index('mailed', XMLDB_INDEX_NOTUNIQUE, array('mailed'));
|
||||
|
||||
// Conditionally launch create table for assign_user_flags.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Copy the flags from the old table to the new one.
|
||||
$sql = 'INSERT INTO {assign_user_flags}
|
||||
(assignment, userid, locked, mailed, extensionduedate)
|
||||
SELECT assignment, userid, locked, mailed, extensionduedate
|
||||
FROM {assign_grades}';
|
||||
$DB->execute($sql);
|
||||
|
||||
// And delete the old columns.
|
||||
// Define index mailed (not unique) to be dropped form assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$index = new xmldb_index('mailed', XMLDB_INDEX_NOTUNIQUE, array('mailed'));
|
||||
|
||||
// Conditionally launch drop index mailed.
|
||||
if ($dbman->index_exists($table, $index)) {
|
||||
$dbman->drop_index($table, $index);
|
||||
}
|
||||
|
||||
// Define field locked to be dropped from assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$field = new xmldb_field('locked');
|
||||
|
||||
// Conditionally launch drop field locked.
|
||||
if ($dbman->field_exists($table, $field)) {
|
||||
$dbman->drop_field($table, $field);
|
||||
}
|
||||
|
||||
// Define field mailed to be dropped from assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$field = new xmldb_field('mailed');
|
||||
|
||||
// Conditionally launch drop field mailed.
|
||||
if ($dbman->field_exists($table, $field)) {
|
||||
$dbman->drop_field($table, $field);
|
||||
}
|
||||
|
||||
// Define field extensionduedate to be dropped from assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$field = new xmldb_field('extensionduedate');
|
||||
|
||||
// Conditionally launch drop field extensionduedate.
|
||||
if ($dbman->field_exists($table, $field)) {
|
||||
$dbman->drop_field($table, $field);
|
||||
}
|
||||
|
||||
// Define field attemptreopenmethod to be added to assign.
|
||||
$table = new xmldb_table('assign');
|
||||
$field = new xmldb_field('attemptreopenmethod', XMLDB_TYPE_CHAR, '10', null,
|
||||
XMLDB_NOTNULL, null, 'none', 'revealidentities');
|
||||
|
||||
// Conditionally launch add field attemptreopenmethod.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Define field maxattempts to be added to assign.
|
||||
$table = new xmldb_table('assign');
|
||||
$field = new xmldb_field('maxattempts', XMLDB_TYPE_INTEGER, '6', null, XMLDB_NOTNULL, null, '-1', 'attemptreopenmethod');
|
||||
|
||||
// Conditionally launch add field maxattempts.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Define field attemptnumber to be added to assign_submission.
|
||||
$table = new xmldb_table('assign_submission');
|
||||
$field = new xmldb_field('attemptnumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'groupid');
|
||||
|
||||
// Conditionally launch add field attemptnumber.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Define field attemptnumber to be added to assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$field = new xmldb_field('attemptnumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'grade');
|
||||
|
||||
// Conditionally launch add field attemptnumber.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Define index attemptnumber (not unique) to be added to assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$index = new xmldb_index('attemptnumber', XMLDB_INDEX_NOTUNIQUE, array('attemptnumber'));
|
||||
|
||||
// Conditionally launch add index attemptnumber.
|
||||
if (!$dbman->index_exists($table, $index)) {
|
||||
$dbman->add_index($table, $index);
|
||||
}
|
||||
|
||||
// Define index uniqueattemptsubmission (unique) to be added to assign_submission.
|
||||
$table = new xmldb_table('assign_submission');
|
||||
$index = new xmldb_index('uniqueattemptsubmission',
|
||||
XMLDB_INDEX_UNIQUE,
|
||||
array('assignment', 'userid', 'groupid', 'attemptnumber'));
|
||||
|
||||
// Conditionally launch add index uniqueattempt.
|
||||
if (!$dbman->index_exists($table, $index)) {
|
||||
$dbman->add_index($table, $index);
|
||||
}
|
||||
|
||||
// Define index uniqueattemptgrade (unique) to be added to assign_grades.
|
||||
$table = new xmldb_table('assign_grades');
|
||||
$index = new xmldb_index('uniqueattemptgrade', XMLDB_INDEX_UNIQUE, array('assignment', 'userid', 'attemptnumber'));
|
||||
|
||||
// Conditionally launch add index uniqueattempt.
|
||||
if (!$dbman->index_exists($table, $index)) {
|
||||
$dbman->add_index($table, $index);
|
||||
}
|
||||
|
||||
// Module assign savepoint reached.
|
||||
upgrade_mod_savepoint(true, 2013030600, 'assign');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -95,13 +95,23 @@ class mod_assign_external extends external_api {
|
||||
if (count ($requestedassignmentids) > 0) {
|
||||
$placeholders = array();
|
||||
list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
|
||||
list($inorequalsql2, $placeholders2) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
|
||||
|
||||
$grademaxattempt = 'SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt
|
||||
FROM {assign_grades} mxg
|
||||
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.locked,ag.mailed ".
|
||||
"ag.grader,ag.grade ".
|
||||
"FROM {assign_grades} ag ".
|
||||
"WHERE ag.assignment ".$inorequalsql.
|
||||
"JOIN ( " . $grademaxattempt . " ) gmx ON ag.userid = gmx.userid".
|
||||
" WHERE ag.assignment ".$inorequalsql.
|
||||
" AND ag.timemodified >= :since".
|
||||
" AND ag.attemptnumber = gmx.maxattempt" .
|
||||
" ORDER BY ag.assignment, ag.id";
|
||||
$placeholders['since'] = $params['since'];
|
||||
// Combine the parameters.
|
||||
$placeholders += $placeholders2;
|
||||
$rs = $DB->get_recordset_sql($sql, $placeholders);
|
||||
$currentassignmentid = null;
|
||||
$assignment = null;
|
||||
@ -113,8 +123,6 @@ class mod_assign_external extends external_api {
|
||||
$grade['timemodified'] = $rd->timemodified;
|
||||
$grade['grader'] = $rd->grader;
|
||||
$grade['grade'] = (string)$rd->grade;
|
||||
$grade['locked'] = $rd->locked;
|
||||
$grade['mailed'] = $rd->mailed;
|
||||
|
||||
if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
|
||||
if (!is_null($assignment)) {
|
||||
@ -165,9 +173,7 @@ class mod_assign_external extends external_api {
|
||||
'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'),
|
||||
'locked' => new external_value(PARAM_BOOL, 'locked'),
|
||||
'mailed' => new external_value(PARAM_BOOL, 'mailed')
|
||||
'grade' => new external_value(PARAM_TEXT, 'grade')
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -504,11 +510,18 @@ class mod_assign_external extends external_api {
|
||||
foreach ($assigns as $assign) {
|
||||
$submissions = array();
|
||||
$submissionplugins = $assign->get_submission_plugins();
|
||||
$placeholders = array('assignment' => $assign->get_instance()->id);
|
||||
$placeholders = array('assignid1' => $assign->get_instance()->id,
|
||||
'assignid2' => $assign->get_instance()->id);
|
||||
|
||||
$submissionmaxattempt = 'SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
|
||||
FROM {assign_submission} mxs
|
||||
WHERE mxs.assignment = :assignid1 GROUP BY mxs.userid';
|
||||
|
||||
$sql = "SELECT mas.id, mas.assignment,mas.userid,".
|
||||
"mas.timecreated,mas.timemodified,mas.status,mas.groupid ".
|
||||
"FROM {assign_submission} mas ".
|
||||
"WHERE mas.assignment = :assignment";
|
||||
"JOIN ( " . $submissionmaxattempt . " ) smx ON mas.userid = smx.userid ".
|
||||
"WHERE mas.assignment = :assignid2 AND mas.attemptnumber = smx.maxattempt";
|
||||
|
||||
if (!empty($params['status'])) {
|
||||
$placeholders['status'] = $params['status'];
|
||||
|
@ -52,6 +52,9 @@ class mod_assign_grading_batch_operations_form extends moodleform {
|
||||
if ($instance['duedate']) {
|
||||
$options['grantextension'] = get_string('grantextension', 'assign');
|
||||
}
|
||||
if ($instance['attemptreopenmethod'] == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL) {
|
||||
$options['addattempt'] = get_string('addattempt', 'assign');
|
||||
}
|
||||
|
||||
foreach ($instance['feedbackplugins'] as $plugin) {
|
||||
if ($plugin->is_visible() && $plugin->is_enabled()) {
|
||||
|
@ -116,6 +116,9 @@ class assign_grading_table extends table_sql implements renderable {
|
||||
$params = array();
|
||||
$params['assignmentid1'] = (int)$this->assignment->get_instance()->id;
|
||||
$params['assignmentid2'] = (int)$this->assignment->get_instance()->id;
|
||||
$params['assignmentid3'] = (int)$this->assignment->get_instance()->id;
|
||||
$params['assignmentid4'] = (int)$this->assignment->get_instance()->id;
|
||||
$params['assignmentid5'] = (int)$this->assignment->get_instance()->id;
|
||||
|
||||
$extrauserfields = get_extra_user_fields($this->assignment->get_context());
|
||||
|
||||
@ -125,15 +128,33 @@ class assign_grading_table extends table_sql implements renderable {
|
||||
$fields .= 's.id as submissionid, ';
|
||||
$fields .= 's.timecreated as firstsubmission, ';
|
||||
$fields .= 's.timemodified as timesubmitted, ';
|
||||
$fields .= 's.attemptnumber as attemptnumber, ';
|
||||
$fields .= 'g.id as gradeid, ';
|
||||
$fields .= 'g.grade as grade, ';
|
||||
$fields .= 'g.timemodified as timemarked, ';
|
||||
$fields .= 'g.timecreated as firstmarked, ';
|
||||
$fields .= 'g.mailed as mailed, ';
|
||||
$fields .= 'g.locked as locked, ';
|
||||
$fields .= 'g.extensionduedate as extensionduedate';
|
||||
$from = '{user} u LEFT JOIN {assign_submission} s ON u.id = s.userid AND s.assignment = :assignmentid1' .
|
||||
' LEFT JOIN {assign_grades} g ON u.id = g.userid AND g.assignment = :assignmentid2';
|
||||
$fields .= 'uf.mailed as mailed, ';
|
||||
$fields .= 'uf.locked as locked, ';
|
||||
$fields .= 'uf.extensionduedate as extensionduedate';
|
||||
|
||||
$submissionmaxattempt = 'SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
|
||||
FROM {assign_submission} mxs
|
||||
WHERE mxs.assignment = :assignmentid4 GROUP BY mxs.userid';
|
||||
$grademaxattempt = 'SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt
|
||||
FROM {assign_grades} mxg
|
||||
WHERE mxg.assignment = :assignmentid5 GROUP BY mxg.userid';
|
||||
$from = '{user} u
|
||||
LEFT JOIN ( ' . $submissionmaxattempt . ' ) smx ON u.id = smx.userid
|
||||
LEFT JOIN ( ' . $grademaxattempt . ' ) gmx ON u.id = gmx.userid
|
||||
LEFT JOIN {assign_submission} s ON
|
||||
u.id = s.userid AND
|
||||
s.assignment = :assignmentid1 AND
|
||||
s.attemptnumber = smx.maxattempt
|
||||
LEFT JOIN {assign_grades} g ON
|
||||
u.id = g.userid AND
|
||||
g.assignment = :assignmentid2 AND
|
||||
g.attemptnumber = gmx.maxattempt
|
||||
LEFT JOIN {assign_user_flags} uf ON u.id = uf.userid AND uf.assignment = :assignmentid3';
|
||||
|
||||
$userparams = array();
|
||||
$userindex = 0;
|
||||
@ -159,6 +180,7 @@ class assign_grading_table extends table_sql implements renderable {
|
||||
$params['userid'] = $userfilter;
|
||||
}
|
||||
}
|
||||
|
||||
$this->set_sql($fields, $from, $where, $params);
|
||||
|
||||
if ($downloadfilename) {
|
||||
@ -829,6 +851,23 @@ class assign_grading_table extends table_sql implements renderable {
|
||||
$actions[$url->out(false)] = $description;
|
||||
}
|
||||
|
||||
$ismanual = $this->assignment->get_instance()->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL;
|
||||
$hassubmission = !empty($row->status);
|
||||
$notreopened = $hassubmission && $row->status != ASSIGN_SUBMISSION_STATUS_REOPENED;
|
||||
$isunlimited = $this->assignment->get_instance()->maxattempts == ASSIGN_UNLIMITED_ATTEMPTS;
|
||||
$hasattempts = $isunlimited || $row->attemptnumber < $this->assignment->get_instance()->maxattempts - 1;
|
||||
|
||||
if ($ismanual && $hassubmission && $notreopened && $hasattempts) {
|
||||
$urlparams = array('id' => $this->assignment->get_course_module()->id,
|
||||
'userid'=>$row->id,
|
||||
'action'=>'addattempt',
|
||||
'sesskey'=>sesskey(),
|
||||
'page'=>$this->currpage);
|
||||
$url = new moodle_url('/mod/assign/view.php', $urlparams);
|
||||
$description = get_string('addattempt', 'assign');
|
||||
$actions[$url->out(false)] = $description;
|
||||
}
|
||||
|
||||
$edit .= $this->output->container_start(array('yui3-menu', 'actionmenu'), 'actionselect' . $row->id);
|
||||
$edit .= $this->output->container_start(array('yui3-menu-content'));
|
||||
$edit .= html_writer::start_tag('ul');
|
||||
|
@ -24,6 +24,11 @@
|
||||
|
||||
$string['activityoverview'] = 'You have assignments that need attention';
|
||||
$string['addsubmission'] = 'Add submission';
|
||||
$string['addattempt'] = 'Allow another attempt';
|
||||
$string['addnewattempt'] = 'Add a new attempt';
|
||||
$string['addnewattempt_help'] = 'This will create a new blank submission for you to work on.';
|
||||
$string['addnewattemptfromprevious'] = 'Add a new attempt based on previous submission';
|
||||
$string['addnewattemptfromprevious_help'] = 'This will copy the contents of your previous submission to a new submission for you to work on.';
|
||||
$string['allowsubmissions'] = 'Allow the user to continue making submissions to this assignment.';
|
||||
$string['allowsubmissionsshort'] = 'Allow submission changes';
|
||||
$string['allowsubmissionsfromdate'] = 'Allow submissions from';
|
||||
@ -59,6 +64,15 @@ $string['assignmentplugins'] = 'Assignment plugins';
|
||||
$string['assignmentsperpage'] = 'Assignments per page';
|
||||
$string['assignsubmission'] = 'Submission plugin';
|
||||
$string['assignsubmissionpluginname'] = 'Submission plugin';
|
||||
$string['attemptheading'] = 'Attempt {$a->attemptnumber}: {$a->submissionsummary}';
|
||||
$string['attemptnumber'] = 'Attempt number';
|
||||
$string['attempthistory'] = 'Previous attempts';
|
||||
$string['attemptsettings'] = 'Attempt settings';
|
||||
$string['attemptreopenmethod'] = 'Attempts reopened';
|
||||
$string['attemptreopenmethod_help'] = 'Determines how student submission attempts are reopened. The available options are: <ul><li>Never - The student submission cannot be reopened.</li><li>Manually - The student submission can be reopened by a teacher.</li><li>Automatically until pass - The student submission is automatically reopened until the student achieves the grade to pass value that is set in the gradebook for this assignment.</li></ul>';
|
||||
$string['attemptreopenmethod_manual'] = 'Manually';
|
||||
$string['attemptreopenmethod_none'] = 'Never';
|
||||
$string['attemptreopenmethod_untilpass'] = 'Automatically until pass';
|
||||
$string['availability'] = 'Availability';
|
||||
$string['backtoassignment'] = 'Back to assignment';
|
||||
$string['batchoperationsdescription'] = 'With selected...';
|
||||
@ -66,6 +80,7 @@ $string['batchoperationconfirmlock'] = 'Lock all selected submissions?';
|
||||
$string['batchoperationconfirmgrantextension'] = 'Grant an extension to all selected submissions?';
|
||||
$string['batchoperationconfirmunlock'] = 'Unlock all selected submissions?';
|
||||
$string['batchoperationconfirmreverttodraft'] = 'Revert selected submissions to draft?';
|
||||
$string['batchoperationconfirmaddattempt'] = 'Allow another attempt for selected submissions?';
|
||||
$string['batchoperationlock'] = 'lock submissions';
|
||||
$string['batchoperationunlock'] = 'unlock submissions';
|
||||
$string['batchoperationreverttodraft'] = 'revert submissions to draft';
|
||||
@ -78,7 +93,7 @@ $string['comment'] = 'Comment';
|
||||
$string['completionsubmit'] = 'Student must submit to this activity to complete it';
|
||||
$string['conversionexception'] = 'Could not convert assignment. Exception was: {$a}.';
|
||||
$string['configshowrecentsubmissions'] = 'Everyone can see notifications of submissions in recent activity reports.';
|
||||
$string['confirmsubmission'] = 'Are you sure you want to submit your work for grading? You will not be able to make any more changes';
|
||||
$string['confirmsubmission'] = 'Are you sure you want to submit your work for grading? You will not be able to make any more changes.';
|
||||
$string['confirmbatchgradingoperation'] = 'Are you sure you want to {$a->operation} for {$a->count} students?';
|
||||
$string['couldnotconvertgrade'] = 'Could not convert assignment grade for user {$a}.';
|
||||
$string['couldnotconvertsubmission'] = 'Could not convert assignment submission for user {$a}.';
|
||||
@ -86,6 +101,8 @@ $string['couldnotcreatecoursemodule'] = 'Could not create course module.';
|
||||
$string['couldnotcreatenewassignmentinstance'] = 'Could not create new assignment instance.';
|
||||
$string['couldnotfindassignmenttoupgrade'] = 'Could not find old assignment instance to upgrade.';
|
||||
$string['currentgrade'] = 'Current grade in gradebook';
|
||||
$string['currentattempt'] = 'This is attempt {$a}.';
|
||||
$string['currentattemptof'] = 'This is attempt {$a->attemptnumber} ( {$a->maxattempts} attempts allowed ).';
|
||||
$string['cutoffdate'] = 'Cut-off date';
|
||||
$string['cutoffdate_help'] = 'If set, the assignment will not accept submissions after this date without an extension.';
|
||||
$string['cutoffdatevalidation'] = 'The cut-off date cannot be earlier than the due date.';
|
||||
@ -106,7 +123,10 @@ $string['duedateno'] = 'No due date';
|
||||
$string['submissionempty'] = 'Nothing was submitted';
|
||||
$string['duedatereached'] = 'The due date for this assignment has now passed';
|
||||
$string['duedatevalidation'] = 'Due date must be after the allow submissions from date.';
|
||||
$string['editsubmission'] = 'Edit my submission';
|
||||
$string['editattemptfeedback'] = 'Edit the grade and feedback for attempt number {$a}.';
|
||||
$string['editingpreviousfeedbackwarning'] = 'You are editing the feedback for a previous attempt. This is attempt {$a->attemptnumber} out of {$a->totalattempts}.';
|
||||
$string['editsubmission'] = 'Edit submission';
|
||||
$string['editsubmission_help'] = 'Make changes to your submission';
|
||||
$string['editingstatus'] = 'Editing status';
|
||||
$string['editaction'] = 'Actions...';
|
||||
$string['extensionduedate'] = 'Extension due date';
|
||||
@ -160,10 +180,11 @@ $string['gradeoutofhelp'] = 'Grade';
|
||||
$string['gradeoutofhelp_help'] = 'Enter the grade for the student\'s submission here. You may include decimals.';
|
||||
$string['gradestudent'] = 'Grade student: (id={$a->id}, fullname={$a->fullname}). ';
|
||||
$string['grading'] = 'Grading';
|
||||
$string['gradingchangessaved'] = 'The grade changes were saved';
|
||||
$string['gradingmethodpreview'] = 'Grading criteria';
|
||||
$string['gradingoptions'] = 'Options';
|
||||
$string['gradingstatus'] = 'Grading status';
|
||||
$string['gradingstudentprogress'] = 'Grading student {$a->index} of {$a->count}';
|
||||
$string['gradingstudent'] = 'Grading student';
|
||||
$string['gradingsummary'] = 'Grading summary';
|
||||
$string['hideshow'] = 'Hide/Show';
|
||||
$string['hiddenuser'] = 'Participant ';
|
||||
@ -178,7 +199,9 @@ $string['locksubmissionforstudent'] = 'Prevent any more submissions for student:
|
||||
$string['locksubmissions'] = 'Lock submissions';
|
||||
$string['manageassignfeedbackplugins'] = 'Manage assignment feedback plugins';
|
||||
$string['manageassignsubmissionplugins'] = 'Manage assignment submission plugins';
|
||||
$string['maxgrade'] = 'Maximum Grade';
|
||||
$string['maxattempts'] = 'Maximum attempts';
|
||||
$string['maxattempts_help'] = 'The maximum number of submissions attempts that can be made by a student. After this number of attempts has been made the student's submission will not be able to be reopened.';
|
||||
$string['maxgrade'] = 'Maximum grade';
|
||||
$string['messageprovider:assign_notification'] = 'Assignment notifications';
|
||||
$string['modulename'] = 'Assignment';
|
||||
$string['modulename_help'] = 'The assignment activity module enables a teacher to communicate tasks, collect work and provide grades and feedback.
|
||||
@ -190,14 +213,15 @@ $string['modulename_link'] = 'mod/assignment/view';
|
||||
$string['modulenameplural'] = 'Assignments';
|
||||
$string['mysubmission'] = 'My submission: ';
|
||||
$string['newsubmissions'] = 'Assignments submitted';
|
||||
$string['noattempt'] = 'No attempt';
|
||||
$string['nofiles'] = 'No files. ';
|
||||
$string['nograde'] = 'No grade. ';
|
||||
$string['nolatesubmissions'] = 'No late submissions accepted. ';
|
||||
$string['nomoresubmissionsaccepted'] = 'No more submissions accepted';
|
||||
$string['noonlinesubmissions'] = 'This assignment does not require you to submit anything online';
|
||||
$string['nosavebutnext'] = 'Next';
|
||||
$string['nosubmission'] = 'Nothing has been submitted for this assignment';
|
||||
$string['nosubmissionsacceptedafter'] = 'No submissions accepted after ';
|
||||
$string['nomoresubmissionsaccepted'] = 'No more submissions accepted';
|
||||
$string['notgraded'] = 'Not graded';
|
||||
$string['notgradedyet'] = 'Not graded yet';
|
||||
$string['notsubmittedyet'] = 'Not submitted yet';
|
||||
@ -210,6 +234,7 @@ $string['numberofsubmissionsneedgrading'] = 'Needs grading';
|
||||
$string['numberofteams'] = 'Groups';
|
||||
$string['offline'] = 'No online submissions required';
|
||||
$string['open'] = 'Open';
|
||||
$string['outof'] = '{$a->current} out of {$a->total}';
|
||||
$string['overdue'] = '<font color="red">Assignment is overdue by: {$a}</font>';
|
||||
$string['outlinegrade'] = 'Grade: {$a}';
|
||||
$string['page-mod-assign-x'] = 'Any assignment module page';
|
||||
@ -238,6 +263,7 @@ $string['reverttodraft'] = 'Revert the submission to draft status.';
|
||||
$string['reverttodraftshort'] = 'Revert the submission to draft';
|
||||
$string['reviewed'] = 'Reviewed';
|
||||
$string['savechanges'] = 'Save changes';
|
||||
$string['savegradingresult'] = 'Grade';
|
||||
$string['saveallquickgradingchanges'] = 'Save all quick grading changes';
|
||||
$string['savenext'] = 'Save and show next';
|
||||
$string['scale'] = 'Scale';
|
||||
@ -251,9 +277,20 @@ $string['sendsubmissionreceipts'] = 'Send submission receipt to students';
|
||||
$string['sendsubmissionreceipts_help'] = 'This switch will enable submission receipts for students. Students will receive a notification every time they successfully submit an assignment';
|
||||
$string['settings'] = 'Assignment settings';
|
||||
$string['showrecentsubmissions'] = 'Show recent submissions';
|
||||
$string['submissioncopiedtext'] = 'You have made a copy of your previous
|
||||
assignment submission for \'{$a->assignment}\'
|
||||
|
||||
You can see the status of your assignment submission:
|
||||
|
||||
{$a->url}';
|
||||
$string['submissioncopiedhtml'] = 'You have made a copy of your previous
|
||||
assignment submission for \'<i>{$a->assignment}</i>\'<br /><br />
|
||||
You can see the status of your <a href="{$a->url}">assignment submission</a>.';
|
||||
$string['submissioncopiedsmall'] = 'You have copied your previous assignment submission for {$a->assignment}';
|
||||
$string['submissiondrafts'] = 'Require students click submit button';
|
||||
$string['submissiondrafts_help'] = 'If enabled, students will have to click a Submit button to declare their submission as final. This allows students to keep a draft version of the submission on the system. If this setting is changed from "No" to "Yes" after students have already submitted those submissions will be regarded as final.';
|
||||
$string['submissioneditable'] = 'Student can edit this submission';
|
||||
$string['submissionnotcopiedinvalidstatus'] = 'The submission was not copied because it has been edited since it was reopened.';
|
||||
$string['submissionnoteditable'] = 'Student cannot edit this submission';
|
||||
$string['submissionnotready'] = 'This assignment is not ready to submit:';
|
||||
$string['submissionplugins'] = 'Submission plugins';
|
||||
@ -282,13 +319,15 @@ $string['submissionstatus_draft'] = 'Draft (not submitted)';
|
||||
$string['submissionstatusheading'] = 'Submission status';
|
||||
$string['submissionstatus_marked'] = 'Graded';
|
||||
$string['submissionstatus_new'] = 'New submission';
|
||||
$string['submissionstatus_reopened'] = 'Reopened';
|
||||
$string['submissionstatus_'] = 'No submission';
|
||||
$string['submissionstatus'] = 'Submission status';
|
||||
$string['submissionstatus_submitted'] = 'Submitted for grading';
|
||||
$string['submissionsummary'] = '{$a->status}. Last modified on {$a->timemodified}';
|
||||
$string['submissionteam'] = 'Group';
|
||||
$string['submission'] = 'Submission';
|
||||
$string['submitaction'] = 'Submit';
|
||||
$string['submitassignment_help'] = 'Once this assignment is submitted you will not be able to make any more changes';
|
||||
$string['submitassignment_help'] = 'Once this assignment is submitted you will not be able to make any more changes.';
|
||||
$string['submitassignment'] = 'Submit assignment';
|
||||
$string['submittedearly'] = 'Assignment was submitted {$a} early';
|
||||
$string['submittedlate'] = 'Assignment was submitted {$a} late';
|
||||
@ -304,6 +343,8 @@ $string['timemodified'] = 'Last modified';
|
||||
$string['timeremaining'] = 'Time remaining';
|
||||
$string['unlocksubmissionforstudent'] = 'Allow submissions for student: (id={$a->id}, fullname={$a->fullname}).';
|
||||
$string['unlocksubmissions'] = 'Unlock submissions';
|
||||
$string['unlimitedattempts'] = 'Unlimited';
|
||||
$string['unlimitedattemptsallowed'] = 'Unlimited attempts allowed.';
|
||||
$string['updategrade'] = 'Update grade';
|
||||
$string['updatetable'] = 'Save and update table';
|
||||
$string['upgradenotimplemented'] = 'Upgrade not implemented in plugin ({$a->type} {$a->subtype})';
|
||||
|
@ -150,20 +150,33 @@ function assign_update_instance(stdClass $data, $form) {
|
||||
*/
|
||||
function assign_supports($feature) {
|
||||
switch($feature) {
|
||||
case FEATURE_GROUPS: return true;
|
||||
case FEATURE_GROUPINGS: return true;
|
||||
case FEATURE_GROUPMEMBERSONLY: return true;
|
||||
case FEATURE_MOD_INTRO: return true;
|
||||
case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
|
||||
case FEATURE_COMPLETION_HAS_RULES: return true;
|
||||
case FEATURE_GRADE_HAS_GRADE: return true;
|
||||
case FEATURE_GRADE_OUTCOMES: return true;
|
||||
case FEATURE_BACKUP_MOODLE2: return true;
|
||||
case FEATURE_SHOW_DESCRIPTION: return true;
|
||||
case FEATURE_ADVANCED_GRADING: return true;
|
||||
case FEATURE_PLAGIARISM: return true;
|
||||
case FEATURE_GROUPS:
|
||||
return true;
|
||||
case FEATURE_GROUPINGS:
|
||||
return true;
|
||||
case FEATURE_GROUPMEMBERSONLY:
|
||||
return true;
|
||||
case FEATURE_MOD_INTRO:
|
||||
return true;
|
||||
case FEATURE_COMPLETION_TRACKS_VIEWS:
|
||||
return true;
|
||||
case FEATURE_COMPLETION_HAS_RULES:
|
||||
return true;
|
||||
case FEATURE_GRADE_HAS_GRADE:
|
||||
return true;
|
||||
case FEATURE_GRADE_OUTCOMES:
|
||||
return true;
|
||||
case FEATURE_BACKUP_MOODLE2:
|
||||
return true;
|
||||
case FEATURE_SHOW_DESCRIPTION:
|
||||
return true;
|
||||
case FEATURE_ADVANCED_GRADING:
|
||||
return true;
|
||||
case FEATURE_PLAGIARISM:
|
||||
return true;
|
||||
|
||||
default: return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -118,6 +118,22 @@ class mod_assign_mod_form extends moodleform_mod {
|
||||
$mform->addElement('hidden', 'requiresubmissionstatement', 1);
|
||||
}
|
||||
|
||||
$options = array(
|
||||
ASSIGN_ATTEMPT_REOPEN_METHOD_NONE => get_string('attemptreopenmethod_none', 'mod_assign'),
|
||||
ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL => get_string('attemptreopenmethod_manual', 'mod_assign'),
|
||||
ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS => get_string('attemptreopenmethod_untilpass', 'mod_assign')
|
||||
);
|
||||
$mform->addElement('select', 'attemptreopenmethod', get_string('attemptreopenmethod', 'mod_assign'), $options);
|
||||
$mform->setDefault('attemptreopenmethod', ASSIGN_ATTEMPT_REOPEN_METHOD_NONE);
|
||||
$mform->addHelpButton('attemptreopenmethod', 'attemptreopenmethod', 'mod_assign');
|
||||
|
||||
$options = array(ASSIGN_UNLIMITED_ATTEMPTS => get_string('unlimitedattempts', 'mod_assign'));
|
||||
$options += array_combine(range(1, 30), range(1, 30));
|
||||
$mform->addElement('select', 'maxattempts', get_string('maxattempts', 'mod_assign'), $options);
|
||||
$mform->addHelpButton('maxattempts', 'maxattempts', 'assign');
|
||||
$mform->setDefault('maxattempts', -1);
|
||||
$mform->disabledIf('maxattempts', 'attemptreopenmethod', 'eq', ASSIGN_ATTEMPT_REOPEN_METHOD_NONE);
|
||||
|
||||
$mform->addElement('header', 'groupsubmissionsettings', get_string('groupsubmissionsettings', 'assign'));
|
||||
|
||||
$name = get_string('teamsubmission', 'assign');
|
||||
|
@ -5,7 +5,7 @@ M.mod_assign.init_tree = function(Y, expand_all, htmlid) {
|
||||
var tree = new Y.YUI2.widget.TreeView(htmlid);
|
||||
|
||||
tree.subscribe("clickEvent", function(node, event) {
|
||||
// we want normal clicking which redirects to url
|
||||
// We want normal clicking which redirects to url.
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -169,12 +169,12 @@ M.mod_assign.init_plugin_summary = function(Y, subtype, type, submissionid) {
|
||||
fullclassname = 'full_' + thissuffix;
|
||||
full = Y.one('.' + fullclassname);
|
||||
if (full) {
|
||||
full.hide(true);
|
||||
full.hide(false);
|
||||
}
|
||||
summaryclassname = 'summary_' + thissuffix;
|
||||
summary = Y.one('.' + summaryclassname);
|
||||
if (summary) {
|
||||
summary.show(true);
|
||||
summary.show(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -183,7 +183,7 @@ M.mod_assign.init_plugin_summary = function(Y, subtype, type, submissionid) {
|
||||
|
||||
full = Y.one('.full_' + suffix);
|
||||
if (full) {
|
||||
full.hide();
|
||||
full.hide(false);
|
||||
full.toggleClass('hidefull');
|
||||
}
|
||||
if (expand) {
|
||||
@ -199,12 +199,12 @@ M.mod_assign.init_plugin_summary = function(Y, subtype, type, submissionid) {
|
||||
summaryclassname = 'summary_' + thissuffix;
|
||||
summary = Y.one('.' + summaryclassname);
|
||||
if (summary) {
|
||||
summary.hide(true);
|
||||
summary.hide(false);
|
||||
}
|
||||
fullclassname = 'full_' + thissuffix;
|
||||
full = Y.one('.' + fullclassname);
|
||||
if (full) {
|
||||
full.show(true);
|
||||
full.show(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -52,12 +52,14 @@ class assign_submit_for_grading_page implements renderable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a renderable grading error notification
|
||||
* Implements a renderable message notification
|
||||
* @package mod_assign
|
||||
* @copyright 2012 NetSpot {@link http://www.netspot.com.au}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class assign_quickgrading_result implements renderable {
|
||||
class assign_gradingmessage implements renderable {
|
||||
/** @var string $heading is the heading to display to the user */
|
||||
public $heading = '';
|
||||
/** @var string $message is the message to display to the user */
|
||||
public $message = '';
|
||||
/** @var int $coursemoduleid */
|
||||
@ -65,9 +67,11 @@ class assign_quickgrading_result implements renderable {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param string $heading This is the heading to display
|
||||
* @param string $message This is the message to display
|
||||
*/
|
||||
public function __construct($message, $coursemoduleid) {
|
||||
public function __construct($heading, $message, $coursemoduleid) {
|
||||
$this->heading = $heading;
|
||||
$this->message = $message;
|
||||
$this->coursemoduleid = $coursemoduleid;
|
||||
}
|
||||
@ -363,6 +367,10 @@ class assign_submission_status implements renderable {
|
||||
public $blindmarking = false;
|
||||
/** @var string gradingcontrollerpreview */
|
||||
public $gradingcontrollerpreview = '';
|
||||
/** @var string attemptreopenmethod */
|
||||
public $attemptreopenmethod = 'none';
|
||||
/** @var int maxattempts */
|
||||
public $maxattempts = -1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -390,7 +398,9 @@ class assign_submission_status implements renderable {
|
||||
* @param bool $canviewfullnames
|
||||
* @param int $extensionduedate - Any extension to the due date granted for this user
|
||||
* @param context $context - Any extension to the due date granted for this user
|
||||
* @param blindmarking $blindmarking - Should we hide student identities from graders?
|
||||
* @param bool $blindmarking - Should we hide student identities from graders?
|
||||
* @param string $attemptreopenmethod - The method of reopening student attempts.
|
||||
* @param int $maxattempts - How many attempts can a student make?
|
||||
*/
|
||||
public function __construct($allowsubmissionsfromdate,
|
||||
$alwaysshowdescription,
|
||||
@ -416,7 +426,9 @@ class assign_submission_status implements renderable {
|
||||
$extensionduedate,
|
||||
$context,
|
||||
$blindmarking,
|
||||
$gradingcontrollerpreview) {
|
||||
$gradingcontrollerpreview,
|
||||
$attemptreopenmethod,
|
||||
$maxattempts) {
|
||||
$this->allowsubmissionsfromdate = $allowsubmissionsfromdate;
|
||||
$this->alwaysshowdescription = $alwaysshowdescription;
|
||||
$this->submission = $submission;
|
||||
@ -442,8 +454,66 @@ class assign_submission_status implements renderable {
|
||||
$this->context = $context;
|
||||
$this->blindmarking = $blindmarking;
|
||||
$this->gradingcontrollerpreview = $gradingcontrollerpreview;
|
||||
$this->attemptreopenmethod = $attemptreopenmethod;
|
||||
$this->maxattempts = $maxattempts;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to output the attempt history for a particular assignment.
|
||||
*
|
||||
* @package mod_assign
|
||||
* @copyright 2012 Davo Smith, Synergy Learning
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class assign_attempt_history implements renderable {
|
||||
|
||||
/** @var array submissions */
|
||||
public $submissions = array();
|
||||
/** @var array grades */
|
||||
public $grades = array();
|
||||
/** @var array submissionplugins */
|
||||
public $submissionplugins = array();
|
||||
/** @var array feedbackplugins */
|
||||
public $feedbackplugins = array();
|
||||
/** @var int coursemoduleid */
|
||||
public $coursemoduleid = 0;
|
||||
/** @var string returnaction */
|
||||
public $returnaction = '';
|
||||
/** @var string returnparams */
|
||||
public $returnparams = array();
|
||||
/** @var bool cangrade */
|
||||
public $cangrade = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param $submissions
|
||||
* @param $grades
|
||||
* @param $submissionplugins
|
||||
* @param $feedbackplugins
|
||||
* @param $coursemoduleid
|
||||
* @param $returnaction
|
||||
* @param $returnparams
|
||||
* @param $cangrade
|
||||
*/
|
||||
public function __construct($submissions,
|
||||
$grades,
|
||||
$submissionplugins,
|
||||
$feedbackplugins,
|
||||
$coursemoduleid,
|
||||
$returnaction,
|
||||
$returnparams,
|
||||
$cangrade) {
|
||||
$this->submissions = $submissions;
|
||||
$this->grades = $grades;
|
||||
$this->submissionplugins = $submissionplugins;
|
||||
$this->feedbackplugins = $feedbackplugins;
|
||||
$this->coursemoduleid = $coursemoduleid;
|
||||
$this->returnaction = $returnaction;
|
||||
$this->returnparams = $returnparams;
|
||||
$this->cangrade = $cangrade;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,16 +85,16 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a grading error notification
|
||||
* @param assign_quickgrading_result $result The result to render
|
||||
* Render a grading message notification
|
||||
* @param assign_gradingmessage $result The result to render
|
||||
* @return string
|
||||
*/
|
||||
public function render_assign_quickgrading_result(assign_quickgrading_result $result) {
|
||||
public function render_assign_gradingmessage(assign_gradingmessage $result) {
|
||||
$urlparams = array('id' => $result->coursemoduleid, 'action'=>'grading');
|
||||
$url = new moodle_url('/mod/assign/view.php', $urlparams);
|
||||
|
||||
$o = '';
|
||||
$o .= $this->output->heading(get_string('quickgradingresult', 'assign'), 4);
|
||||
$o .= $this->output->heading($result->heading, 4);
|
||||
$o .= $this->output->notification($result->message);
|
||||
$o .= $this->output->continue_button($url);
|
||||
return $o;
|
||||
@ -179,7 +179,9 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
$o .= $this->output->continue_button($cancelurl);
|
||||
} else {
|
||||
// All submission plugins ready - show the confirmation form.
|
||||
$o .= $this->output->box_start('generalbox submitconfirm');
|
||||
$o .= $this->moodleform($page->confirmform);
|
||||
$o .= $this->output->box_end();
|
||||
}
|
||||
$o .= $this->output->container_end();
|
||||
|
||||
@ -426,6 +428,32 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
$t->data[] = $row;
|
||||
}
|
||||
|
||||
if ($status->attemptreopenmethod != ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) {
|
||||
$currentattempt = 1;
|
||||
if (!$status->teamsubmissionenabled) {
|
||||
if ($status->submission) {
|
||||
$currentattempt = $status->submission->attemptnumber + 1;
|
||||
}
|
||||
} else {
|
||||
if ($status->teamsubmission) {
|
||||
$currentattempt = $status->teamsubmission->attemptnumber + 1;
|
||||
}
|
||||
}
|
||||
|
||||
$row = new html_table_row();
|
||||
$cell1 = new html_table_cell(get_string('attemptnumber', 'assign'));
|
||||
$maxattempts = $status->maxattempts;
|
||||
if ($maxattempts == ASSIGN_UNLIMITED_ATTEMPTS) {
|
||||
$message = get_string('currentattempt', 'assign', $currentattempt);
|
||||
} else {
|
||||
$message = get_string('currentattemptof', 'assign', array('attemptnumber'=>$currentattempt,
|
||||
'maxattempts'=>$maxattempts));
|
||||
}
|
||||
$cell2 = new html_table_cell($message);
|
||||
$row->cells = array($cell1, $cell2);
|
||||
$t->data[] = $row;
|
||||
}
|
||||
|
||||
$row = new html_table_row();
|
||||
$cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
|
||||
if (!$status->teamsubmissionenabled) {
|
||||
@ -437,7 +465,7 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
if (!$status->submissionsenabled) {
|
||||
$cell2 = new html_table_cell(get_string('noonlinesubmissions', 'assign'));
|
||||
} else {
|
||||
$cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
|
||||
$cell2 = new html_table_cell(get_string('noattempt', 'assign'));
|
||||
}
|
||||
}
|
||||
$row->cells = array($cell1, $cell2);
|
||||
@ -637,23 +665,52 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
if ($status->view == assign_submission_status::STUDENT_VIEW) {
|
||||
if ($status->canedit) {
|
||||
if (!$submission) {
|
||||
$o .= $this->output->box_start('generalbox submissionaction');
|
||||
$urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
|
||||
$o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
|
||||
get_string('addsubmission', 'assign'), 'get');
|
||||
$o .= $this->output->box_start('boxaligncenter submithelp');
|
||||
$o .= get_string('editsubmission_help', 'assign');
|
||||
$o .= $this->output->box_end();
|
||||
$o .= $this->output->box_end();
|
||||
} else if ($submission->status == ASSIGN_SUBMISSION_STATUS_REOPENED) {
|
||||
$o .= $this->output->box_start('generalbox submissionaction');
|
||||
$urlparams = array('id' => $status->coursemoduleid, 'action' => 'editprevioussubmission');
|
||||
$o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
|
||||
get_string('addnewattemptfromprevious', 'assign'), 'get');
|
||||
$o .= $this->output->box_start('boxaligncenter submithelp');
|
||||
$o .= get_string('addnewattemptfromprevious_help', 'assign');
|
||||
$o .= $this->output->box_end();
|
||||
$o .= $this->output->box_end();
|
||||
$o .= $this->output->box_start('generalbox submissionaction');
|
||||
$urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
|
||||
$o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
|
||||
get_string('addnewattempt', 'assign'), 'get');
|
||||
$o .= $this->output->box_start('boxaligncenter submithelp');
|
||||
$o .= get_string('addnewattempt_help', 'assign');
|
||||
$o .= $this->output->box_end();
|
||||
$o .= $this->output->box_end();
|
||||
} else {
|
||||
$o .= $this->output->box_start('generalbox submissionaction');
|
||||
$urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
|
||||
$o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
|
||||
get_string('editsubmission', 'assign'), 'get');
|
||||
$o .= $this->output->box_start('boxaligncenter submithelp');
|
||||
$o .= get_string('editsubmission_help', 'assign');
|
||||
$o .= $this->output->box_end();
|
||||
$o .= $this->output->box_end();
|
||||
}
|
||||
}
|
||||
|
||||
if ($status->cansubmit) {
|
||||
$urlparams = array('id' => $status->coursemoduleid, 'action'=>'submit');
|
||||
$o .= $this->output->box_start('generalbox submissionaction');
|
||||
$o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
|
||||
get_string('submitassignment', 'assign'), 'get');
|
||||
$o .= $this->output->box_start('boxaligncenter submithelp');
|
||||
$o .= get_string('submitassignment_help', 'assign');
|
||||
$o .= $this->output->box_end();
|
||||
$o .= $this->output->box_end();
|
||||
}
|
||||
}
|
||||
|
||||
@ -661,6 +718,154 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the attempt history for this assignment
|
||||
*
|
||||
* @param assign_attempt_history $history
|
||||
* @return string
|
||||
*/
|
||||
public function render_assign_attempt_history(assign_attempt_history $history) {
|
||||
$o = '';
|
||||
|
||||
$submittedstr = get_string('submitted', 'assign');
|
||||
$gradestr = get_string('grade');
|
||||
$gradedonstr = get_string('gradedon', 'assign');
|
||||
$gradedbystr = get_string('gradedby', 'assign');
|
||||
|
||||
// Don't show the last one because it is the current submission.
|
||||
array_pop($history->submissions);
|
||||
|
||||
// Show newest to oldest.
|
||||
$history->submissions = array_reverse($history->submissions);
|
||||
|
||||
if (empty($history->submissions)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$containerid = 'attempthistory' . uniqid();
|
||||
$o .= $this->heading(get_string('attempthistory', 'assign'), 3);
|
||||
$o .= $this->box_start('attempthistory', $containerid);
|
||||
|
||||
foreach ($history->submissions as $i => $submission) {
|
||||
$grade = null;
|
||||
foreach ($history->grades as $onegrade) {
|
||||
if ($onegrade->attemptnumber == $submission->attemptnumber) {
|
||||
$grade = $onegrade;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$editbtn = '';
|
||||
|
||||
if ($submission) {
|
||||
$submissionsummary = userdate($submission->timemodified);
|
||||
} else {
|
||||
$submissionsummary = get_string('nosubmission', 'assign');
|
||||
}
|
||||
|
||||
$attemptsummaryparams = array('attemptnumber'=>$submission->attemptnumber+1,
|
||||
'submissionsummary'=>$submissionsummary);
|
||||
$o .= $this->heading(get_string('attemptheading', 'assign', $attemptsummaryparams), 4);
|
||||
|
||||
$t = new html_table();
|
||||
|
||||
if ($submission) {
|
||||
$cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
|
||||
$cell2 = new html_table_cell(get_string('submissionstatus_' . $submission->status, 'assign'));
|
||||
$t->data[] = new html_table_row(array($cell1, $cell2));
|
||||
|
||||
foreach ($history->submissionplugins as $plugin) {
|
||||
$pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
|
||||
if ($plugin->is_enabled() &&
|
||||
$plugin->is_visible() &&
|
||||
$plugin->has_user_summary() &&
|
||||
$pluginshowsummary) {
|
||||
|
||||
$cell1 = new html_table_cell($plugin->get_name());
|
||||
$pluginsubmission = new assign_submission_plugin_submission($plugin,
|
||||
$submission,
|
||||
assign_submission_plugin_submission::SUMMARY,
|
||||
$history->coursemoduleid,
|
||||
$history->returnaction,
|
||||
$history->returnparams);
|
||||
$cell2 = new html_table_cell($this->render($pluginsubmission));
|
||||
|
||||
$t->data[] = new html_table_row(array($cell1, $cell2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($grade) {
|
||||
// Heading 'feedback'.
|
||||
$title = get_string('feedback', 'assign', $i);
|
||||
$title .= $this->output->spacer(array('width'=>10));
|
||||
if ($history->cangrade) {
|
||||
// Edit previous feedback.
|
||||
$returnparams = http_build_query($history->returnparams);
|
||||
$urlparams = array('id' => $history->coursemoduleid,
|
||||
'userid'=>$grade->userid,
|
||||
'attemptnumber'=>$grade->attemptnumber,
|
||||
'action'=>'grade',
|
||||
'rownum'=>0,
|
||||
'returnaction'=>$history->returnaction,
|
||||
'returnparams'=>$returnparams);
|
||||
$url = new moodle_url('/mod/assign/view.php', $urlparams);
|
||||
$icon = new pix_icon('gradefeedback',
|
||||
get_string('editattemptfeedback', 'assign', $grade->attemptnumber+1),
|
||||
'mod_assign');
|
||||
$title .= $this->output->action_icon($url, $icon);
|
||||
}
|
||||
$cell = new html_table_cell($title);
|
||||
$cell->attributes['class'] = 'feedbacktitle';
|
||||
$cell->colspan = 2;
|
||||
$t->data[] = new html_table_row(array($cell));
|
||||
|
||||
// Grade.
|
||||
$cell1 = new html_table_cell($gradestr);
|
||||
$cell2 = $grade->gradefordisplay;
|
||||
$t->data[] = new html_table_row(array($cell1, $cell2));
|
||||
|
||||
// Graded on.
|
||||
$cell1 = new html_table_cell($gradedonstr);
|
||||
$cell2 = new html_table_cell(userdate($grade->timemodified));
|
||||
$t->data[] = new html_table_row(array($cell1, $cell2));
|
||||
|
||||
// Graded by.
|
||||
$cell1 = new html_table_cell($gradedbystr);
|
||||
$cell2 = new html_table_cell($this->output->user_picture($grade->grader) .
|
||||
$this->output->spacer(array('width'=>30)) . fullname($grade->grader));
|
||||
$t->data[] = new html_table_row(array($cell1, $cell2));
|
||||
|
||||
// Feedback from plugins.
|
||||
foreach ($history->feedbackplugins as $plugin) {
|
||||
if ($plugin->is_enabled() &&
|
||||
$plugin->is_visible() &&
|
||||
$plugin->has_user_summary() &&
|
||||
!$plugin->is_empty($grade)) {
|
||||
|
||||
$cell1 = new html_table_cell($plugin->get_name());
|
||||
$pluginfeedback = new assign_feedback_plugin_feedback(
|
||||
$plugin, $grade, assign_feedback_plugin_feedback::SUMMARY, $history->coursemoduleid,
|
||||
$history->returnaction, $history->returnparams
|
||||
);
|
||||
$cell2 = new html_table_cell($this->render($pluginfeedback));
|
||||
$t->data[] = new html_table_row(array($cell1, $cell2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$o .= html_writer::table($t);
|
||||
}
|
||||
$o .= $this->box_end();
|
||||
$jsparams = array($containerid);
|
||||
|
||||
$this->page->requires->yui_module('moodle-mod_assign-history', 'Y.one("#' . $containerid . '").history');
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a submission plugin submission
|
||||
*
|
||||
@ -751,6 +956,7 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
$this->page->requires->string_for_js('batchoperationconfirmlock', 'assign');
|
||||
$this->page->requires->string_for_js('batchoperationconfirmreverttodraft', 'assign');
|
||||
$this->page->requires->string_for_js('batchoperationconfirmunlock', 'assign');
|
||||
$this->page->requires->string_for_js('batchoperationconfirmaddattempt', 'assign');
|
||||
$this->page->requires->string_for_js('editaction', 'assign');
|
||||
foreach ($table->plugingradingbatchoperations as $plugin => $operations) {
|
||||
foreach ($operations as $operation => $description) {
|
||||
|
@ -17,6 +17,8 @@ div.gradingsummary {
|
||||
div.submissionstatus .generaltable,
|
||||
div.submissionlinks .generaltable,
|
||||
div.feedback .generaltable,
|
||||
div.submissionsummarytable .generaltable,
|
||||
div.attempthistory table,
|
||||
div.gradingsummary .generaltable {
|
||||
width: 100%;
|
||||
}
|
||||
@ -30,7 +32,6 @@ div.gradingsummary .generaltable {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
|
||||
div.submissionsummarytable table tbody tr td.c0 {
|
||||
width: 30%;
|
||||
}
|
||||
@ -73,6 +74,12 @@ div.submissionlocked {
|
||||
background-color: #efefcf;
|
||||
}
|
||||
|
||||
td.submissionreopened,
|
||||
div.submissionreopened {
|
||||
color: black;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
td.submissiongraded,
|
||||
div.submissiongraded {
|
||||
color: black;
|
||||
@ -160,3 +167,90 @@ td.submissioneditable {
|
||||
.jsenabled .quickgradingform form .commentscontainer textarea {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .previousfeedbackwarning {
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #500;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submissionhistory {
|
||||
background-color: #b0b0b0;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submissionhistory .cell.historytitle {
|
||||
background-color: #808080;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submissionhistory .cell {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submissionhistory .singlebutton {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
}
|
||||
|
||||
#page-mod-assign-view.dir-rtl .submissionhistory .singlebutton {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submissionsummarytable .singlebutton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.jsenabled .mod-assign-history-link {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.jsenabled .mod-assign-history-link h4 {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#page-mod-assign-view.jsenabled .attempthistory h4 {
|
||||
margin-bottom: 7px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#page-mod-assign-view.jsenabled.dir_rtl .attempthistory h4 {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dir-rtl.jsenabled .mod-assign-history-link h4 {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.jsenabled .mod-assign-history-link-open {
|
||||
padding: 0 5px 0 20px; background: url([[pix:t/expanded]]) 2px center no-repeat;
|
||||
}
|
||||
|
||||
.jsenabled .mod-assign-history-link-closed {
|
||||
padding: 0 5px 0 20px; background: url([[pix:t/collapsed]]) 2px center no-repeat;
|
||||
}
|
||||
|
||||
.dir-rtl.jsenabled .mod-assign-history-link-closed {
|
||||
padding: 0 20px 0 5px; background: url([[pix:t/collapsed_rtl]]) 2px center no-repeat;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submithelp {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .feedbacktitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#page-mod-assign-view .submitconfirm,
|
||||
#page-mod-assign-view .submissionlinks,
|
||||
#page-mod-assign-view .submissionaction {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
#page-mod-assign-view .submissionsummarytable .c0,
|
||||
#page-mod-assign-view .mod-assign-history-panel .c0 {
|
||||
width: 150px;
|
||||
}
|
||||
|
@ -449,4 +449,35 @@ class assign_submission_file extends assign_submission_plugin {
|
||||
return array(ASSIGNSUBMISSION_FILE_FILEAREA=>$this->get_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the student's submission from a previous submission. Used when a student opts to base their resubmission
|
||||
* on the last submission.
|
||||
* @param stdClass $sourcesubmission
|
||||
* @param stdClass $destsubmission
|
||||
*/
|
||||
public function copy_submission(stdClass $sourcesubmission, stdClass $destsubmission) {
|
||||
global $DB;
|
||||
|
||||
// Copy the files across.
|
||||
$contextid = $this->assignment->get_context()->id;
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($contextid,
|
||||
'assignsubmission_file',
|
||||
ASSIGNSUBMISSION_FILE_FILEAREA,
|
||||
$sourcesubmission->id,
|
||||
'id',
|
||||
false);
|
||||
foreach ($files as $file) {
|
||||
$fieldupdates = array('itemid' => $destsubmission->id);
|
||||
$fs->create_file_from_storedfile($fieldupdates, $file);
|
||||
}
|
||||
|
||||
// Copy the assignsubmission_file record.
|
||||
if ($filesubmission = $this->get_file_submission($sourcesubmission->id)) {
|
||||
unset($filesubmission->id);
|
||||
$filesubmission->submission = $destsubmission->id;
|
||||
$DB->insert_record('assignsubmission_file', $filesubmission);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -470,6 +470,34 @@ class assign_submission_onlinetext extends assign_submission_plugin {
|
||||
return array(ASSIGNSUBMISSION_ONLINETEXT_FILEAREA=>$this->get_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the student's submission from a previous submission. Used when a student opts to base their resubmission
|
||||
* on the last submission.
|
||||
* @param stdClass $sourcesubmission
|
||||
* @param stdClass $destsubmission
|
||||
*/
|
||||
public function copy_submission(stdClass $sourcesubmission, stdClass $destsubmission) {
|
||||
global $DB;
|
||||
|
||||
// Copy the files across (attached via the text editor).
|
||||
$contextid = $this->assignment->get_context()->id;
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($contextid, 'assignsubmission_onlinetext',
|
||||
ASSIGNSUBMISSION_ONLINETEXT_FILEAREA, $sourcesubmission->id, 'id', false);
|
||||
foreach ($files as $file) {
|
||||
$fieldupdates = array('itemid' => $destsubmission->id);
|
||||
$fs->create_file_from_storedfile($fieldupdates, $file);
|
||||
}
|
||||
|
||||
// Copy the assignsubmission_onlinetext record.
|
||||
$onlinetextsubmission = $this->get_onlinetext_submission($sourcesubmission->id);
|
||||
if ($onlinetextsubmission) {
|
||||
unset($onlinetextsubmission->id);
|
||||
$onlinetextsubmission->submission = $destsubmission->id;
|
||||
$DB->insert_record('assignsubmission_onlinetext', $onlinetextsubmission);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,18 +60,28 @@ abstract class assign_submission_plugin extends assign_plugin {
|
||||
/**
|
||||
* Check if the submission plugin has all the required data to allow the work
|
||||
* to be submitted for grading
|
||||
* @param stdClass $submission the assign_submission record being submitted.
|
||||
* @return bool|string 'true' if OK to proceed with submission, otherwise a
|
||||
* a message to display to the user
|
||||
*/
|
||||
public function precheck_submission() {
|
||||
public function precheck_submission($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Carry out any extra processing required when the work is submitted for grading
|
||||
* @param stdClass $submission the assign_submission record being submitted.
|
||||
* @return void
|
||||
*/
|
||||
public function submit_for_grading() {
|
||||
public function submit_for_grading($submission) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the plugin specific submission data to a new submission record.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copy_submission( stdClass $oldsubmission, stdClass $submission) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class mod_assign_base_testcase extends advanced_testcase {
|
||||
/*
|
||||
* For tests that make sense to use alot of data, create extra students/teachers.
|
||||
*/
|
||||
protected function createExtraUsers() {
|
||||
protected function create_extra_users() {
|
||||
global $DB;
|
||||
$this->extrateachers = array();
|
||||
for ($i = 0; $i < self::EXTRA_TEACHER_COUNT; $i++) {
|
||||
@ -217,8 +217,8 @@ class testable_assign extends assign {
|
||||
return parent::delete_grades();
|
||||
}
|
||||
|
||||
public function testable_apply_grade_to_user($formdata, $userid) {
|
||||
return parent::apply_grade_to_user($formdata, $userid);
|
||||
public function testable_apply_grade_to_user($formdata, $userid, $attemptnumber) {
|
||||
return parent::apply_grade_to_user($formdata, $userid, $attemptnumber);
|
||||
}
|
||||
|
||||
public function testable_get_grading_userid_list() {
|
||||
@ -233,6 +233,10 @@ class testable_assign extends assign {
|
||||
return parent::update_submission($submission, $userid, $updatetime, $teamsubmission);
|
||||
}
|
||||
|
||||
public function testable_process_add_attempt($userid = 0) {
|
||||
return parent::process_add_attempt($userid);
|
||||
}
|
||||
|
||||
public function testable_submissions_open($userid = 0) {
|
||||
return parent::submissions_open($userid);
|
||||
}
|
||||
|
@ -75,8 +75,18 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
|
||||
$user_enrolment_data['userid'] = $USER->id;
|
||||
$DB->insert_record('user_enrolments', $user_enrolment_data);
|
||||
|
||||
// Create a student and give them a grade.
|
||||
// Create a student and give them 2 grades (for 2 attempts).
|
||||
$student = self::getDataGenerator()->create_user();
|
||||
$grade = new stdClass();
|
||||
$grade->assignment = $assign->id;
|
||||
$grade->userid = $student->id;
|
||||
$grade->timecreated = time();
|
||||
$grade->timemodified = $grade->timecreated;
|
||||
$grade->grader = $USER->id;
|
||||
$grade->grade = 50;
|
||||
$grade->attemptnumber = 0;
|
||||
$DB->insert_record('assign_grades', $grade);
|
||||
|
||||
$grade = new stdClass();
|
||||
$grade->assignment = $assign->id;
|
||||
$grade->userid = $student->id;
|
||||
@ -84,8 +94,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
|
||||
$grade->timemodified = $grade->timecreated;
|
||||
$grade->grader = $USER->id;
|
||||
$grade->grade = 75;
|
||||
$grade->locked = false;
|
||||
$grade->mailed = true;
|
||||
$grade->attemptnumber = 1;
|
||||
$DB->insert_record('assign_grades', $grade);
|
||||
|
||||
$assignmentids[] = $assign->id;
|
||||
@ -98,9 +107,11 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
|
||||
$this->assertEquals(1, count($result['assignments']));
|
||||
$assignment = $result['assignments'][0];
|
||||
$this->assertEquals($assign->id, $assignment['assignmentid']);
|
||||
// Should only get the last grade for this student.
|
||||
$this->assertEquals(1, count($assignment['grades']));
|
||||
$grade = $assignment['grades'][0];
|
||||
$this->assertEquals($student->id, $grade['userid']);
|
||||
// Should be the last grade (not the first)
|
||||
$this->assertEquals(75, $grade['grade']);
|
||||
}
|
||||
|
||||
@ -218,13 +229,25 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
|
||||
$assign1 = self::getDataGenerator()->create_module('assign', $assigndata);
|
||||
|
||||
// Create a student with an online text submission.
|
||||
// First attempt.
|
||||
$student = self::getDataGenerator()->create_user();
|
||||
$submission = new stdClass();
|
||||
$submission->assignment = $assign1->id;
|
||||
$submission->userid = $student->id;
|
||||
$submission->timecreated = time();
|
||||
$submission->timemodified = $submission->timecreated;
|
||||
$submission->status = 'draft';
|
||||
$submission->attemptnumber = 0;
|
||||
$sid = $DB->insert_record('assign_submission', $submission);
|
||||
|
||||
// Second attempt.
|
||||
$submission = new stdClass();
|
||||
$submission->assignment = $assign1->id;
|
||||
$submission->userid = $student->id;
|
||||
$submission->timecreated = time();
|
||||
$submission->timemodified = $submission->timecreated;
|
||||
$submission->status = 'submitted';
|
||||
$submission->attemptnumber = 1;
|
||||
$sid = $DB->insert_record('assign_submission', $submission);
|
||||
$submission->id = $sid;
|
||||
|
||||
|
@ -63,7 +63,9 @@ class mod_assign_generator extends testing_module_generator {
|
||||
'requireallteammemberssubmit' => 0,
|
||||
'teamsubmissiongroupingid' => 0,
|
||||
'blindmarking' => 0,
|
||||
'cmidnumber' => ''
|
||||
'cmidnumber' => '',
|
||||
'attemptreopenmethod' => 'none',
|
||||
'maxattempts' => -1
|
||||
);
|
||||
|
||||
foreach ($defaultsettings as $name => $value) {
|
||||
|
@ -137,4 +137,3 @@ class mod_assign_lib_testcase extends mod_assign_base_testcase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,6 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$assign->testable_process_reveal_identities();
|
||||
|
||||
// Test sesskey is required.
|
||||
$nosesskey = true;
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$this->setExpectedException('moodle_exception');
|
||||
$assign->testable_process_reveal_identities();
|
||||
@ -165,7 +164,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
// Now see if the data is in the gradebook.
|
||||
$gradinginfo = grade_get_grades($this->course->id,
|
||||
@ -192,7 +191,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
// Simulate a submission.
|
||||
$this->setUser($this->students[0]);
|
||||
@ -220,7 +219,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
// Simulate a submission.
|
||||
$this->setUser($this->students[0]);
|
||||
@ -286,11 +285,6 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$instance->duedate = $now;
|
||||
$instance->instance = $instance->id;
|
||||
$instance->assignsubmission_onlinetext_enabled = 1;
|
||||
$instance->assignsubmission_file_enabled = 0;
|
||||
$instance->assignsubmission_comments_enabled = 0;
|
||||
$instance->assignfeedback_comments_enabled = 0;
|
||||
$instance->assignfeedback_file_enabled = 0;
|
||||
$instance->assignfeedback_offline_enabled = 0;
|
||||
|
||||
$assign->update_instance($instance);
|
||||
|
||||
@ -299,7 +293,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
}
|
||||
|
||||
public function test_list_participants() {
|
||||
$this->createExtraUsers();
|
||||
$this->create_extra_users();
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance(array('grade'=>100));
|
||||
|
||||
@ -307,7 +301,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
}
|
||||
|
||||
public function test_count_teams() {
|
||||
$this->createExtraUsers();
|
||||
$this->create_extra_users();
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance(array('teamsubmission'=>1));
|
||||
|
||||
@ -315,7 +309,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
}
|
||||
|
||||
public function test_count_submissions() {
|
||||
$this->createExtraUsers();
|
||||
$this->create_extra_users();
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
|
||||
|
||||
@ -334,7 +328,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->extrastudents[0]->id, 0);
|
||||
|
||||
// Simulate a submission.
|
||||
$this->setUser($this->extrastudents[1]);
|
||||
@ -376,7 +370,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->extrastudents[3]->id, 0);
|
||||
|
||||
$this->assertEquals(2, $assign->count_grades());
|
||||
$this->assertEquals(4, $assign->count_submissions());
|
||||
@ -386,7 +380,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
}
|
||||
|
||||
public function test_get_grading_userid_list() {
|
||||
$this->createExtraUsers();
|
||||
$this->create_extra_users();
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance();
|
||||
|
||||
@ -407,7 +401,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
// Now run cron and see that one message was sent.
|
||||
$this->preventResetByRollback();
|
||||
@ -430,7 +424,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
$this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
|
||||
$this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
|
||||
@ -456,7 +450,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
|
||||
|
||||
public function test_update_submission() {
|
||||
$this->createExtraUsers();
|
||||
$this->create_extra_users();
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance();
|
||||
|
||||
@ -564,7 +558,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
}
|
||||
|
||||
public function test_get_graders() {
|
||||
$this->createExtraUsers();
|
||||
$this->create_extra_users();
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance();
|
||||
|
||||
@ -614,7 +608,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id);
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
// Now we should see the feedback.
|
||||
$this->setUser($this->students[0]);
|
||||
@ -656,6 +650,98 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
|
||||
$this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
|
||||
}
|
||||
|
||||
public function test_attempt_reopen_method_manual() {
|
||||
global $PAGE;
|
||||
|
||||
$this->setUser($this->editingteachers[0]);
|
||||
$assign = $this->create_instance(array('attemptreopenmethod'=>ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
|
||||
'maxattempts'=>3,
|
||||
'submissiondrafts'=>1,
|
||||
'assignsubmission_onlinetext_enabled'=>1));
|
||||
$PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
|
||||
|
||||
// Student should be able to see an add submission button.
|
||||
$this->setUser($this->students[0]);
|
||||
$output = $assign->view_student_summary($this->students[0], true);
|
||||
$this->assertNotEquals(false, strpos($output, get_string('addsubmission', 'assign')));
|
||||
|
||||
// Add a submission.
|
||||
$now = time();
|
||||
$submission = $assign->get_user_submission($this->students[0]->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);
|
||||
|
||||
// And now submit it for marking.
|
||||
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
|
||||
$assign->testable_update_submission($submission, $this->students[0]->id, true, false);
|
||||
|
||||
// Verify the student cannot make changes to the submission.
|
||||
$output = $assign->view_student_summary($this->students[0], true);
|
||||
$this->assertEquals(false, strpos($output, get_string('addsubmission', 'assign')));
|
||||
|
||||
// Mark the submission.
|
||||
$this->setUser($this->teachers[0]);
|
||||
$data = new stdClass();
|
||||
$data->grade = '50.0';
|
||||
$assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
|
||||
|
||||
// Check the student can see the grade.
|
||||
$this->setUser($this->students[0]);
|
||||
$output = $assign->view_student_summary($this->students[0], true);
|
||||
$this->assertNotEquals(false, strpos($output, '50.0'));
|
||||
|
||||
// Allow the student another attempt.
|
||||
$this->teachers[0]->ignoresesskey = true;
|
||||
$this->setUser($this->teachers[0]);
|
||||
$result = $assign->testable_process_add_attempt($this->students[0]->id);
|
||||
$this->assertEquals(true, $result);
|
||||
|
||||
// Check that the previous attempt is now in the submission history table.
|
||||
$this->setUser($this->students[0]);
|
||||
$output = $assign->view_student_summary($this->students[0], true);
|
||||
// Need a better check.
|
||||
$this->assertNotEquals(false, strpos($output, 'Submission text'), 'Contains: Submission text');
|
||||
|
||||
// Check that the student now has a button for Add a new attempt".
|
||||
$this->assertNotEquals(false, strpos($output, get_string('addnewattempt', 'assign')));
|
||||
// Check that the student now does not have a button for Submit.
|
||||
$this->assertEquals(false, strpos($output, get_string('submitassignment', 'assign')));
|
||||
|
||||
// Check that the student now has a submission history.
|
||||
$this->assertNotEquals(false, strpos($output, get_string('attempthistory', 'assign')));
|
||||
|
||||
$this->setUser($this->teachers[0]);
|
||||
// Check that the grading table loads correctly and contains this user.
|
||||
// This is also testing that we do not get duplicate rows in the grading table.
|
||||
$gradingtable = new assign_grading_table($assign, 100, '', 0, true);
|
||||
$output = $assign->get_renderer()->render($gradingtable);
|
||||
$this->assertEquals(true, strpos($output, $this->students[0]->lastname));
|
||||
|
||||
// Should be 1 not 2.
|
||||
$this->assertEquals(1, $assign->count_submissions());
|
||||
$this->assertEquals(1, $assign->count_submissions_with_status('reopened'));
|
||||
$this->assertEquals(0, $assign->count_submissions_need_grading());
|
||||
$this->assertEquals(1, $assign->count_grades());
|
||||
|
||||
// Change max attempts to unlimited.
|
||||
$formdata = clone($assign->get_instance());
|
||||
$formdata->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
|
||||
$formdata->instance = $formdata->id;
|
||||
$assign->update_instance($formdata);
|
||||
|
||||
// Check we can repopen still.
|
||||
$result = $assign->testable_process_add_attempt($this->students[0]->id);
|
||||
$this->assertEquals(true, $result);
|
||||
|
||||
$grades = $assign->get_user_grades_for_gradebook($this->students[0]->id);
|
||||
$this->assertEquals(50, (int)$grades[$this->students[0]->id]->rawgrade);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
43
mod/assign/upgrade.txt
Normal file
43
mod/assign/upgrade.txt
Normal file
@ -0,0 +1,43 @@
|
||||
This files describes API changes in the assign code.
|
||||
|
||||
|
||||
=== 2.5 ===
|
||||
|
||||
* New feature - Attempt History
|
||||
|
||||
This adds settings so that a student can have build up a history of separate submission attempts and grades for the same
|
||||
assignment.
|
||||
|
||||
Extra settings on the assign table are:
|
||||
attemptreopenmethod - The way attempts can be reopened. One of:
|
||||
ASSIGN_ATTEMPT_REOPEN_METHOD_NONE - Attempts cannot be reopened (default)
|
||||
ASSIGN_ATTEMPT_REOPEN_METHOD_UNTIL_PASS - Attempts are reopened on grading until the gradebook
|
||||
indicates this student has passed.
|
||||
ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL - Attempts are reopened on manually by the grader.
|
||||
maxattempts - The maximum allowed number of attempts per student for this assign instance.
|
||||
|
||||
Extra settings on the submission and grade records:
|
||||
attemptnumber - Starting from 0 until the latest attempt.
|
||||
|
||||
New table assign_user_flags holds user specific flags that were stored in the assign_grade table. (contains assignment,
|
||||
userid, extensionduedate, mailed and locked)
|
||||
|
||||
assign changes:
|
||||
"get_user_grade" function has an extra optional parameter to retrieve a specific attempt number.
|
||||
"get_user_submission" function has an extra optional parameter to retrieve a specific attempt number.
|
||||
"get_group_submission" function has an extra optional parameter to retrieve a specific attempt number.
|
||||
new "get_user_flags" function can retrieve the user flags for a specific user (extensionduedate, mailed and locked).
|
||||
new "update_user_flags" function can update the user flags for a specific user (extensionduedate, mailed and locked).
|
||||
|
||||
assign_submission_plugin changes:
|
||||
"precheck_submission" function now takes a submission record so you can determine which submission is being checked.
|
||||
"submit_for_grading" function now takes a submission record so you can determine which submission is being submitted.
|
||||
new function "copy_submission" can be implemented to copy submission data from one submission to a new one.
|
||||
|
||||
New renderable object "assign_attempt_history" for rendering the list of previous submissions.
|
||||
New renderable object "assign_gradingmessage" for rendering a generic grading message.
|
||||
|
||||
|
||||
=== Earlier changes ===
|
||||
|
||||
* Were not documented in this way. Sorry.
|
@ -99,6 +99,8 @@ class assign_upgrade_manager {
|
||||
$data->requireallteammemberssubmit = 0;
|
||||
$data->teamsubmissiongroupingid = 0;
|
||||
$data->blindmarking = 0;
|
||||
$data->attemptreopenmethod = 'none';
|
||||
$data->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
|
||||
|
||||
$newassignment = new assign(null, null, null);
|
||||
|
||||
@ -247,7 +249,14 @@ class assign_upgrade_manager {
|
||||
$grade->timemodified = $oldsubmission->timemarked;
|
||||
$grade->timecreated = $oldsubmission->timecreated;
|
||||
$grade->grade = $oldsubmission->grade;
|
||||
$grade->mailed = $oldsubmission->mailed;
|
||||
if ($oldsubmission->mailed) {
|
||||
// The mailed flag goes in the flags table.
|
||||
$flags = new stdClass();
|
||||
$flags->userid = $oldsubmission->userid;
|
||||
$flags->assignment = $newassignment->get_instance()->id;
|
||||
$flags->mailed = 1;
|
||||
$DB->insert_record('assign_user_flags', $flags);
|
||||
}
|
||||
$grade->id = $DB->insert_record('assign_grades', $grade);
|
||||
if (!$grade->id) {
|
||||
$log .= get_string('couldnotinsertgrade', 'mod_assign', $grade->userid);
|
||||
|
@ -25,7 +25,7 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$module->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
|
||||
$module->version = 2012112901; // The current module version (Date: YYYYMMDDXX).
|
||||
$module->version = 2013030600; // The current module version (Date: YYYYMMDDXX).
|
||||
$module->requires = 2012112900; // Requires this Moodle version.
|
||||
$module->cron = 60;
|
||||
|
||||
|
71
mod/assign/yui/history/history.js
vendored
Normal file
71
mod/assign/yui/history/history.js
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
YUI.add('moodle-mod_assign-history', function (Y) {
|
||||
// Define a function that will run in the context of a
|
||||
// Node instance:
|
||||
var CSS = {
|
||||
LINK: 'mod-assign-history-link',
|
||||
OPEN: 'mod-assign-history-link-open',
|
||||
CLOSED: 'mod-assign-history-link-closed',
|
||||
PANEL: 'mod-assign-history-panel'
|
||||
},
|
||||
COUNT = 0,
|
||||
TOGGLE = function() {
|
||||
var id = this.get('for'),
|
||||
panel = Y.one('#' + id);
|
||||
console.log(this);
|
||||
if (this.hasClass(CSS.OPEN)) {
|
||||
this.removeClass(CSS.OPEN);
|
||||
this.addClass(CSS.CLOSED);
|
||||
this.setStyle('overflow', 'hidden');
|
||||
panel.hide();
|
||||
} else {
|
||||
this.removeClass(CSS.CLOSED);
|
||||
this.addClass(CSS.OPEN);
|
||||
panel.show();
|
||||
}
|
||||
},
|
||||
HISTORY = function() {
|
||||
var link = null,
|
||||
panel = null,
|
||||
wrapper = null,
|
||||
container = this;
|
||||
|
||||
// Loop through all the children of this container and turn
|
||||
// every odd node to a link to open/close the following panel.
|
||||
this.get('children').each(function () {
|
||||
if (link) {
|
||||
COUNT++;
|
||||
// First convert the link to an anchor.
|
||||
wrapper = Y.Node.create('<a/>');
|
||||
panel = this;
|
||||
container.insertBefore(wrapper, link);
|
||||
link.remove(false);
|
||||
wrapper.appendChild(link);
|
||||
|
||||
// Add a for attribute to the link to link to the id of the panel.
|
||||
if (!panel.get('id')) {
|
||||
panel.set('id', CSS.PANEL + COUNT);
|
||||
}
|
||||
wrapper.set('for', panel.get('id'));
|
||||
// Add an aria attribute for the live region.
|
||||
panel.set('aria-live', 'polite');
|
||||
|
||||
wrapper.addClass(CSS.LINK);
|
||||
wrapper.addClass(CSS.CLOSED);
|
||||
panel.addClass(CSS.PANEL);
|
||||
panel.hide();
|
||||
link = null;
|
||||
} else {
|
||||
link = this;
|
||||
}
|
||||
});
|
||||
|
||||
// Setup event listeners.
|
||||
this.delegate('click', TOGGLE, '.' + CSS.LINK);
|
||||
};
|
||||
|
||||
// Use addMethod to add history to the Node prototype:
|
||||
Y.Node.addMethod("history", HISTORY);
|
||||
|
||||
// Extend this functionality to NodeLists.
|
||||
Y.NodeList.importMethod(Y.Node.prototype, "history");
|
||||
}, '@VERSION@', { requires: ['node', 'transition'] });
|
Loading…
x
Reference in New Issue
Block a user