Merge branch 'MDL-39959-master' of git://github.com/ankitagarwal/moodle
authorMarina Glancy <marina@moodle.com>
Tue, 17 Sep 2013 01:08:27 +0000 (11:08 +1000)
committerMarina Glancy <marina@moodle.com>
Tue, 17 Sep 2013 01:08:27 +0000 (11:08 +1000)
54 files changed:
admin/tool/uploaduser/user_form.php
grade/import/csv/index.php
grade/import/grade_import_form.php
lang/en/grades.php
lib/db/install.xml
lib/db/upgrade.php
mod/assign/assignmentplugin.php
mod/assign/db/services.php
mod/assign/externallib.php
mod/assign/feedback/comments/backup/moodle2/restore_assignfeedback_comments_subplugin.class.php
mod/assign/feedback/comments/locallib.php
mod/assign/feedback/comments/settings.php
mod/assign/feedback/file/backup/moodle2/restore_assignfeedback_file_subplugin.class.php
mod/assign/feedback/file/locallib.php
mod/assign/feedback/file/settings.php
mod/assign/gradingtable.php
mod/assign/index.php
mod/assign/lib.php
mod/assign/locallib.php
mod/assign/mod_form.php
mod/assign/renderable.php
mod/assign/renderer.php
mod/assign/submission/file/backup/moodle2/restore_assignsubmission_file_subplugin.class.php
mod/assign/submission/file/locallib.php
mod/assign/submission/onlinetext/backup/moodle2/restore_assignsubmission_onlinetext_subplugin.class.php
mod/assign/submission/onlinetext/locallib.php
mod/assign/submissionplugin.php
mod/assign/tests/base_test.php
mod/assign/tests/externallib_test.php
mod/assign/tests/locallib_test.php
mod/assign/upgrade.txt
mod/assign/version.php
mod/book/locallib.php
mod/quiz/styles.css
mod/scorm/backup/moodle2/backup_scorm_stepslib.php
mod/scorm/datamodels/aicclib.php
mod/scorm/datamodels/scormlib.php
mod/scorm/db/install.xml
mod/scorm/db/subplugins.php [changed mode: 0644->0755]
mod/scorm/db/upgrade.php
mod/scorm/lib.php
mod/scorm/loadSCO.php
mod/scorm/locallib.php
mod/scorm/report/basic/report.php
mod/scorm/report/graphs/report.php
mod/scorm/report/interactions/report.php
mod/scorm/report/objectives/report.php
mod/scorm/report/userreport.php
mod/scorm/version.php
mod/scorm/view.js
mod/scorm/view.php
theme/formal_white/style/course.css
user/editlib.php
version.php

index ce32ea2..26876ce 100644 (file)
@@ -250,7 +250,7 @@ class admin_uploaduser_form2 extends moodleform {
             $mform->setType('htmleditor', PARAM_INT);
         }
 
-        $mform->addElement('text', 'city', get_string('city'), 'maxlength="100" size="25"');
+        $mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="25"');
         $mform->setType('city', PARAM_TEXT);
         if (empty($CFG->defaultcity)) {
             $mform->setDefault('city', $templateuser->city);
@@ -288,14 +288,14 @@ class admin_uploaduser_form2 extends moodleform {
         $mform->setType('url', PARAM_URL);
         $mform->setAdvanced('url');
 
-        $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="64" size="25"');
+        $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"');
         $mform->setType('idnumber', PARAM_NOTAGS);
 
-        $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="40" size="25"');
+        $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="255" size="25"');
         $mform->setType('institution', PARAM_TEXT);
         $mform->setDefault('institution', $templateuser->institution);
 
-        $mform->addElement('text', 'department', get_string('department'), 'maxlength="30" size="25"');
+        $mform->addElement('text', 'department', get_string('department'), 'maxlength="255" size="25"');
         $mform->setType('department', PARAM_TEXT);
         $mform->setDefault('department', $templateuser->department);
 
@@ -307,7 +307,7 @@ class admin_uploaduser_form2 extends moodleform {
         $mform->setType('phone2', PARAM_NOTAGS);
         $mform->setAdvanced('phone2');
 
-        $mform->addElement('text', 'address', get_string('address'), 'maxlength="70" size="25"');
+        $mform->addElement('text', 'address', get_string('address'), 'maxlength="255" size="25"');
         $mform->setType('address', PARAM_TEXT);
         $mform->setAdvanced('address');
 
index f09a79a..8cdc537 100644 (file)
@@ -63,7 +63,8 @@ if ($id) {
 
             $displaystring = null;
             if (!empty($grade_item->itemmodule)) {
-                $displaystring = get_string('modulename', $grade_item->itemmodule).': '.$grade_item->get_name();
+                $displaystring = get_string('modulename', $grade_item->itemmodule).get_string('labelsep', 'langconfig')
+                        .$grade_item->get_name();
             } else {
                 $displaystring = $grade_item->get_name();
             }
index 73ff680..eb427c9 100644 (file)
@@ -88,17 +88,22 @@ class grade_import_mapping_form extends moodleform {
         }
         $mform->addElement('select', 'mapfrom', get_string('mapfrom', 'grades'), $mapfromoptions);
 
-        $maptooptions = array('userid'=>'userid', 'username'=>'username', 'useridnumber'=>'useridnumber', 'useremail'=>'useremail', '0'=>'ignore');
+        $maptooptions = array(
+            'userid'       => get_string('userid', 'grades'),
+            'username'     => get_string('username'),
+            'useridnumber' => get_string('idnumber'),
+            'useremail'    => get_string('email'),
+            '0'            => get_string('ignore', 'grades')
+        );
         $mform->addElement('select', 'mapto', get_string('mapto', 'grades'), $maptooptions);
 
         $mform->addElement('header', 'general', get_string('mappings', 'grades'));
 
-        // add a comment option
-
-        $comments = array();
+        // Add a feedback option.
+        $feedbacks = array();
         if ($gradeitems = $this->_customdata['gradeitems']) {
             foreach ($gradeitems as $itemid => $itemname) {
-                $comments['feedback_'.$itemid] = 'comments for '.$itemname;
+                $feedbacks['feedback_'.$itemid] = get_string('feedbackforgradeitems', 'grades', $itemname);
             }
         }
 
@@ -106,11 +111,16 @@ class grade_import_mapping_form extends moodleform {
             $i = 0; // index
             foreach ($header as $h) {
                 $h = trim($h);
-                // this is what each header maps to
-                $mform->addElement('selectgroups', 'mapping_'.$i, s($h),
-                    array('others'=>array('0'=>'ignore', 'new'=>'new gradeitem'),
-                    'gradeitems'=>$gradeitems,
-                    'comments'=>$comments));
+                // This is what each header maps to.
+                $headermapsto = array(
+                    get_string('others', 'grades')     => array(
+                        '0'   => get_string('ignore', 'grades'),
+                        'new' => get_string('newitem', 'grades')
+                    ),
+                    get_string('gradeitems', 'grades') => $gradeitems,
+                    get_string('feedbacks', 'grades')  => $feedbacks
+                );
+                $mform->addElement('selectgroups', 'mapping_'.$i, s($h), $headermapsto);
                 $i++;
             }
         }
index 99ab859..005f649 100644 (file)
@@ -202,6 +202,8 @@ $string['feedback'] = 'Feedback';
 $string['feedback_help'] = 'This box enables any comments about the grade to be added.';
 $string['feedbackadd'] = 'Add feedback';
 $string['feedbackedit'] = 'Edit feedback';
+$string['feedbackforgradeitems'] = 'Feedback for {$a}';
+$string['feedbacks'] = 'Feedbacks';
 $string['feedbacksaved'] = 'Feedback saved';
 $string['feedbackview'] = 'View feedback';
 $string['finalgrade'] = 'Final grade';
@@ -335,6 +337,7 @@ $string['chooseaction'] = 'Choose an action ...';
 $string['choosecategory'] = 'Select category';
 $string['identifier'] = 'Identify user by';
 $string['idnumbers'] = 'ID numbers';
+$string['ignore'] = 'Ignore';
 $string['import'] = 'Import';
 $string['importcsv'] = 'Import CSV';
 $string['importcustom'] = 'Import as custom outcomes (only this course)';
@@ -446,6 +449,7 @@ $string['numberofgrades'] = 'Number of grades';
 $string['onascaleof'] = 'on a scale of {$a->grademin} to {$a->grademax}';
 $string['operations'] = 'Operations';
 $string['options'] = 'Options';
+$string['others'] = 'Others';
 $string['outcome'] = 'Outcome';
 $string['outcome_help'] = 'This setting determines the outcome which this grade item will represent in the gradebook.';
 $string['outcomeassigntocourse'] = 'Assign another outcome to this course';
@@ -656,6 +660,7 @@ $string['usenoscale'] = 'Use no scale';
 $string['usepercent'] = 'Use percent';
 $string['user'] = 'User';
 $string['usergrade'] = 'User {$a->fullname} ({$a->useridnumber}) on item {$a->gradeidnumber}';
+$string['userid'] = 'User ID';
 $string['userpreferences'] = 'User preferences';
 $string['userenrolmentsuspended'] = 'User enrolment suspended';
 $string['useweighted'] = 'Use weighted';
index 8095fae..d79981f 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20130905" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20130913" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
         <FIELD NAME="msn" TYPE="char" LENGTH="50" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="phone1" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="phone2" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="institution" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="department" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="address" TYPE="char" LENGTH="70" NOTNULL="true" SEQUENCE="false"/>
+        <FIELD NAME="institution" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
+        <FIELD NAME="department" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
+        <FIELD NAME="address" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="city" TYPE="char" LENGTH="120" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="country" TYPE="char" LENGTH="2" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="lang" TYPE="char" LENGTH="30" NOTNULL="true" DEFAULT="en" SEQUENCE="false"/>
       </KEYS>
     </TABLE>
   </TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
index 1fad3d4..543d1b3 100644 (file)
@@ -2424,5 +2424,31 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013091000.03);
     }
 
+    if ($oldversion < 2013091300.01) {
+
+        $table = new xmldb_table('user');
+
+        // Changing precision of field institution on table user to (255).
+        $field = new xmldb_field('institution', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'phone2');
+
+        // Launch change of precision for field institution.
+        $dbman->change_field_precision($table, $field);
+
+        // Changing precision of field department on table user to (255).
+        $field = new xmldb_field('department', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'institution');
+
+        // Launch change of precision for field department.
+        $dbman->change_field_precision($table, $field);
+
+        // Changing precision of field address on table user to (255).
+        $field = new xmldb_field('address', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'department');
+
+        // Launch change of precision for field address.
+        $dbman->change_field_precision($table, $field);
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013091300.01);
+    }
+
     return true;
 }
index cda69f1..ea6a36a 100644 (file)
@@ -627,5 +627,13 @@ abstract class assign_plugin {
         return true;
     }
 
-
+    /**
+     * If this plugin can participate in a webservice (save_submission or save_grade),
+     * return a list of external_params to be included in the definition of that webservice.
+     *
+     * @return external_description|null
+     */
+    public function get_external_parameters() {
+        return null;
+    }
 }
index 1fe8cd2..b2d12fc 100644 (file)
@@ -63,5 +63,70 @@ $functions = array(
                 'classpath' => 'mod/assign/externallib.php',
                 'description' => 'Returns the blind marking mappings for assignments',
                 'type' => 'read'
+        ),
+
+        'mod_assign_revert_submissions_to_draft' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'revert_submissions_to_draft',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Reverts the list of submissions to draft status',
+                'type' => 'write'
+        ),
+
+        'mod_assign_lock_submissions' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'lock_submissions',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Prevent students from making changes to a list of submissions',
+                'type' => 'write'
+        ),
+
+        'mod_assign_unlock_submissions' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'unlock_submissions',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Allow students to make changes to a list of submissions',
+                'type' => 'write'
+        ),
+
+        'mod_assign_save_submission' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'save_submission',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Update the current students submission',
+                'type' => 'write'
+        ),
+
+        'mod_assign_submit_for_grading' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'submit_for_grading',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Submit the current students assignment for grading',
+                'type' => 'write'
+        ),
+
+        'mod_assign_save_grade' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'save_grade',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Save a grade update for a single student.',
+                'type' => 'write'
+        ),
+
+        'mod_assign_save_user_extensions' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'save_user_extensions',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Save a list of assignment extensions',
+                'type' => 'write'
+        ),
+
+        'mod_assign_reveal_identities' => array(
+                'classname' => 'mod_assign_external',
+                'methodname' => 'reveal_identities',
+                'classpath' => 'mod/assign/externallib.php',
+                'description' => 'Reveal the identities for a blind marking assignment',
+                'type' => 'write'
         )
+
 );
index 2b03f07..8aa0a35 100644 (file)
@@ -29,9 +29,43 @@ require_once("$CFG->libdir/externallib.php");
 
 /**
  * Assign functions
+ * @copyright 2012 Paul Charsley
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 class mod_assign_external extends external_api {
 
+    /**
+     * Generate a warning in a standard structure for a known failure.
+     *
+     * @param int $assignmentid - The assignment
+     * @param string $warningcode - The key for the warning message
+     * @param string $detail - A description of the error
+     * @return array - Warning structure containing item, itemid, warningcode, message
+     */
+    private static function generate_warning($assignmentid, $warningcode, $detail) {
+        $warningmessages = array(
+            'couldnotlock'=>'Could not lock the submission for this user.',
+            'couldnotunlock'=>'Could not unlock the submission for this user.',
+            'couldnotsubmitforgrading'=>'Could not submit assignment for grading.',
+            'couldnotrevealidentities'=>'Could not reveal identities.',
+            'couldnotgrantextensions'=>'Could not grant submission date extensions.',
+            'couldnotrevert'=>'Could not revert submission to draft.',
+            'invalidparameters'=>'Invalid parameters.',
+            'couldnotsavesubmission'=>'Could not save submission.',
+            'couldnotsavegrade'=>'Could not save grade.'
+        );
+
+        $message = $warningmessages[$warningcode];
+        if (empty($message)) {
+            $message = 'Unknown warning type.';
+        }
+
+        return array('item'=>$detail,
+                     'itemid'=>$assignmentid,
+                     'warningcode'=>$warningcode,
+                     'message'=>$message);
+    }
+
     /**
      * Describes the parameters for get_grades
      * @return external_external_function_parameters
@@ -53,7 +87,7 @@ class mod_assign_external extends external_api {
 
     /**
      * Returns grade information from assign_grades for the requested assignment ids
-     * @param array of ints $assignmentids
+     * @param int[] $assignmentids
      * @param int $since only return records with timemodified >= since
      * @return array of grade records for each requested assignment
      * @since  Moodle 2.4
@@ -102,7 +136,7 @@ class mod_assign_external extends external_api {
                                 WHERE mxg.assignment ' . $inorequalsql2 . ' GROUP BY mxg.userid';
 
             $sql = "SELECT ag.id,ag.assignment,ag.userid,ag.timecreated,ag.timemodified,".
-                   "ag.grader,ag.grade ".
+                   "ag.grader,ag.grade,ag.attemptnumber ".
                    "FROM {assign_grades} ag ".
                    "JOIN ( " . $grademaxattempt . " ) gmx ON ag.userid = gmx.userid".
                    " WHERE ag.assignment ".$inorequalsql.
@@ -122,6 +156,7 @@ class mod_assign_external extends external_api {
                 $grade['timecreated'] = $rd->timecreated;
                 $grade['timemodified'] = $rd->timemodified;
                 $grade['grader'] = $rd->grader;
+                $grade['attemptnumber'] = $rd->attemptnumber;
                 $grade['grade'] = (string)$rd->grade;
 
                 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
@@ -170,6 +205,7 @@ class mod_assign_external extends external_api {
                         array(
                             'id'            => new external_value(PARAM_INT, 'grade id'),
                             'userid'        => new external_value(PARAM_INT, 'student id'),
+                            'attemptnumber' => new external_value(PARAM_INT, 'attempt number'),
                             'timecreated'   => new external_value(PARAM_INT, 'grade creation time'),
                             'timemodified'  => new external_value(PARAM_INT, 'grade last modified time'),
                             'grader'        => new external_value(PARAM_INT, 'grader'),
@@ -473,7 +509,7 @@ class mod_assign_external extends external_api {
     /**
      * Returns submissions for the requested assignment ids
      *
-     * @param array of ints $assignmentids
+     * @param int[] $assignmentids
      * @param string $status only return submissions with this status
      * @param int $since only return submissions with timemodified >= since
      * @param int $before only return submissions with timemodified <= before
@@ -528,7 +564,7 @@ class mod_assign_external extends external_api {
                                      WHERE mxs.assignment = :assignid1 GROUP BY mxs.userid';
 
             $sql = "SELECT mas.id, mas.assignment,mas.userid,".
-                   "mas.timecreated,mas.timemodified,mas.status,mas.groupid ".
+                   "mas.timecreated,mas.timemodified,mas.status,mas.groupid,mas.attemptnumber ".
                    "FROM {assign_submission} mas ".
                    "JOIN ( " . $submissionmaxattempt . " ) smx ON mas.userid = smx.userid ".
                    "WHERE mas.assignment = :assignid2 AND mas.attemptnumber = smx.maxattempt";
@@ -557,6 +593,7 @@ class mod_assign_external extends external_api {
                         'timecreated' => $submissionrecord->timecreated,
                         'timemodified' => $submissionrecord->timemodified,
                         'status' => $submissionrecord->status,
+                        'attemptnumber' => $submissionrecord->attemptnumber,
                         'groupid' => $submissionrecord->groupid
                     );
                     foreach ($submissionplugins as $submissionplugin) {
@@ -638,6 +675,7 @@ class mod_assign_external extends external_api {
                         array(
                             'id' => new external_value(PARAM_INT, 'submission id'),
                             'userid' => new external_value(PARAM_INT, 'student id'),
+                            'attemptnumber' => new external_value(PARAM_INT, 'attempt number'),
                             'timecreated' => new external_value(PARAM_INT, 'submission creation time'),
                             'timemodified' => new external_value(PARAM_INT, 'submission last modified time'),
                             'status' => new external_value(PARAM_TEXT, 'submission status'),
@@ -716,7 +754,7 @@ class mod_assign_external extends external_api {
 
     /**
      * Returns user flag information from assign_user_flags for the requested assignment ids
-     * @param array of ints $assignmentids
+     * @param int[] $assignmentids
      * @return array of user flag records for each requested assignment
      * @since  Moodle 2.6
      */
@@ -870,7 +908,7 @@ class mod_assign_external extends external_api {
 
     /**
      * Returns user mapping information from assign_user_mapping for the requested assignment ids
-     * @param array of ints $assignmentids
+     * @param int[] $assignmentids
      * @return array of user mapping records for each requested assignment
      * @since  Moodle 2.6
      */
@@ -995,4 +1033,620 @@ class mod_assign_external extends external_api {
         );
     }
 
+    /**
+     * Describes the parameters for lock_submissions
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function lock_submissions_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'userids' => new external_multiple_structure(
+                    new external_value(PARAM_INT, 'user id'),
+                    '1 or more user ids',
+                    VALUE_REQUIRED),
+            )
+        );
+    }
+
+    /**
+     * Locks (prevent updates to) submissions in this assignment.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @param array $userids Array of user ids to lock
+     * @return array of warnings for each submission that could not be locked.
+     * @since Moodle 2.6
+     */
+    public static function lock_submissions($assignmentid, $userids) {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::lock_submissions_parameters(),
+                        array('assignmentid' => $assignmentid,
+                              'userids' => $userids));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $warnings = array();
+        foreach ($userids as $userid) {
+            if (!$assignment->lock_submission($userid)) {
+                $detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid;
+                $warnings[] = self::generate_warning($assignmentid,
+                                                     'couldnotlock',
+                                                     $detail);
+            }
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for lock_submissions
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function lock_submissions_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for revert_submissions_to_draft
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function revert_submissions_to_draft_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'userids' => new external_multiple_structure(
+                    new external_value(PARAM_INT, 'user id'),
+                    '1 or more user ids',
+                    VALUE_REQUIRED),
+            )
+        );
+    }
+
+    /**
+     * Reverts a list of user submissions to draft for a single assignment.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @param array $userids Array of user ids to revert
+     * @return array of warnings for each submission that could not be reverted.
+     * @since Moodle 2.6
+     */
+    public static function revert_submissions_to_draft($assignmentid, $userids) {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::revert_submissions_to_draft_parameters(),
+                        array('assignmentid' => $assignmentid,
+                              'userids' => $userids));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $warnings = array();
+        foreach ($userids as $userid) {
+            if (!$assignment->revert_to_draft($userid)) {
+                $detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid;
+                $warnings[] = self::generate_warning($assignmentid,
+                                                     'couldnotrevert',
+                                                     $detail);
+            }
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for revert_submissions_to_draft
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function revert_submissions_to_draft_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for unlock_submissions
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function unlock_submissions_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'userids' => new external_multiple_structure(
+                    new external_value(PARAM_INT, 'user id'),
+                    '1 or more user ids',
+                    VALUE_REQUIRED),
+            )
+        );
+    }
+
+    /**
+     * Locks (prevent updates to) submissions in this assignment.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @param array $userids Array of user ids to lock
+     * @return array of warnings for each submission that could not be locked.
+     * @since Moodle 2.6
+     */
+    public static function unlock_submissions($assignmentid, $userids) {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::unlock_submissions_parameters(),
+                        array('assignmentid' => $assignmentid,
+                              'userids' => $userids));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $warnings = array();
+        foreach ($userids as $userid) {
+            if (!$assignment->unlock_submission($userid)) {
+                $detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid;
+                $warnings[] = self::generate_warning($assignmentid,
+                                                     'couldnotunlock',
+                                                     $detail);
+            }
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for unlock_submissions
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function unlock_submissions_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for submit_for_grading
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function submit_for_grading_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'acceptsubmissionstatement' => new external_value(PARAM_BOOL, 'Accept the assignment submission statement')
+            )
+        );
+    }
+
+    /**
+     * Submit the logged in users assignment for grading.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @return array of warnings to indicate any errors.
+     * @since Moodle 2.6
+     */
+    public static function submit_for_grading($assignmentid, $acceptsubmissionstatement) {
+        global $CFG, $USER;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::submit_for_grading_parameters(),
+                                            array('assignmentid' => $assignmentid,
+                                                  'acceptsubmissionstatement' => $acceptsubmissionstatement));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $warnings = array();
+        $data = new stdClass();
+        $data->submissionstatement = $acceptsubmissionstatement;
+
+        if (!$assignment->submit_for_grading($data)) {
+            $detail = 'User id: ' . $USER->id . ', Assignment id: ' . $assignmentid;
+            $warnings[] = self::generate_warning($assignmentid,
+                                                 'couldnotsubmitforgrading',
+                                                 $detail);
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for submit_for_grading
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function submit_for_grading_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for save_user_extensions
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function save_user_extensions_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'userids' => new external_multiple_structure(
+                    new external_value(PARAM_INT, 'user id'),
+                    '1 or more user ids',
+                    VALUE_REQUIRED),
+                'dates' => new external_multiple_structure(
+                    new external_value(PARAM_INT, 'dates'),
+                    '1 or more extension dates (timestamp)',
+                    VALUE_REQUIRED),
+            )
+        );
+    }
+
+    /**
+     * Grant extension dates to students for an assignment.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @param array $userids Array of user ids to grant extensions to
+     * @param array $dates Array of extension dates
+     * @return array of warnings for each extension date that could not be granted
+     * @since Moodle 2.6
+     */
+    public static function save_user_extensions($assignmentid, $userids, $dates) {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::save_user_extensions_parameters(),
+                        array('assignmentid' => $assignmentid,
+                              'userids' => $userids,
+                              'dates' => $dates));
+
+        if (count($userids) != count($dates)) {
+            $detail = 'Length of userids and dates parameters differ.';
+            $warnings[] = self::generate_warning($assignmentid,
+                                                 'invalidparameters',
+                                                 $detail);
+
+            return $warnings;
+        }
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $warnings = array();
+        foreach ($userids as $idx => $userid) {
+            $duedate = $dates[$idx];
+            if (!$assignment->save_user_extension($userid, $duedate)) {
+                $detail = 'User id: ' . $userid . ', Assignment id: ' . $assignmentid . ', Extension date: ' . $duedate;
+                $warnings[] = self::generate_warning($assignmentid,
+                                                     'couldnotgrantextensions',
+                                                     $detail);
+            }
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for save_user_extensions
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function save_user_extensions_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for reveal_identities
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function reveal_identities_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on')
+            )
+        );
+    }
+
+    /**
+     * Reveal the identities of anonymous students to markers for a single assignment.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @return array of warnings to indicate any errors.
+     * @since Moodle 2.6
+     */
+    public static function reveal_identities($assignmentid) {
+        global $CFG, $USER;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::reveal_identities_parameters(),
+                                            array('assignmentid' => $assignmentid));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $warnings = array();
+        if (!$assignment->reveal_identities()) {
+            $detail = 'User id: ' . $USER->id . ', Assignment id: ' . $assignmentid;
+            $warnings[] = self::generate_warning($assignmentid,
+                                                 'couldnotrevealidentities',
+                                                 $detail);
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for reveal_identities
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function reveal_identities_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for save_submission
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function save_submission_parameters() {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+        $instance = new assign(null, null, null);
+        $pluginsubmissionparams = array();
+
+        foreach ($instance->get_submission_plugins() as $plugin) {
+            $pluginparams = $plugin->get_external_parameters();
+            if (!empty($pluginparams)) {
+                $pluginsubmissionparams = array_merge($pluginsubmissionparams, $pluginparams);
+            }
+        }
+
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'plugindata' => new external_single_structure(
+                    $pluginsubmissionparams
+                )
+            )
+        );
+    }
+
+    /**
+     * Save a student submission for a single assignment
+     *
+     * @param int $assignmentid The id of the assignment
+     * @param array $plugindata - The submitted data for plugins
+     * @return array of warnings to indicate any errors
+     * @since Moodle 2.6
+     */
+    public static function save_submission($assignmentid, $plugindata) {
+        global $CFG, $USER;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::save_submission_parameters(),
+                                            array('assignmentid' => $assignmentid,
+                                                  'plugindata' => $plugindata));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $notices = array();
+
+        $submissiondata = (object)$plugindata;
+
+        $assignment->save_submission($submissiondata, $notices);
+
+        $warnings = array();
+        foreach ($notices as $notice) {
+            $warnings[] = self::generate_warning($assignmentid,
+                                                 'couldnotsavesubmission',
+                                                 $notice);
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for save_submission
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function save_submission_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
+
+    /**
+     * Describes the parameters for save_grade
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function save_grade_parameters() {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+        $instance = new assign(null, null, null);
+        $pluginfeedbackparams = array();
+
+        foreach ($instance->get_feedback_plugins() as $plugin) {
+            $pluginparams = $plugin->get_external_parameters();
+            if (!empty($pluginparams)) {
+                $pluginfeedbackparams = array_merge($pluginfeedbackparams, $pluginparams);
+            }
+        }
+
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+                'userid' => new external_value(PARAM_INT, 'The student id to operate on'),
+                'grade' => new external_value(PARAM_FLOAT, 'The new grade for this user'),
+                'attemptnumber' => new external_value(PARAM_INT, 'The attempt number (-1 means latest attempt)'),
+                'addattempt' => new external_value(PARAM_BOOL, 'Allow another attempt if the attempt reopen method is manual'),
+                'workflowstate' => new external_value(PARAM_ALPHA, 'The next marking workflow state'),
+                'applytoall' => new external_value(PARAM_BOOL, 'If true, this grade will be applied ' .
+                                                               'to all members ' .
+                                                               'of the group (for group assignments).'),
+                'plugindata' => new external_single_structure(
+                    $pluginfeedbackparams
+                )
+            )
+        );
+    }
+
+    /**
+     * Save a student grade for a single assignment.
+     *
+     * @param int $assignmentid The id of the assignment
+     * @param int $userid The id of the user
+     * @param float $grade The grade
+     * @param int $attemptnumber The attempt number
+     * @param bool $addattempt Allow another attempt
+     * @param string $workflowstate New workflow state
+     * @param bool $applytoall Apply the grade to all members of the group
+     * @param array $plugindata Custom data used by plugins
+     * @return null
+     * @since Moodle 2.6
+     */
+    public static function save_grade($assignmentid,
+                                      $userid,
+                                      $grade,
+                                      $attemptnumber,
+                                      $addattempt,
+                                      $workflowstate,
+                                      $applytoall,
+                                      $plugindata) {
+        global $CFG, $USER;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::save_grade_parameters(),
+                                            array('assignmentid' => $assignmentid,
+                                                  'userid' => $userid,
+                                                  'grade' => $grade,
+                                                  'attemptnumber' => $attemptnumber,
+                                                  'workflowstate' => $workflowstate,
+                                                  'addattempt' => $addattempt,
+                                                  'applytoall' => $applytoall,
+                                                  'plugindata' => $plugindata));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $gradedata = (object)$plugindata;
+
+        $gradedata->addattempt = $addattempt;
+        $gradedata->attemptnumber = $attemptnumber;
+        $gradedata->workflowstate = $workflowstate;
+        $gradedata->applytoall = $applytoall;
+        $gradedata->grade = $grade;
+
+        $assignment->save_grade($userid, $gradedata);
+
+        return null;
+    }
+
+    /**
+     * Describes the return value for save_grade
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function save_grade_returns() {
+        return null;
+    }
+
+    /**
+     * Describes the parameters for copy_previous_attempt
+     * @return external_external_function_parameters
+     * @since  Moodle 2.6
+     */
+    public static function copy_previous_attempt_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'),
+            )
+        );
+    }
+
+    /**
+     * Copy a students previous attempt to a new attempt.
+     *
+     * @param int $assignmentid
+     * @return array of warnings to indicate any errors.
+     * @since Moodle 2.6
+     */
+    public static function copy_previous_attempt($assignmentid) {
+        global $CFG, $USER;
+        require_once("$CFG->dirroot/mod/assign/locallib.php");
+
+        $params = self::validate_parameters(self::copy_previous_attempt_parameters(),
+                                            array('assignmentid' => $assignmentid));
+
+        $cm = get_coursemodule_from_instance('assign', $assignmentid, 0, false, MUST_EXIST);
+        $context = context_module::instance($cm->id);
+
+        $assignment = new assign($context, $cm, null);
+
+        $notices = array();
+
+        $assignment->copy_previous_attempt($submissiondata, $notices);
+
+        $warnings = array();
+        foreach ($notices as $notice) {
+            $warnings[] = self::generate_warning($assignmentid,
+                                                 'couldnotcopyprevioussubmission',
+                                                 $notice);
+        }
+
+        return $warnings;
+    }
+
+    /**
+     * Describes the return value for save_submission
+     *
+     * @return external_single_structure
+     * @since Moodle 2.6
+     */
+    public static function copy_previous_attempt_returns() {
+        return new external_multiple_structure(
+           new external_warnings()
+        );
+    }
 }
index 1efd24e..9b95aed 100644 (file)
@@ -15,7 +15,9 @@
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Restore subplugin class that provides the necessary information needed to restore
+ * Restore subplugin class.
+ *
+ * Provides the necessary information needed to restore
  * one assign_submission subplugin.
  *
  * @package   assignfeedback_comments
@@ -26,7 +28,9 @@
 defined('MOODLE_INTERNAL') || die();
 
 /**
- * Restore subplugin class that provides the necessary information needed to restore
+ * Restore subplugin class.
+ *
+ * Provides the necessary information needed to restore
  * one assignfeedback subplugin.
  *
  * @package   assignfeedback_comments
index 9ed302c..2d6e92d 100644 (file)
@@ -390,4 +390,16 @@ class assign_feedback_comments extends assign_feedback_plugin {
         return $this->view($grade) == '';
     }
 
+    /**
+     * Return a description of external params suitable for uploading an feedback comment from a webservice.
+     *
+     * @return external_description|null
+     */
+    public function get_external_parameters() {
+        $editorparams = array('text' => new external_value(PARAM_TEXT, 'The text for this feedback.'),
+                              'format' => new external_value(PARAM_INT, 'The format for this feedback'));
+        $editorstructure = new external_single_structure($editorparams);
+        return array('assignfeedbackcomments_editor' => $editorstructure);
+    }
+
 }
index f85cd5a..f8d45ae 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * This file defines the admin settings for this plugin
  *
- * @package   assignsubmission_comments
+ * @package   assignfeedback_comments
  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
index df258d3..a408afd 100644 (file)
@@ -24,7 +24,9 @@
 defined('MOODLE_INTERNAL') || die();
 
 /**
- * Restore subplugin class that provides the necessary information needed
+ * Restore subplugin class.
+ *
+ * Provides the necessary information needed
  * to restore one assign_feedback subplugin.
  *
  * @package   assignfeedback_file
index 50c0e25..7b64583 100644 (file)
@@ -36,7 +36,7 @@ define('ASSIGNFEEDBACK_FILE_MAXFILEUNZIPTIME', 120);
 /**
  * Library class for file feedback plugin extending feedback plugin base class.
  *
- * @package   asignfeedback_file
+ * @package   assignfeedback_file
  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
@@ -609,4 +609,19 @@ class assign_feedback_file extends assign_feedback_plugin {
     public function get_grading_actions() {
         return array('uploadzip'=>get_string('uploadzip', 'assignfeedback_file'));
     }
+
+    /**
+     * Return a description of external params suitable for uploading a feedback file from a webservice.
+     *
+     * @return external_description|null
+     */
+    public function get_external_parameters() {
+        return array(
+            'files_filemanager' => new external_value(
+                PARAM_INT,
+                'The id of a draft area containing files for this feedback.'
+            )
+        );
+    }
+
 }
index 0719b0b..ead9c88 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * This file defines the admin settings for this plugin
  *
- * @package   assignsubmission_onlinetext
+ * @package   assignfeedback_file
  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
index 4b795fe..d7c7e27 100644 (file)
@@ -71,6 +71,7 @@ class assign_grading_table extends table_sql implements renderable {
      * @param string $filter The current filter
      * @param int $rowoffset For showing a subsequent page of results
      * @param bool $quickgrading Is this table wrapped in a quickgrading form?
+     * @param string $downloadfilename
      */
     public function __construct(assign $assignment,
                                 $perpage,
@@ -435,6 +436,7 @@ class assign_grading_table extends table_sql implements renderable {
     /**
      * Add a column with an ID that uniquely identifies this user in this assignment.
      *
+     * @param stdClass $row
      * @return string
      */
     public function col_recordid(stdClass $row) {
@@ -621,8 +623,8 @@ class assign_grading_table extends table_sql implements renderable {
      * Use a static cache to try and reduce DB calls.
      *
      * @param int $userid The user id for this submission
-     * @param int $groupid The groupid (returned)
-     * @param mixed $submission The stdClass submission or false (returned)
+     * @param int $group The groupid (returned)
+     * @param stdClass|false $submission The stdClass submission or false (returned)
      * @param int $attemptnumber Return a specific attempt number (-1 for latest)
      */
     protected function get_group_and_submission($userid, &$group, &$submission, $attemptnumber) {
index f072009..bc6d798 100644 (file)
@@ -40,6 +40,7 @@ $PAGE->navbar->add($strplural);
 $PAGE->set_title($strplural);
 $PAGE->set_heading($course->fullname);
 echo $OUTPUT->header();
+echo $OUTPUT->heading(format_string($strplural));
 
 $context = context_course::instance($course->id);
 
index 49a13f1..99bd425 100644 (file)
@@ -16,6 +16,7 @@
 
 /**
  * This file contains the moodle hooks for the assign module.
+ *
  * It delegates most functions to the assignment class.
  *
  * @package   mod_assign
@@ -59,8 +60,9 @@ function assign_delete_instance($id) {
  * This function is used by the reset_course_userdata function in moodlelib.
  * This function will remove all assignment submissions and feedbacks in the database
  * and clean up any related data.
- * @param $data the data submitted from the reset course.
- * @return array status array
+ *
+ * @param stdClass $data the data submitted from the reset course.
+ * @return array
  */
 function assign_reset_userdata($data) {
     global $CFG, $DB;
@@ -109,7 +111,7 @@ function assign_reset_gradebook($courseid, $type='') {
 /**
  * Implementation of the function for printing the form elements that control
  * whether the course reset functionality affects the assignment.
- * @param $mform form passed by reference
+ * @param moodleform $mform form passed by reference
  */
 function assign_reset_course_form_definition(&$mform) {
     $mform->addElement('header', 'assignheader', get_string('modulenameplural', 'assign'));
@@ -131,7 +133,7 @@ function assign_reset_course_form_defaults($course) {
  *
  * This is done by calling the update_instance() method of the assignment type class
  * @param stdClass $data
- * @param $form
+ * @param stdClass $form - unused
  * @return object
  */
 function assign_update_instance(stdClass $data, $form) {
@@ -280,11 +282,11 @@ function assign_get_coursemodule_info($coursemodule) {
  * @param stdClass $currentcontext Current context of block
  */
 function assign_page_type_list($pagetype, $parentcontext, $currentcontext) {
-    $module_pagetype = array(
+    $modulepagetype = array(
         'mod-assign-*' => get_string('page-mod-assign-x', 'assign'),
         'mod-assign-view' => get_string('page-mod-assign-view', 'assign'),
     );
-    return $module_pagetype;
+    return $modulepagetype;
 }
 
 /**
@@ -656,10 +658,10 @@ function assign_get_recent_mod_activity(&$activities,
     }
 
     $groupmode       = groups_get_activity_groupmode($cm, $course);
-    $cm_context      = context_module::instance($cm->id);
-    $grader          = has_capability('moodle/grade:viewall', $cm_context);
-    $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context);
-    $viewfullnames   = has_capability('moodle/site:viewfullnames', $cm_context);
+    $cmcontext      = context_module::instance($cm->id);
+    $grader          = has_capability('moodle/grade:viewall', $cmcontext);
+    $accessallgroups = has_capability('moodle/site:accessallgroups', $cmcontext);
+    $viewfullnames   = has_capability('moodle/site:viewfullnames', $cmcontext);
 
     if (is_null($modinfo->get_groups())) {
         // Load all my groups and cache it in modinfo.
index 5941b34..62f0678 100644 (file)
@@ -389,7 +389,7 @@ class assign {
                 $nextpageparams['action'] = 'editsubmission';
             }
         } else if ($action == 'lock') {
-            $this->process_lock();
+            $this->process_lock_submission();
             $action = 'redirect';
             $nextpageparams['action'] = 'grading';
         } else if ($action == 'addattempt') {
@@ -401,7 +401,7 @@ class assign {
             $action = 'redirect';
             $nextpageparams['action'] = 'grading';
         } else if ($action == 'unlock') {
-            $this->process_unlock();
+            $this->process_unlock_submission();
             $action = 'redirect';
             $nextpageparams['action'] = 'grading';
         } else if ($action == 'setbatchmarkingworkflowstate') {
@@ -674,7 +674,7 @@ class assign {
      * Actual implementation of the reset course functionality, delete all the
      * assignment submissions for course $data->courseid.
      *
-     * @param $data the data submitted from the reset course.
+     * @param stdClass $data the data submitted from the reset course.
      * @return array status array
      */
     public function reset_userdata($data) {
@@ -1260,12 +1260,21 @@ class assign {
      */
     public function list_participants($currentgroup, $idsonly) {
         if ($idsonly) {
-            return get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.id', null, null, null,
+            $users = get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.id', null, null, null,
                     $this->show_only_active_users());
         } else {
-            return get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.*', null, null, null,
+            $users = get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.*', null, null, null,
                     $this->show_only_active_users());
         }
+
+        $cm = $this->get_course_module();
+        foreach ($users as $userid => $user) {
+            if (!groups_course_module_visible($cm, $userid)) {
+                unset($users[$userid]);
+            }
+        }
+
+        return $users;
     }
 
     /**
@@ -1297,7 +1306,7 @@ class assign {
      * @return int number of matching users
      */
     public function count_participants($currentgroup) {
-        return count_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, true);
+        return count($this->list_participants($currentgroup, true));
     }
 
     /**
@@ -2003,10 +2012,10 @@ class assign {
                     $submitted = get_string('submissionstatus_', 'assign');
                 }
             }
-            $grading_info = grade_get_grades($course->id, 'mod', 'assign', $cm->instance, $USER->id);
-            if (isset($grading_info->items[0]->grades[$USER->id]) &&
-                    !$grading_info->items[0]->grades[$USER->id]->hidden ) {
-                $grade = $grading_info->items[0]->grades[$USER->id]->str_grade;
+            $gradinginfo = grade_get_grades($course->id, 'mod', 'assign', $cm->instance, $USER->id);
+            if (isset($gradinginfo->items[0]->grades[$USER->id]) &&
+                    !$gradinginfo->items[0]->grades[$USER->id]->hidden ) {
+                $grade = $gradinginfo->items[0]->grades[$USER->id]->str_grade;
             } else {
                 $grade = '-';
             }
@@ -2142,6 +2151,7 @@ class assign {
     /**
      * Rewrite plugin file urls so they resolve correctly in an exported zip.
      *
+     * @param string $text - The replacement text
      * @param stdClass $user - The user record
      * @param assign_plugin $plugin - The assignment plugin
      */
@@ -2231,6 +2241,7 @@ class assign {
     /**
      * Display a continue page.
      *
+     * @param string $message - The message to display
      * @return string
      */
     protected function view_savegrading_result($message) {
@@ -3237,6 +3248,7 @@ class assign {
     /**
      * Allows the plugin to show a batch grading operation page.
      *
+     * @param moodleform $mform
      * @return none
      */
     protected function view_plugin_grading_batch_operation($mform) {
@@ -3314,9 +3326,9 @@ class assign {
 
             foreach ($userlist as $userid) {
                 if ($data->operation == 'lock') {
-                    $this->process_lock($userid);
+                    $this->process_lock_submission($userid);
                 } else if ($data->operation == 'unlock') {
-                    $this->process_unlock($userid);
+                    $this->process_unlock_submission($userid);
                 } else if ($data->operation == 'reverttodraft') {
                     $this->process_revert_to_draft($userid);
                 } else if ($data->operation == 'addattempt') {
@@ -3453,7 +3465,7 @@ class assign {
     /**
      * Ask the user to confirm they want to submit their work for grading.
      *
-     * @param $mform moodleform - null unless form validation has failed
+     * @param moodleform $mform - null unless form validation has failed
      * @return string
      */
     protected function check_submit_for_grading($mform) {
@@ -3651,7 +3663,8 @@ class assign {
                 // Only show the grade if it is not hidden in gradebook.
                 if (!empty($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden)) {
                     if ($controller = $gradingmanager->get_active_controller()) {
-                        $controller->set_grade_range(make_grades_menu($this->get_instance()->grade), $this->get_instance()->grade > 0);
+                        $menu = make_grades_menu($this->get_instance()->grade);
+                        $controller->set_grade_range($menu, $this->get_instance()->grade > 0);
                         $gradefordisplay = $controller->render_grade($PAGE,
                                                                      $grade->id,
                                                                      $gradingitem,
@@ -4241,7 +4254,6 @@ class assign {
      * @param string $modulename
      * @param stdClass $coursemodule
      * @param string $assignmentname
-     * @param stdClass $info
      */
     protected static function format_notification_message_html($messagetype,
                                                              $info,
@@ -4281,6 +4293,8 @@ class assign {
      * @param stdClass $course
      * @param string $modulename
      * @param string $assignmentname
+     * @param bool $blindmarking
+     * @param int $uniqueidforuser
      * @return void
      */
     public static function send_assignment_notification($userfrom,
@@ -4462,18 +4476,85 @@ class assign {
         }
     }
 
+    /**
+     * Submit a submission for grading.
+     *
+     * @return bool Return false if the submission was not submitted.
+     */
+    public function submit_for_grading($data) {
+        global $USER;
+
+        // Need submit permission to submit an assignment.
+        require_capability('mod/assign:submit', $this->context);
+
+        $instance = $this->get_instance();
+
+        if ($instance->teamsubmission) {
+            $submission = $this->get_group_submission($USER->id, 0, true);
+        } else {
+            $submission = $this->get_user_submission($USER->id, true);
+        }
+
+        if (!$this->submissions_open($USER->id)) {
+            return false;
+        }
+
+        if ($instance->requiresubmissionstatement && !$data->submissionstatement) {
+            return false;
+        }
+
+        if ($submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
+            // Give each submission plugin a chance to process the submission.
+            $plugins = $this->get_submission_plugins();
+            foreach ($plugins as $plugin) {
+                if ($plugin->is_enabled() && $plugin->is_visible()) {
+                    $plugin->submit_for_grading($submission);
+                }
+            }
+
+            $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+            $this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
+            $completion = new completion_info($this->get_course());
+            if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
+                $completion->update_state($this->get_course_module(), COMPLETION_COMPLETE, $USER->id);
+            }
+
+            if (!empty($data->submissionstatement)) {
+                $logmessage = get_string('submissionstatementacceptedlog',
+                                         'mod_assign',
+                                         fullname($USER));
+                $this->add_to_log('submission statement accepted', $logmessage);
+            }
+            $logdata = $this->add_to_log('submit for grading', $this->format_submission_for_log($submission), '', true);
+            $this->notify_graders($submission);
+            $this->notify_student_submission_receipt($submission);
+
+            // Trigger assessable_submitted event on submission.
+            $params = array(
+                'context' => context_module::instance($this->get_course_module()->id),
+                'objectid' => $submission->id,
+                'other' => array(
+                    'submission_editable' => false
+                )
+            );
+            $event = \mod_assign\event\assessable_submitted::create($params);
+            $event->set_legacy_logdata($logdata);
+            $event->trigger();
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Assignment submission is processed before grading.
      *
-     * @param $mform If validation failed when submitting this form - this is the moodleform.
+     * @param moodleform|null $mform If validation failed when submitting this form - this is the moodleform.
      *               It can be null.
      * @return bool Return false if the validation fails. This affects which page is displayed next.
      */
     protected function process_submit_for_grading($mform) {
         global $USER, $CFG;
 
-        // Need submit permission to submit an assignment.
-        require_capability('mod/assign:submit', $this->context);
         require_once($CFG->dirroot . '/mod/assign/submissionconfirmform.php');
         require_sesskey();
 
@@ -4503,57 +4584,7 @@ class assign {
             if ($mform->get_data() == false) {
                 return false;
             }
-            if ($instance->teamsubmission) {
-                $submission = $this->get_group_submission($USER->id, 0, true);
-            } else {
-                $submission = $this->get_user_submission($USER->id, true);
-            }
-
-            if ($submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
-                // Give each submission plugin a chance to process the submission.
-                $plugins = $this->get_submission_plugins();
-                foreach ($plugins as $plugin) {
-                    if ($plugin->is_enabled() && $plugin->is_visible()) {
-                        $plugin->submit_for_grading($submission);
-                    }
-                }
-
-                $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
-                $this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
-                $completion = new completion_info($this->get_course());
-                if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
-                    $completion->update_state($this->get_course_module(), COMPLETION_COMPLETE, $USER->id);
-                }
-
-                if (isset($data->submissionstatement)) {
-                    $logmessage = get_string('submissionstatementacceptedlog',
-                                             'mod_assign',
-                                             fullname($USER));
-                    $addtolog = $this->add_to_log('submission statement accepted', $logmessage, '', true);
-                    $params = array(
-                        'context' => $this->context,
-                        'objectid' => $submission->id
-                    );
-                    $event = \mod_assign\event\statement_accepted::create($params);
-                    $event->set_legacy_logdata($addtolog);
-                    $event->trigger();
-                }
-                $logdata = $this->add_to_log('submit for grading', $this->format_submission_for_log($submission), '', true);
-                $this->notify_graders($submission);
-                $this->notify_student_submission_receipt($submission);
-
-                // Trigger assessable_submitted event on submission.
-                $params = array(
-                    'context' => context_module::instance($this->get_course_module()->id),
-                    'objectid' => $submission->id,
-                    'other' => array(
-                        'submission_editable' => false
-                    )
-                );
-                $event = \mod_assign\event\assessable_submitted::create($params);
-                $event->set_legacy_logdata($logdata);
-                $event->trigger();
-            }
+            return $this->submit_for_grading($data);
         }
         return true;
     }
@@ -4565,9 +4596,30 @@ class assign {
      * @param mixed $extensionduedate Either an integer date or null
      * @return boolean
      */
-    protected function save_user_extension($userid, $extensionduedate) {
+    public function save_user_extension($userid, $extensionduedate) {
         global $DB;
 
+        // Need submit permission to submit an assignment.
+        require_capability('mod/assign:grantextension', $this->context);
+
+        if (!is_enrolled($this->get_course_context(), $userid)) {
+            return false;
+        }
+        if (!has_capability('mod/assign:submit', $this->context, $userid)) {
+            return false;
+        }
+
+        if ($this->get_instance()->duedate && $extensionduedate) {
+            if ($this->get_instance()->duedate > $extensionduedate) {
+                return false;
+            }
+        }
+        if ($this->get_instance()->allowsubmissionsfromdate && $extensionduedate) {
+            if ($this->get_instance()->allowsubmissionsfromdate > $extensionduedate) {
+                return false;
+            }
+        }
+
         $flags = $this->get_user_flags($userid, true);
         $flags->extensionduedate = $extensionduedate;
 
@@ -4599,9 +4651,6 @@ class assign {
         // Include extension form.
         require_once($CFG->dirroot . '/mod/assign/extensionform.php');
 
-        // Need submit permission to submit an assignment.
-        require_capability('mod/assign:grantextension', $this->context);
-
         $batchusers = optional_param('selectedusers', '', PARAM_SEQUENCE);
         $userid = 0;
         if (!$batchusers) {
@@ -4834,11 +4883,12 @@ class assign {
      *
      * @return void
      */
-    protected function process_reveal_identities() {
-        global $DB, $CFG;
+    public function reveal_identities() {
+        global $DB;
 
         require_capability('mod/assign:revealidentities', $this->context);
-        if (!confirm_sesskey()) {
+
+        if ($this->get_instance()->revealidentities || empty($this->get_instance()->blindmarking)) {
             return false;
         }
 
@@ -4882,6 +4932,20 @@ class assign {
         $event->trigger();
     }
 
+    /**
+     * Reveal student identities to markers (and the gradebook).
+     *
+     * @return void
+     */
+    protected function process_reveal_identities() {
+
+        if (!confirm_sesskey()) {
+            return false;
+        }
+
+        return $this->reveal_identities();
+    }
+
 
     /**
      * Save grading options.
@@ -5009,15 +5073,30 @@ class assign {
     }
 
     /**
-     * Copy the current assignment submission from the last submitted attempt.
+     * Require a valid sess key and then call copy_previous_attempt.
      *
      * @param  array $notices Any error messages that should be shown
      *                        to the user at the top of the edit submission form.
      * @return bool
      */
     protected function process_copy_previous_attempt(&$notices) {
+        require_sesskey();
+
+        return copy_previous_attempt($notices);
+    }
+
+    /**
+     * Copy the current assignment submission from the last submitted attempt.
+     *
+     * @param  array $notices Any error messages that should be shown
+     *                        to the user at the top of the edit submission form.
+     * @return bool
+     */
+    public function copy_previous_attempt(&$notices) {
         global $USER, $CFG;
 
+        require_capability('mod/assign:submit', $this->context);
+
         $instance = $this->get_instance();
         if ($instance->teamsubmission) {
             $submission = $this->get_group_submission($USER->id, 0, true);
@@ -5128,121 +5207,137 @@ class assign {
     }
 
     /**
-     * Save assignment submission.
+     * Save assignment submission for the current user.
      *
-     * @param  moodleform $mform
+     * @param  stdClass $data
      * @param  array $notices Any error messages that should be shown
-     *                        to the user at the top of the edit submission form.
+     *                        to the user.
      * @return bool
      */
-    protected function process_save_submission(&$mform, &$notices) {
-        global $USER, $CFG;
-
-        // Include submission form.
-        require_once($CFG->dirroot . '/mod/assign/submission_form.php');
+    public function save_submission(stdClass $data, & $notices) {
+        global $CFG, $USER;
 
-        // Need submit permission to submit an assignment.
         require_capability('mod/assign:submit', $this->context);
-        require_sesskey();
-        if (!$this->submissions_open()) {
-            $notices[] = get_string('duedatereached', 'assign');
-            return false;
-        }
         $instance = $this->get_instance();
 
-        $data = new stdClass();
-        $mform = new mod_assign_submission_form(null, array($this, $data));
-        if ($mform->is_cancelled()) {
-            return true;
+        if ($instance->teamsubmission) {
+            $submission = $this->get_group_submission($USER->id, 0, true);
+        } else {
+            $submission = $this->get_user_submission($USER->id, true);
+        }
+        if ($instance->submissiondrafts) {
+            $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
+        } else {
+            $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
         }
-        if ($data = $mform->get_data()) {
-            if ($instance->teamsubmission) {
-                $submission = $this->get_group_submission($USER->id, 0, true);
-            } else {
-                $submission = $this->get_user_submission($USER->id, true);
-            }
-            if ($instance->submissiondrafts) {
-                $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
-            } else {
-                $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
-            }
 
-            $flags = $this->get_user_flags($USER->id, false);
+        $flags = $this->get_user_flags($USER->id, false);
 
-            // Get the flags to check if it is locked.
-            if ($flags && $flags->locked) {
-                print_error('submissionslocked', 'assign');
-                return true;
-            }
+        // Get the flags to check if it is locked.
+        if ($flags && $flags->locked) {
+            print_error('submissionslocked', 'assign');
+            return true;
+        }
 
-            $pluginerror = false;
-            foreach ($this->submissionplugins as $plugin) {
-                if ($plugin->is_enabled() && $plugin->is_visible()) {
-                    if (!$plugin->save($submission, $data)) {
-                        $notices[] = $plugin->get_error();
-                        $pluginerror = true;
-                    }
+        $pluginerror = false;
+        foreach ($this->submissionplugins as $plugin) {
+            if ($plugin->is_enabled() && $plugin->is_visible()) {
+                if (!$plugin->save($submission, $data)) {
+                    $notices[] = $plugin->get_error();
+                    $pluginerror = true;
                 }
             }
-            $allempty = $this->submission_empty($submission);
-            if ($pluginerror || $allempty) {
-                if ($allempty) {
-                    $notices[] = get_string('submissionempty', 'mod_assign');
-                }
-                return false;
+        }
+        $allempty = $this->submission_empty($submission);
+        if ($pluginerror || $allempty) {
+            if ($allempty) {
+                $notices[] = get_string('submissionempty', 'mod_assign');
             }
+            return false;
+        }
 
-            $this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
-
-            // Logging.
-            if (isset($data->submissionstatement)) {
-                $logmessage = get_string('submissionstatementacceptedlog',
-                                         'mod_assign',
-                                         fullname($USER));
-                $addtolog = $this->add_to_log('submission statement accepted', $logmessage, '', true);
-                $params = array(
-                    'context' => $this->context,
-                    'objectid' => $submission->id
-                );
-                $event = \mod_assign\event\statement_accepted::create($params);
-                $event->set_legacy_logdata($addtolog);
-                $event->trigger();
-            }
+        $this->update_submission($submission, $USER->id, true, $instance->teamsubmission);
 
-            $addtolog = $this->add_to_log('submit', $this->format_submission_for_log($submission), '', true);
+        // Logging.
+        if (isset($data->submissionstatement)) {
+            $logmessage = get_string('submissionstatementacceptedlog',
+                                     'mod_assign',
+                                     fullname($USER));
+            $this->add_to_log('submission statement accepted', $logmessage);
+            $addtolog = $this->add_to_log('submission statement accepted', $logmessage, '', true);
             $params = array(
                 'context' => $this->context,
                 'objectid' => $submission->id
             );
-            $event = \mod_assign\event\submission_updated::create($params);
+            $event = \mod_assign\event\statement_accepted::create($params);
             $event->set_legacy_logdata($addtolog);
             $event->trigger();
+        }
+        $addtolog = $this->add_to_log('submit', $this->format_submission_for_log($submission), '', true);
+        $params = array(
+            'context' => $this->context,
+            'objectid' => $submission->id
+        );
+        $event = \mod_assign\event\submission_updated::create($params);
+        $event->set_legacy_logdata($addtolog);
+        $event->trigger();
 
-            $complete = COMPLETION_INCOMPLETE;
-            if ($submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
-                $complete = COMPLETION_COMPLETE;
-            }
-            $completion = new completion_info($this->get_course());
-            if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
-                $completion->update_state($this->get_course_module(), $complete, $USER->id);
-            }
+        $complete = COMPLETION_INCOMPLETE;
+        if ($submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
+            $complete = COMPLETION_COMPLETE;
+        }
+        $completion = new completion_info($this->get_course());
+        if ($completion->is_enabled($this->get_course_module()) && $instance->completionsubmit) {
+            $completion->update_state($this->get_course_module(), $complete, $USER->id);
+        }
 
-            if (!$instance->submissiondrafts) {
-                $this->notify_student_submission_receipt($submission);
-                $this->notify_graders($submission);
-                // Trigger assessable_submitted event on submission.
-                $params = array(
-                    'context' => context_module::instance($this->get_course_module()->id),
-                    'objectid' => $submission->id,
-                    'other' => array(
-                        'submission_editable' => true
-                    )
-                );
-                $event = \mod_assign\event\assessable_submitted::create($params);
-                $event->trigger();
-            }
+        if (!$instance->submissiondrafts) {
+            $this->notify_student_submission_receipt($submission);
+            $this->notify_graders($submission);
+            // Trigger assessable_submitted event on submission.
+            $params = array(
+                'context' => context_module::instance($this->get_course_module()->id),
+                'objectid' => $submission->id,
+                'other' => array(
+                    'submission_editable' => true
+                )
+            );
+            $event = \mod_assign\event\assessable_submitted::create($params);
+            $event->trigger();
+        }
+        return true;
+    }
+
+    /**
+     * Save assignment submission.
+     *
+     * @param  moodleform $mform
+     * @param  array $notices Any error messages that should be shown
+     *                        to the user at the top of the edit submission form.
+     * @return bool
+     */
+    protected function process_save_submission(&$mform, &$notices) {
+        global $CFG;
+
+        // Include submission form.
+        require_once($CFG->dirroot . '/mod/assign/submission_form.php');
+
+        // Need submit permission to submit an assignment.
+        require_sesskey();
+        if (!$this->submissions_open()) {
+            $notices[] = get_string('duedatereached', 'assign');
+            return false;
+        }
+        $instance = $this->get_instance();
+
+        $data = new stdClass();
+        $mform = new mod_assign_submission_form(null, array($this, $data));
+        if ($mform->is_cancelled()) {
             return true;
         }
+        if ($data = $mform->get_data()) {
+            return $this->save_submission($data, $notices);
+        }
         return false;
     }
 
@@ -5286,6 +5381,7 @@ class assign {
      * This is specific to the assignment, marker and student.
      *
      * @param int $userid - The student userid
+     * @param stdClass|false $grade - The grade record
      * @param bool $gradingdisabled
      * @return mixed gradingform_instance|null $gradinginstance
      */
@@ -5677,21 +5773,15 @@ class assign {
 
     /**
      * Revert to draft.
-     * Uses url parameter userid
      *
      * @param int $userid
-     * @return void
+     * @return boolean
      */
-    protected function process_revert_to_draft($userid = 0) {
+    public function revert_to_draft($userid) {
         global $DB, $USER;
 
         // Need grade permission.
         require_capability('mod/assign:grade', $this->context);
-        require_sesskey();
-
-        if (!$userid) {
-            $userid = required_param('userid', PARAM_INT);
-        }
 
         if ($this->get_instance()->teamsubmission) {
             $submission = $this->get_group_submission($userid, 0, false);
@@ -5700,7 +5790,7 @@ class assign {
         }
 
         if (!$submission) {
-            return;
+            return false;
         }
         $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
         $this->update_submission($submission, $userid, true, $this->get_instance()->teamsubmission);
@@ -5739,39 +5829,51 @@ class assign {
         $event = \mod_assign\event\submission_status_updated::create($params);
         $event->set_legacy_logdata($addtolog);
         $event->trigger();
+        return true;
     }
 
     /**
-     * Lock the process.
-     * Uses url parameter userid
+     * Revert to draft.
+     * Uses url parameter userid if userid not supplied as a parameter.
      *
      * @param int $userid
-     * @return void
+     * @return boolean
      */
-    protected function process_lock($userid = 0) {
-        global $USER, $DB;
-
-        // Need grade permission.
-        require_capability('mod/assign:grade', $this->context);
+    protected function process_revert_to_draft($userid = 0) {
         require_sesskey();
 
         if (!$userid) {
             $userid = required_param('userid', PARAM_INT);
         }
 
+        return $this->revert_to_draft($userid);
+    }
+
+    /**
+     * Prevent student updates to this submission
+     *
+     * @param int $userid
+     * @return bool
+     */
+    public function lock_submission($userid) {
+        global $USER, $DB;
+        // Need grade permission.
+        require_capability('mod/assign:grade', $this->context);
+
         // Give each submission plugin a chance to process the locking.
         $plugins = $this->get_submission_plugins();
         $submission = $this->get_user_submission($userid, false);
-        foreach ($plugins as $plugin) {
-            if ($plugin->is_enabled() && $plugin->is_visible()) {
-                $plugin->lock($submission);
-            }
-        }
 
         $flags = $this->get_user_flags($userid, true);
         $flags->locked = 1;
         $this->update_user_flags($flags);
 
+        foreach ($plugins as $plugin) {
+            if ($plugin->is_enabled() && $plugin->is_visible()) {
+                $plugin->lock($submission, $flags);
+            }
+        }
+
         $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
 
         $logmessage = get_string('locksubmissionforstudent',
@@ -5786,6 +5888,7 @@ class assign {
         $event = \mod_assign\event\submission_locked::create($params);
         $event->set_legacy_logdata($addtolog);
         $event->trigger();
+        return true;
     }
 
 
@@ -5896,34 +5999,49 @@ class assign {
 
 
     /**
-     * Unlock the process.
+     * Prevent student updates to this submission.
+     * Uses url parameter userid.
      *
      * @param int $userid
      * @return void
      */
-    protected function process_unlock($userid = 0) {
-        global $USER, $DB;
+    protected function process_lock_submission($userid = 0) {
 
-        // Need grade permission.
-        require_capability('mod/assign:grade', $this->context);
         require_sesskey();
 
         if (!$userid) {
             $userid = required_param('userid', PARAM_INT);
         }
+
+        return $this->lock_submission($userid);
+    }
+
+    /**
+     * Unlock the student submission.
+     *
+     * @param int $userid
+     * @return bool
+     */
+    public function unlock_submission($userid) {
+        global $USER, $DB;
+
+        // Need grade permission.
+        require_capability('mod/assign:grade', $this->context);
+
         // Give each submission plugin a chance to process the unlocking.
         $plugins = $this->get_submission_plugins();
         $submission = $this->get_user_submission($userid, false);
-        foreach ($plugins as $plugin) {
-            if ($plugin->is_enabled() && $plugin->is_visible()) {
-                $plugin->unlock($submission);
-            }
-        }
 
         $flags = $this->get_user_flags($userid, true);
         $flags->locked = 0;
         $this->update_user_flags($flags);
 
+        foreach ($plugins as $plugin) {
+            if ($plugin->is_enabled() && $plugin->is_visible()) {
+                $plugin->unlock($submission, $flags);
+            }
+        }
+
         $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
 
         $logmessage = get_string('unlocksubmissionforstudent',
@@ -5938,6 +6056,25 @@ class assign {
         $event = \mod_assign\event\submission_unlocked::create($params);
         $event->set_legacy_logdata($addtolog);
         $event->trigger();
+        return true;
+    }
+
+    /**
+     * Unlock the student submission.
+     * Uses url parameter userid.
+     *
+     * @param int $userid
+     * @return bool
+     */
+    protected function process_unlock_submission($userid = 0) {
+
+        require_sesskey();
+
+        if (!$userid) {
+            $userid = required_param('userid', PARAM_INT);
+        }
+
+        return $this->unlock_submission($userid);
     }
 
     /**
@@ -5945,7 +6082,7 @@ class assign {
      *
      * @param stdClass $formdata - the data from the form
      * @param int $userid - the user to apply the grade to
-     * @param int attemptnumber - The attempt number to apply the grade to.
+     * @param int $attemptnumber - The attempt number to apply the grade to.
      * @return void
      */
     protected function apply_grade_to_user($formdata, $userid, $attemptnumber) {
@@ -6051,6 +6188,92 @@ class assign {
     }
 
 
+    /**
+     * Save grade update.
+     *
+     * @param int $userid
+     * @param  stdClass $data
+     * @return bool - was the grade saved
+     */
+    public function save_grade($userid, $data) {
+
+        // Need grade permission.
+        require_capability('mod/assign:grade', $this->context);
+
+        $instance = $this->get_instance();
+        $submission = null;
+        if ($instance->teamsubmission) {
+            $submission = $this->get_group_submission($userid, 0, false, $data->attemptnumber);
+        } else {
+            $submission = $this->get_user_submission($userid, false, $data->attemptnumber);
+        }
+        if ($instance->teamsubmission && $data->applytoall) {
+            $groupid = 0;
+            if ($this->get_submission_group($userid)) {
+                $group = $this->get_submission_group($userid);
+                if ($group) {
+                    $groupid = $group->id;
+                }
+            }
+            $members = $this->get_submission_group_members($groupid, true);
+            foreach ($members as $member) {
+                // User may exist in multple groups (which should put them in the default group).
+                $this->apply_grade_to_user($data, $member->id, $data->attemptnumber);
+                $this->process_outcomes($member->id, $data);
+            }
+        } else {
+            $this->apply_grade_to_user($data, $userid, $data->attemptnumber);
+
+            $this->process_outcomes($userid, $data);
+        }
+        $maxattemptsreached = !empty($submission) &&
+                              $submission->attemptnumber >= ($instance->maxattempts - 1) &&
+                              $instance->maxattempts != ASSIGN_UNLIMITED_ATTEMPTS;
+        $shouldreopen = false;
+        if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
+            // Check the gradetopass from the gradebook.
+            $gradinginfo = grade_get_grades($this->get_course()->id,
+                                            'mod',
+                                            'assign',
+                                            $instance->id,
+                                            $userid);
+
+            // What do we do if the grade has not been added to the gradebook (e.g. blind marking)?
+            $gradingitem = null;
+            $gradebookgrade = null;
+            if (isset($gradinginfo->items[0])) {
+                $gradingitem = $gradinginfo->items[0];
+                $gradebookgrade = $gradingitem->grades[$userid];
+            }
+
+            if ($gradebookgrade) {
+                // TODO: This code should call grade_grade->is_passed().
+                $shouldreopen = true;
+                if (is_null($gradebookgrade->grade)) {
+                    $shouldreopen = false;
+                }
+                if (empty($gradingitem->gradepass) || $gradingitem->gradepass == $gradingitem->grademin) {
+                    $shouldreopen = false;
+                }
+                if ($gradebookgrade->grade >= $gradingitem->gradepass) {
+                    $shouldreopen = false;
+                }
+            }
+        }
+        if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL &&
+                !empty($data->addattempt)) {
+            $shouldreopen = true;
+        }
+        // Never reopen if we are editing a previous attempt.
+        if ($data->attemptnumber != -1) {
+            $shouldreopen = false;
+        }
+        if ($shouldreopen && !$maxattemptsreached) {
+            $this->add_attempt($userid);
+        }
+        return true;
+    }
+
     /**
      * Save grade.
      *
@@ -6062,8 +6285,6 @@ class assign {
         // Include grade form.
         require_once($CFG->dirroot . '/mod/assign/gradeform.php');
 
-        // Need submit permission to submit an assignment.
-        require_capability('mod/assign:grade', $this->context);
         require_sesskey();
 
         $instance = $this->get_instance();
@@ -6102,80 +6323,10 @@ class assign {
                                            array('class'=>'gradeform'));
 
         if ($formdata = $mform->get_data()) {
-            $submission = null;
-            if ($instance->teamsubmission) {
-                $submission = $this->get_group_submission($userid, 0, false, $attemptnumber);
-            } else {
-                $submission = $this->get_user_submission($userid, false, $attemptnumber);
-            }
-            if ($instance->teamsubmission && $formdata->applytoall) {
-                $groupid = 0;
-                if ($this->get_submission_group($userid)) {
-                    $group = $this->get_submission_group($userid);
-                    if ($group) {
-                        $groupid = $group->id;
-                    }
-                }
-                $members = $this->get_submission_group_members($groupid, true);
-                foreach ($members as $member) {
-                    // User may exist in multple groups (which should put them in the default group).
-                    $this->apply_grade_to_user($formdata, $member->id, $attemptnumber);
-                    $this->process_outcomes($member->id, $formdata);
-                }
-            } else {
-                $this->apply_grade_to_user($formdata, $userid, $attemptnumber);
-
-                $this->process_outcomes($userid, $formdata);
-            }
-            $maxattemptsreached = !empty($submission) &&
-                                  $submission->attemptnumber >= ($instance->maxattempts - 1) &&
-                                  $instance->maxattempts != ASSIGN_UNLIMITED_ATTEMPTS;
-            $shouldreopen = false;
-            if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
-                // Check the gradetopass from the gradebook.
-                $gradinginfo = grade_get_grades($this->get_course()->id,
-                                                'mod',
-                                                'assign',
-                                                $instance->id,
-                                                $userid);
-
-                // What do we do if the grade has not been added to the gradebook (e.g. blind marking)?
-                $gradingitem = null;
-                $gradebookgrade = null;
-                if (isset($gradinginfo->items[0])) {
-                    $gradingitem = $gradinginfo->items[0];
-                    $gradebookgrade = $gradingitem->grades[$userid];
-                }
-
-                if ($gradebookgrade) {
-                    // TODO: This code should call grade_grade->is_passed().
-                    $shouldreopen = true;
-                    if (is_null($gradebookgrade->grade)) {
-                        $shouldreopen = false;
-                    }
-                    if (empty($gradingitem->gradepass) || $gradingitem->gradepass == $gradingitem->grademin) {
-                        $shouldreopen = false;
-                    }
-                    if ($gradebookgrade->grade >= $gradingitem->gradepass) {
-                        $shouldreopen = false;
-                    }
-                }
-            }
-            if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL &&
-                    !empty($formdata->addattempt)) {
-                $shouldreopen = true;
-            }
-            // Never reopen if we are editing a previous attempt.
-            if ($attemptnumber != -1) {
-                $shouldreopen = false;
-            }
-            if ($shouldreopen && !$maxattemptsreached) {
-                $this->process_add_attempt($userid);
-            }
+            return $this->save_grade($userid, $formdata);
         } else {
             return false;
         }
-        return true;
     }
 
     /**
@@ -6288,15 +6439,26 @@ class assign {
     }
 
     /**
-     * Add a new attempt for a user.
+     * Check for a sess key and then call add_attempt.
      *
      * @param int $userid int The user to add the attempt for
      * @return bool - true if successful.
      */
     protected function process_add_attempt($userid) {
-        require_capability('mod/assign:grade', $this->context);
         require_sesskey();
 
+        return $this->add_attempt($userid);
+    }
+
+    /**
+     * Add a new attempt for a user.
+     *
+     * @param int $userid int The user to add the attempt for
+     * @return bool - true if successful.
+     */
+    protected function add_attempt($userid) {
+        require_capability('mod/assign:grade', $this->context);
+
         if ($this->get_instance()->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) {
             return false;
         }
@@ -6457,6 +6619,7 @@ class assign {
     /**
      * Lookup this user id and return the unique id for this assignment.
      *
+     * @param int $assignid The assignment id
      * @param int $userid The userid to lookup
      * @return int The unique id
      */
index edfe6eb..1cd183c 100644 (file)
@@ -265,6 +265,11 @@ class mod_assign_mod_form extends moodleform_mod {
         $assignment->plugin_data_preprocessing($defaultvalues);
     }
 
+    /**
+     * Add any custom completion rules to the form.
+     *
+     * @return array Contains the names of the added form elements
+     */
     public function add_completion_rules() {
         $mform =& $this->_form;
 
@@ -272,6 +277,12 @@ class mod_assign_mod_form extends moodleform_mod {
         return array('completionsubmit');
     }
 
+    /**
+     * Determines if completion is enabled for this module.
+     *
+     * @param array $data
+     * @return bool
+     */
     public function completion_rule_enabled($data) {
         return !empty($data['completionsubmit']);
     }
index 5e40398..6b03323 100644 (file)
@@ -42,6 +42,7 @@ class assign_submit_for_grading_page implements renderable {
      * Constructor
      * @param string $notifications - Any mesages to display
      * @param int $coursemoduleid
+     * @param moodleform $confirmform
      */
     public function __construct($notifications, $coursemoduleid, $confirmform) {
         $this->notifications = $notifications;
@@ -69,6 +70,7 @@ class assign_gradingmessage implements renderable {
      * Constructor
      * @param string $heading This is the heading to display
      * @param string $message This is the message to display
+     * @param int $coursemoduleid
      */
     public function __construct($heading, $message, $coursemoduleid) {
         $this->heading = $heading;
@@ -404,6 +406,7 @@ class assign_submission_status implements renderable {
      * @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 bool $blindmarking - Should we hide student identities from graders?
+     * @param string $gradingcontrollerpreview
      * @param string $attemptreopenmethod - The method of reopening student attempts.
      * @param int $maxattempts - How many attempts can a student make?
      */
@@ -493,14 +496,14 @@ class assign_attempt_history implements renderable {
     /**
      * Constructor
      *
-     * @param $submissions
-     * @param $grades
-     * @param $submissionplugins
-     * @param $feedbackplugins
-     * @param $coursemoduleid
-     * @param $returnaction
-     * @param $returnparams
-     * @param $cangrade
+     * @param array $submissions
+     * @param array $grades
+     * @param array $submissionplugins
+     * @param array $feedbackplugins
+     * @param int $coursemoduleid
+     * @param string $returnaction
+     * @param array $returnparams
+     * @param bool $cangrade
      */
     public function __construct($submissions,
                                 $grades,
@@ -648,8 +651,8 @@ class assign_course_index_summary implements renderable {
     /**
      * constructor
      *
-     * @param $usesections boolean - True if this course format uses sections
-     * @param $courseformatname string - The id of this course format
+     * @param boolean $usesections - True if this course format uses sections
+     * @param string $courseformatname - The id of this course format
      */
     public function __construct($usesections, $courseformatname) {
         $this->usesections = $usesections;
index f3a0306..f9058c8 100644 (file)
@@ -221,14 +221,14 @@ class mod_assign_renderer extends plugin_renderer_base {
         }
 
         $this->page->set_title(get_string('pluginname', 'assign'));
-        $this->page->set_heading($header->assign->name);
+        $this->page->set_heading($this->page->course->fullname);
 
         $o .= $this->output->header();
+        $heading = format_string($header->assign->name, false, array('context' => $header->context));
+        $o .= $this->output->heading($heading);
         if ($header->preface) {
             $o .= $header->preface;
         }
-        $heading = format_string($header->assign->name, false, array('context' => $header->context));
-        $o .= $this->output->heading($heading);
 
         if ($header->showintro) {
             $o .= $this->output->box_start('generalbox boxaligncenter', 'intro');
index 8f575e5..2447270 100644 (file)
@@ -23,7 +23,9 @@
  */
 
 /**
- * restore subplugin class that provides the necessary information
+ * Restore subplugin class.
+ *
+ * Provides the necessary information
  * needed to restore one assign_submission subplugin.
  *
  * @package assignsubmission_file
index e9d72e4..a2c2c8b 100644 (file)
@@ -249,6 +249,7 @@ class assign_submission_file extends assign_submission_plugin {
      * Produce a list of files suitable for export that represent this feedback or submission
      *
      * @param stdClass $submission The submission
+     * @param stdClass $user The user record - unused
      * @return array - return an array of files indexed by filename
      */
     public function get_files(stdClass $submission, stdClass $user) {
@@ -477,4 +478,18 @@ class assign_submission_file extends assign_submission_plugin {
         }
         return true;
     }
+
+    /**
+     * Return a description of external params suitable for uploading a file submission from a webservice.
+     *
+     * @return external_description|null
+     */
+    public function get_external_parameters() {
+        return array(
+            'files_filemanager' => new external_value(
+                PARAM_INT,
+                'The id of a draft area containing files for this submission.'
+            )
+        );
+    }
 }
index bfa2342..ac97586 100644 (file)
@@ -23,7 +23,9 @@
  */
 
 /**
- * restore subplugin class that provides the necessary information needed to restore
+ * Restore subplugin class.
+ *
+ * Provides the necessary information needed to restore
  * one assign_submission subplugin.
  *
  * @package assignsubmission_onlinetext
index 6f44e4e..87fcc19 100644 (file)
@@ -495,6 +495,20 @@ class assign_submission_onlinetext extends assign_submission_plugin {
         }
         return true;
     }
+
+    /**
+     * Return a description of external params suitable for uploading an onlinetext submission from a webservice.
+     *
+     * @return external_description|null
+     */
+    public function get_external_parameters() {
+        $editorparams = array('text' => new external_value(PARAM_TEXT, 'The text for this submission.'),
+                              'format' => new external_value(PARAM_INT, 'The format for this submission'),
+                              'itemid' => new external_value(PARAM_INT, 'The draft area id for files attached to the submission'));
+        $editorstructure = new external_single_structure($editorparams);
+        return array('onlinetext_editor' => $editorstructure);
+    }
+
 }
 
 
index 5b48a38..70388cb 100644 (file)
@@ -79,28 +79,32 @@ abstract class assign_submission_plugin extends assign_plugin {
     /**
      * Copy the plugin specific submission data to a new submission record.
      *
+     * @param stdClass $oldsubmission - Old submission record
+     * @param stdClass $submission - New submission record
      * @return bool
      */
     public function copy_submission( stdClass $oldsubmission, stdClass $submission) {
         return true;
     }
 
-    /*
+    /**
      * Carry out any extra processing required when the work is locked.
      *
-     * @param stdClass $submission - assign_submission data
+     * @param stdClass|false $submission - assign_submission data if any
+     * @param stdClass $flags - User flags record
      * @return void
      */
-    public function lock(stdClass $submission) {
+    public function lock($submission, stdClass $flags) {
     }
 
     /**
      * Carry out any extra processing required when the work is unlocked.
      *
-     * @param stdClass $submission - assign_submission data
+     * @param stdClass|false $submission - assign_submission data if any
+     * @param stdClass $flags - User flags record
      * @return void
      */
-    public function unlock(stdClass $submission) {
+    public function unlock($submission, stdClass $flags) {
     }
 
     /**
index cae9553..9155540 100644 (file)
@@ -223,10 +223,6 @@ class mod_assign_base_testcase extends advanced_testcase {
  */
 class testable_assign extends assign {
 
-    public function testable_process_reveal_identities() {
-        return parent::process_reveal_identities();
-    }
-
     public function testable_show_intro() {
         return parent::show_intro();
     }
@@ -259,10 +255,6 @@ class testable_assign extends assign {
         return parent::process_add_attempt($userid);
     }
 
-    public function testable_process_lock($userid = 0) {
-        return parent::process_lock($userid);
-    }
-
     public function testable_process_save_quick_grades($postdata) {
         // Ugly hack to get something into the method.
         global $_POST;
@@ -270,18 +262,6 @@ class testable_assign extends assign {
         return parent::process_save_quick_grades();
     }
 
-    public function testable_process_unlock($userid = 0) {
-        return parent::process_unlock($userid);
-    }
-
-    public function testable_process_copy_previous_attempt(&$notices) {
-        return parent::process_copy_previous_attempt($notices);
-    }
-
-    public function testable_process_revert_to_draft($userid = 0) {
-        return parent::process_revert_to_draft($userid);
-    }
-
     public function testable_process_set_batch_marking_allocation($selectedusers, $markerid) {
         // Ugly hack to get something into the method.
         global $_POST;
index 88a4aa2..eebc750 100644 (file)
@@ -41,7 +41,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
     /**
      * Test get_grades
      */
-    public function test_get_grades () {
+    public function test_get_grades() {
         global $DB, $USER;
 
         $this->resetAfterTest(true);
@@ -118,7 +118,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
     /**
      * Test get_assignments
      */
-    public function test_get_assignments () {
+    public function test_get_assignments() {
         global $DB, $USER;
 
         $this->resetAfterTest(true);
@@ -218,7 +218,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
     /**
      * Test get_submissions
      */
-    public function test_get_submissions () {
+    public function test_get_submissions() {
         global $DB, $USER;
 
         $this->resetAfterTest(true);
@@ -307,7 +307,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
     /**
      * Test get_user_flags
      */
-    public function test_get_user_flags () {
+    public function test_get_user_flags() {
         global $DB, $USER;
 
         $this->resetAfterTest(true);
@@ -378,7 +378,7 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
     /**
      * Test get_user_mappings
      */
-    public function test_get_user_mappings () {
+    public function test_get_user_mappings() {
         global $DB, $USER;
 
         $this->resetAfterTest(true);
@@ -436,4 +436,611 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
         $this->assertEquals($student->id, $mapping['userid']);
     }
 
+    /**
+     * Test lock_submissions
+     */
+    public function test_lock_submissions() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['assignsubmission_onlinetext_enabled'] = 1;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $student2 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $this->getDataGenerator()->enrol_user($student2->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+
+        // Create a student1 with an online text submission.
+        // Simulate a submission.
+        $this->setUser($student1);
+        $submission = $assign->get_user_submission($student1->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Ready to test.
+        $this->setUser($teacher);
+        $students = array($student1->id, $student2->id);
+        $result = mod_assign_external::lock_submissions($instance->id, $students);
+
+        // Check for 0 warnings.
+        $this->assertEquals(0, count($result));
+
+        $this->setUser($student2);
+        $submission = $assign->get_user_submission($student2->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $notices = array();
+        $this->setExpectedException('moodle_exception');
+        $assign->save_submission($data, $notices);
+    }
+
+    /**
+     * Test unlock_submissions
+     */
+    public function test_unlock_submissions() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['assignsubmission_onlinetext_enabled'] = 1;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $student2 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $this->getDataGenerator()->enrol_user($student2->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+
+        // Create a student1 with an online text submission.
+        // Simulate a submission.
+        $this->setUser($student1);
+        $submission = $assign->get_user_submission($student1->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Ready to test.
+        $this->setUser($teacher);
+        $students = array($student1->id, $student2->id);
+        $result = mod_assign_external::lock_submissions($instance->id, $students);
+
+        // Check for 0 warnings.
+        $this->assertEquals(0, count($result));
+
+        $result = mod_assign_external::unlock_submissions($instance->id, $students);
+
+        // Check for 0 warnings.
+        $this->assertEquals(0, count($result));
+
+        $this->setUser($student2);
+        $submission = $assign->get_user_submission($student2->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $notices = array();
+        $assign->save_submission($data, $notices);
+    }
+
+    /**
+     * Test submit_for_grading
+     */
+    public function test_submit_for_grading() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        set_config('submissionreceipts', 0, 'assign');
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['assignsubmission_onlinetext_enabled'] = 1;
+        $params['submissiondrafts'] = 1;
+        $params['sendnotifications'] = 0;
+        $params['requiresubmissionstatement'] = 1;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+
+        // Create a student1 with an online text submission.
+        // Simulate a submission.
+        $this->setUser($student1);
+        $submission = $assign->get_user_submission($student1->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        $result = mod_assign_external::submit_for_grading($instance->id, false);
+
+        // Should be 1 fail because the submission statement was not aceptted.
+        $this->assertEquals(1, count($result));
+
+        $result = mod_assign_external::submit_for_grading($instance->id, true);
+
+        // Check for 0 warnings.
+        $this->assertEquals(0, count($result));
+
+        $submission = $assign->get_user_submission($student1->id, false);
+
+        $this->assertEquals(ASSIGN_SUBMISSION_STATUS_SUBMITTED, $submission->status);
+    }
+
+    /**
+     * Test save_user_extensions
+     */
+    public function test_save_user_extensions() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+        $this->setUser($teacher);
+
+        $now = time();
+        $yesterday = $now - 24*60*60;
+        $tomorrow = $now + 24*60*60;
+        set_config('submissionreceipts', 0, 'assign');
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['submissiondrafts'] = 1;
+        $params['sendnotifications'] = 0;
+        $params['duedate'] = $yesterday;
+        $params['cutoffdate'] = $now - 10;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+
+        $this->setUser($student1);
+        $result = mod_assign_external::submit_for_grading($instance->id, true);
+
+        // Check for 0 warnings.
+        $this->assertEquals(1, count($result));
+
+        $this->setUser($teacher);
+        $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
+        $this->assertEquals(1, count($result));
+
+        $this->setUser($teacher);
+        $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($yesterday - 10));
+        $this->assertEquals(1, count($result));
+
+        $this->setUser($teacher);
+        $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($tomorrow));
+        $this->assertEquals(0, count($result));
+
+        $this->setUser($student1);
+        $result = mod_assign_external::submit_for_grading($instance->id, true);
+        $this->assertEquals(0, count($result));
+
+        $this->setUser($student1);
+        $result = mod_assign_external::save_user_extensions($instance->id, array($student1->id), array($now, $tomorrow));
+
+    }
+
+    /**
+     * Test reveal_identities
+     */
+    public function test_reveal_identities() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+        $this->setUser($teacher);
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['submissiondrafts'] = 1;
+        $params['sendnotifications'] = 0;
+        $params['blindmarking'] = 1;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+
+        $this->setUser($student1);
+        $this->setExpectedException('required_capability_exception');
+        $result = mod_assign_external::reveal_identities($instance->id);
+        $this->assertEquals(1, count($result));
+        $this->assertEquals(true, $assign->is_blind_marking());
+
+        $this->setUser($teacher);
+        $result = mod_assign_external::reveal_identities($instance->id);
+        $this->assertEquals(0, count($result));
+        $this->assertEquals(false, $assign->is_blind_marking());
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['submissiondrafts'] = 1;
+        $params['sendnotifications'] = 0;
+        $params['blindmarking'] = 0;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+        $result = mod_assign_external::reveal_identities($instance->id);
+        $this->assertEquals(1, count($result));
+        $this->assertEquals(false, $assign->is_blind_marking());
+
+    }
+
+    /**
+     * Test revert_submissions_to_draft
+     */
+    public function test_revert_submissions_to_draft() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        set_config('submissionreceipts', 0, 'assign');
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['sendnotifications'] = 0;
+        $params['submissiondrafts'] = 1;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $student2 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $this->getDataGenerator()->enrol_user($student2->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+
+        // Create a student1 with an online text submission.
+        // Simulate a submission.
+        $this->setUser($student1);
+        $result = mod_assign_external::submit_for_grading($instance->id, true);
+        $this->assertEquals(0, count($result));
+
+        // Ready to test.
+        $this->setUser($teacher);
+        $students = array($student1->id, $student2->id);
+        $result = mod_assign_external::revert_submissions_to_draft($instance->id, array($student1->id));
+
+        // Check for 0 warnings.
+        $this->assertEquals(0, count($result));
+
+    }
+
+    /**
+     * Test save_submission
+     */
+    public function test_save_submission() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+        $this->setUser($teacher);
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['assignsubmission_onlinetext_enabled'] = 1;
+        $params['assignsubmission_file_enabled'] = 1;
+        $params['assignsubmission_file_maxfiles'] = 5;
+        $params['assignsubmission_file_maxsizebytes'] = 1024*1024;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $student2 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $this->getDataGenerator()->enrol_user($student2->id,
+                                              $course->id,
+                                              $studentrole->id);
+        // Create a student1 with an online text submission.
+        // Simulate a submission.
+        $this->setUser($student1);
+
+        // Create a file in a draft area.
+        $draftidfile = file_get_unused_draft_itemid();
+
+        $usercontext = context_user::instance($student1->id);
+        $filerecord = array(
+            'contextid' => $usercontext->id,
+            'component' => 'user',
+            'filearea'  => 'draft',
+            'itemid'    => $draftidfile,
+            'filepath'  => '/',
+            'filename'  => 'testtext.txt',
+        );
+
+        $fs = get_file_storage();
+        $fs->create_file_from_string($filerecord, 'text contents');
+
+        // Create another file in a different draft area.
+        $draftidonlinetext = file_get_unused_draft_itemid();
+
+        $filerecord = array(
+            'contextid' => $usercontext->id,
+            'component' => 'user',
+            'filearea'  => 'draft',
+            'itemid'    => $draftidonlinetext,
+            'filepath'  => '/',
+            'filename'  => 'shouldbeanimage.txt',
+        );
+
+        $fs->create_file_from_string($filerecord, 'image contents (not really)');
+
+        // Now try a submission.
+        $submissionpluginparams = array();
+        $submissionpluginparams['files_filemanager'] = $draftidfile;
+        $onlinetexteditorparams = array('text'=>'Yeeha!',
+                                        'format'=>1,
+                                        'itemid'=>$draftidonlinetext);
+        $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
+        $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
+
+        $this->assertEquals(0, count($result));
+
+    }
+
+    /**
+     * Test save_grade
+     */
+    public function test_save_grade() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+        $this->setUser($teacher);
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['assignfeedback_file_enabled'] = 1;
+        $params['assignfeedback_comments_enabled'] = 1;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $student2 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+        $this->getDataGenerator()->enrol_user($student2->id,
+                                              $course->id,
+                                              $studentrole->id);
+        // Simulate a grade.
+        $this->setUser($teacher);
+
+        // Create a file in a draft area.
+        $draftidfile = file_get_unused_draft_itemid();
+
+        $usercontext = context_user::instance($teacher->id);
+        $filerecord = array(
+            'contextid' => $usercontext->id,
+            'component' => 'user',
+            'filearea'  => 'draft',
+            'itemid'    => $draftidfile,
+            'filepath'  => '/',
+            'filename'  => 'testtext.txt',
+        );
+
+        $fs = get_file_storage();
+        $fs->create_file_from_string($filerecord, 'text contents');
+
+        // Now try a grade.
+        $feedbackpluginparams = array();
+        $feedbackpluginparams['files_filemanager'] = $draftidfile;
+        $feedbackeditorparams = array('text'=>'Yeeha!',
+                                        'format'=>1);
+        $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
+        $result = mod_assign_external::save_grade($instance->id,
+                                                  $student1->id,
+                                                  50.0,
+                                                  -1,
+                                                  true,
+                                                  'released',
+                                                  false,
+                                                  $feedbackpluginparams);
+
+        // No warnings.
+        $this->assertEquals(0, count($result));
+
+        $result = mod_assign_external::get_grades(array($instance->id));
+
+        $this->assertEquals($result['assignments'][0]['grades'][0]['grade'], '50.0');
+    }
+
+    /**
+     * Test copy_previous_attempt
+     */
+    public function test_copy_previous_attempt() {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment and users.
+        $course = self::getDataGenerator()->create_course();
+
+        $teacher = self::getDataGenerator()->create_user();
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        $this->getDataGenerator()->enrol_user($teacher->id,
+                                              $course->id,
+                                              $teacherrole->id);
+        $this->setUser($teacher);
+
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $course->id;
+        $params['assignsubmission_onlinetext_enabled'] = 1;
+        $params['assignsubmission_file_enabled'] = 0;
+        $params['assignfeedback_file_enabled'] = 0;
+        $params['attemptreopenmethod'] = 'manual';
+        $params['maxattempts'] = 5;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $course);
+
+        $student1 = self::getDataGenerator()->create_user();
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->getDataGenerator()->enrol_user($student1->id,
+                                              $course->id,
+                                              $studentrole->id);
+        // Now try a submission.
+        $this->setUser($student1);
+        $draftidonlinetext = file_get_unused_draft_itemid();
+        $submissionpluginparams = array();
+        $onlinetexteditorparams = array('text'=>'Yeeha!',
+                                        'format'=>1,
+                                        'itemid'=>$draftidonlinetext);
+        $submissionpluginparams['onlinetext_editor'] = $onlinetexteditorparams;
+        $submissionpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
+        $result = mod_assign_external::save_submission($instance->id, $submissionpluginparams);
+
+        $this->setUser($teacher);
+        // Add a grade and reopen the attempt.
+        // Now try a grade.
+        $feedbackpluginparams = array();
+        $feedbackpluginparams['files_filemanager'] = file_get_unused_draft_itemid();
+        $feedbackeditorparams = array('text'=>'Yeeha!',
+                                        'format'=>1);
+        $feedbackpluginparams['assignfeedbackcomments_editor'] = $feedbackeditorparams;
+        $result = mod_assign_external::save_grade($instance->id,
+                                                  $student1->id,
+                                                  50.0,
+                                                  -1,
+                                                  true,
+                                                  'released',
+                                                  false,
+                                                  $feedbackpluginparams);
+
+        $this->setUser($student1);
+        // Now copy the previous attempt.
+        $result = mod_assign_external::copy_previous_attempt($instance->id);
+        // No warnings.
+        $this->assertEquals(0, count($result));
+
+        $this->setUser($teacher);
+        $result = mod_assign_external::get_submissions(array($instance->id));
+
+        // Check we are now on the second attempt.
+        $this->assertEquals($result['assignments'][0]['submissions'][0]['attemptnumber'], 1);
+        // Check the plugins data is not empty.
+        $this->assertNotEmpty($result['assignments'][0]['submissions'][0]['plugins']);
+
+    }
 }
index 3ed48e8..ed10b06 100644 (file)
@@ -83,26 +83,31 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
 
         // Test students cannot reveal identities.
         $nopermission = false;
+        $this->students[0]->ignoresesskey = true;
         $this->setUser($this->students[0]);
         $this->setExpectedException('required_capability_exception');
-        $assign->testable_process_reveal_identities();
+        $assign->reveal_identities();
+        $this->students[0]->ignoresesskey = false;
 
         // Test teachers cannot reveal identities.
         $nopermission = false;
+        $this->teachers[0]->ignoresesskey = true;
         $this->setUser($this->teachers[0]);
         $this->setExpectedException('required_capability_exception');
-        $assign->testable_process_reveal_identities();
+        $assign->reveal_identities();
+        $this->teachers[0]->ignoresesskey = false;
 
         // Test sesskey is required.
         $this->setUser($this->editingteachers[0]);
         $this->setExpectedException('moodle_exception');
-        $assign->testable_process_reveal_identities();
+        $assign->reveal_identities();
 
         // Test editingteacher can reveal identities if sesskey is ignored.
         $this->editingteachers[0]->ignoresesskey = true;
         $this->setUser($this->editingteachers[0]);
-        $assign->testable_process_reveal_identities();
+        $assign->reveal_identities();
         $this->assertEquals(false, $assign->is_blind_marking());
+        $this->editingteachers[0]->ignoresesskey = false;
 
         // Test student names are visible.
         $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
@@ -699,6 +704,28 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         $this->assertCount(4, $assign->testable_get_graders($this->students[0]->id));
     }
 
+    public function test_group_members_only() {
+        global $CFG;
+
+        $this->setAdminUser();
+        $this->create_extra_users();
+        $CFG->enablegroupmembersonly = true;
+        $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
+        groups_assign_grouping($grouping->id, $this->groups[0]->id);
+
+        // Force create an assignment with SEPARATEGROUPS.
+        $instance = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id),
+            array('groupmembersonly' => SEPARATEGROUPS, 'groupingid' => $grouping->id));
+
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+        $assign = new testable_assign($context, $cm, $this->course);
+
+        $this->setUser($this->teachers[0]);
+        $this->assertCount(5, $assign->list_participants(0, true));
+
+    }
+
     public function test_get_uniqueid_for_user() {
         $this->setUser($this->editingteachers[0]);
         $assign = $this->create_instance();
@@ -1016,7 +1043,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         $assign = $this->create_instance();
         $sink = $this->redirectEvents();
 
-        $assign->testable_process_lock($this->students[0]->id);
+        $assign->lock_submission($this->students[0]->id);
 
         $events = $sink->get_events();
         $this->assertCount(1, $events);
@@ -1049,7 +1076,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         $assign = $this->create_instance(array('blindmarking'=>1));
         $sink = $this->redirectEvents();
 
-        $assign->testable_process_reveal_identities();
+        $assign->reveal_identities();
 
         $events = $sink->get_events();
         $this->assertCount(1, $events);
@@ -1083,7 +1110,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
 
         $sink = $this->redirectEvents();
-        $assign->testable_process_revert_to_draft($this->students[0]->id);
+        $assign->revert_to_draft($this->students[0]->id);
 
         $events = $sink->get_events();
         $this->assertCount(1, $events);
@@ -1191,7 +1218,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
 
         $sink = $this->redirectEvents();
         $notices = null;
-        $assign->testable_process_copy_previous_attempt($notices);
+        $assign->copy_previous_attempt($notices);
 
         $events = $sink->get_events();
         $this->assertCount(1, $events);
@@ -1221,7 +1248,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         $assign = $this->create_instance();
         $sink = $this->redirectEvents();
 
-        $assign->testable_process_unlock($this->students[0]->id);
+        $assign->unlock_submission($this->students[0]->id);
 
         $events = $sink->get_events();
         $this->assertCount(1, $events);
index 1f513fe..44c2f89 100644 (file)
@@ -3,6 +3,11 @@ This files describes API changes in the assign code.
 === 2.6 ===
 * To see submission/grades of inactive users, user should have moodle/course:viewsuspendedusers capability.
 * count_* functions will return only active participants.
+* assign_submission_plugin->lock and unlock methods have an additional parameter for user flags. A user will not
+  always have a submission record when the submission is locked/unlocked.
+* Submission and feedback plugins can now participate in webservices. The plugin must implement get_external_parameters()
+  to describe the parameters it is expecting from the mod_assign_save_grade or mod_assign_save_submission functions. The
+  plugin will then handle the webservice via it's normal save() method with the extra data supplied in the $data argument.
 
 === 2.5 ===
 
index 7b06f0d..e2cb6d0 100644 (file)
@@ -25,7 +25,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $module->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
-$module->version  = 2013070902;    // The current module version (Date: YYYYMMDDXX).
+$module->version  = 2013080800;    // The current module version (Date: YYYYMMDDXX).
 $module->requires = 2013050100;    // Requires this Moodle version.
 $module->cron     = 60;
 
index bc52dc7..0bc9061 100644 (file)
@@ -151,7 +151,7 @@ function book_get_chapter_title($chid, $chapters, $book, $context) {
 }
 
 /**
- * Add the book TOC sticky block to the 1st region available
+ * Add the book TOC sticky block to the default region
  *
  * @param array $chapters
  * @param stdClass $chapter
@@ -169,9 +169,8 @@ function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) {
     $bc->attributes['class'] = 'block block_book_toc';
     $bc->content = $toc;
 
-    $regions = $PAGE->blocks->get_regions();
-    $firstregion = reset($regions);
-    $PAGE->blocks->add_fake_block($bc, $firstregion);
+    $defaultregion = $PAGE->blocks->get_default_region();
+    $PAGE->blocks->add_fake_block($bc, $defaultregion);
 }
 
 /**
index 428203c..589a927 100644 (file)
@@ -571,15 +571,15 @@ table#categoryquestions {
     border-left: thin solid #777;
     line-height: 1.3em;
     border-radius: 0.6em;
-    border-radius-bottomleft: 0;
-    border-radius-topleft: 0;
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
     width: 88%;
     padding: 0.15em 0 0.3em;
     background-color: #d6d6d6;
 }
 #page-mod-quiz-edit div.quizpage .pagecontent .pagestatus {
-    border-radius-bottomright: 0.3em;
-    border-radius-topright: 0.3em;
+    border-bottom-right-radius: 0.3em;
+    border-top-right-radius: 0.3em;
     margin: 0.3em;
     padding: 0.1em 0.1em 0.1em 0.3em;
     background-color: #eee;
@@ -647,8 +647,8 @@ table#categoryquestions {
     float: left;
     position: relative;
     border-radius: 0.3em;
-    border-radius-bottomleft: 0;
-    border-radius-topleft: 0;
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
     line-height: 1.2em;
     padding: 0.1em;
     background-color: #F9F9F9;
@@ -757,8 +757,8 @@ table#categoryquestions {
     float: left;
     position: relative;
     border-radius: 0.6em;
-    border-radius-bottomleft: 0;
-    border-radius-topleft: 0;
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
     line-height: 1.4em;
     padding: 0.5em;
 }
@@ -772,8 +772,8 @@ table#categoryquestions {
     position: absolute;
     right: 60px;
     border-radius: 0.2em;
-    border-radius-bottomleft: 0;
-    border-radius-topleft: 0;
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
     z-index: 900;
     display: block;
     margin: 0;
@@ -792,8 +792,8 @@ table#categoryquestions {
     position: absolute;
     right: 50px;
     border-radius: 0.2em;
-    border-radius-bottomleft: 0;
-    border-radius-topleft: 0;
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
     z-index: 900;
     display: block;
     margin: 0;
index 6c81396..11712d0 100644 (file)
@@ -51,7 +51,7 @@ class backup_scorm_activity_structure_step extends backup_activity_structure_ste
 
         $sco = new backup_nested_element('sco', array('id'), array(
             'manifest', 'organization', 'parent', 'identifier',
-            'launch', 'scormtype', 'title'));
+            'launch', 'scormtype', 'title', 'sortorder'));
 
         $scodatas = new backup_nested_element('sco_datas');
 
@@ -128,7 +128,7 @@ class backup_scorm_activity_structure_step extends backup_activity_structure_ste
         $scorm->set_source_table('scorm', array('id' => backup::VAR_ACTIVITYID));
 
         // Order is important for several SCORM calls (especially scorm_scoes) in the following calls to set_source_table
-        $sco->set_source_table('scorm_scoes', array('scorm' => backup::VAR_PARENTID), 'id ASC');
+        $sco->set_source_table('scorm_scoes', array('scorm' => backup::VAR_PARENTID), 'sortorder, id');
         $scodata->set_source_table('scorm_scoes_data', array('scoid' => backup::VAR_PARENTID), 'id ASC');
         $seqrulecond->set_source_table('scorm_seq_ruleconds', array('scoid' => backup::VAR_PARENTID), 'id ASC');
         $seqrulecondsdata->set_source_table('scorm_seq_rulecond', array('ruleconditionsid' => backup::VAR_PARENTID), 'id ASC');
index c33fd3f..4675494 100644 (file)
@@ -248,10 +248,11 @@ function scorm_parse_aicc($scorm) {
     }
 
     $oldscoes = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id));
-
+    $sortorder = 0;
     $launch = 0;
     if (isset($courses)) {
         foreach ($courses as $course) {
+            $sortorder++;
             $sco = new stdClass();
             $sco->identifier = $course->id;
             $sco->scorm = $scorm->id;
@@ -260,12 +261,13 @@ function scorm_parse_aicc($scorm) {
             $sco->parent = '/';
             $sco->launch = '';
             $sco->scormtype = '';
+            $sco->sortorder = $sortorder;
 
             if ($ss = $DB->get_record('scorm_scoes', array('scorm'=>$scorm->id,
                                                            'identifier'=>$sco->identifier))) {
                 $id = $ss->id;
                 $sco->id = $id;
-                $DB->update_record('scorm_scoes',$sco);
+                $DB->update_record('scorm_scoes', $sco);
                 unset($oldscoes[$id]);
             } else {
                 $id = $DB->insert_record('scorm_scoes', $sco);
@@ -421,17 +423,17 @@ function scorm_aicc_confirm_hacp_session($hacpsession) {
  */
 function scorm_aicc_generate_simple_sco($scorm) {
     global $DB;
-    // find the old one
-    $scos = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id));
+    // Find the oldest one.
+    $scos = $DB->get_records('scorm_scoes', array('scorm' => $scorm->id), 'id');
     if (!empty($scos)) {
         $sco = array_shift($scos);
     } else {
-        $sco = new object();
+        $sco = new stdClass();
     }
-    // get rid of old ones
-    foreach($scos as $oldsco) {
-        $DB->delete_records('scorm_scoes', array('id'=>$oldsco->id));
-        $DB->delete_records('scorm_scoes_track', array('scoid'=>$oldsco->id));
+    // Get rid of old ones.
+    foreach ($scos as $oldsco) {
+        $DB->delete_records('scorm_scoes', array('id' => $oldsco->id));
+        $DB->delete_records('scorm_scoes_track', array('scoid' => $oldsco->id));
     }
 
     $sco->identifier = 'A1';
@@ -439,11 +441,10 @@ function scorm_aicc_generate_simple_sco($scorm) {
     $sco->organization = '';
     $sco->title = $scorm->name;
     $sco->parent = '/';
-    // add the HACP signal to the activity launcher
+    // Add the HACP signal to the activity launcher.
     if (preg_match('/\?/', $scorm->reference)) {
         $sco->launch = $scorm->reference.'&CMI=HACP';
-    }
-    else {
+    } else {
         $sco->launch = $scorm->reference.'?CMI=HACP';
     }
     $sco->scormtype = 'sco';
index 6fa4f5d..91ef6d8 100644 (file)
@@ -525,27 +525,47 @@ function scorm_parse_scorm($scorm, $manifest) {
     $scoes = new stdClass();
     $scoes->version = '';
     $scoes = scorm_get_manifest($manifests, $scoes);
+    $sortorder = 0;
     if (count($scoes->elements) > 0) {
         $olditems = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id));
         foreach ($scoes->elements as $manifest => $organizations) {
             foreach ($organizations as $organization => $items) {
                 foreach ($items as $identifier => $item) {
+                    $sortorder++;
                     // This new db mngt will support all SCORM future extensions
                     $newitem = new stdClass();
                     $newitem->scorm = $scorm->id;
                     $newitem->manifest = $manifest;
                     $newitem->organization = $organization;
+                    $newitem->sortorder = $sortorder;
                     $standarddatas = array('parent', 'identifier', 'launch', 'scormtype', 'title');
                     foreach ($standarddatas as $standarddata) {
                         if (isset($item->$standarddata)) {
                             $newitem->$standarddata = $item->$standarddata;
+                        } else {
+                            $newitem->$standarddata = '';
                         }
                     }
 
-                    // Insert the new SCO, and retain the link between the old and new for later adjustment
-                    $id = $DB->insert_record('scorm_scoes', $newitem);
                     if (!empty($olditems) && ($olditemid = scorm_array_search('identifier', $newitem->identifier, $olditems))) {
-                        $olditems[$olditemid]->newid = $id;
+                        $newitem->id = $olditemid;
+                        // Update the Sco sortorder but keep id so that user tracks are kept against the same ids.
+                        $DB->update_record('scorm_scoes', $newitem);
+                        $id = $olditemid;
+                        // Remove all old data so we don't duplicate it.
+                        $DB->delete_records('scorm_scoes_data', array('scoid'=>$olditemid));
+                        $DB->delete_records('scorm_seq_objective', array('scoid'=>$olditemid));
+                        $DB->delete_records('scorm_seq_mapinfo', array('scoid'=>$olditemid));
+                        $DB->delete_records('scorm_seq_ruleconds', array('scoid'=>$olditemid));
+                        $DB->delete_records('scorm_seq_rulecond', array('scoid'=>$olditemid));
+                        $DB->delete_records('scorm_seq_rolluprule', array('scoid'=>$olditemid));
+                        $DB->delete_records('scorm_seq_rolluprulecond', array('scoid'=>$olditemid));
+
+                        // Now remove this SCO from the olditems object as we have dealt with it.
+                        unset($olditems[$olditemid]);
+                    } else {
+                        // Insert the new SCO, and retain the link between the old and new for later adjustment
+                        $id = $DB->insert_record('scorm_scoes', $newitem);
                     }
 
                     if ($optionaldatas = scorm_optionals_data($item, $standarddatas)) {
@@ -641,9 +661,6 @@ function scorm_parse_scorm($scorm, $manifest) {
             foreach ($olditems as $olditem) {
                 $DB->delete_records('scorm_scoes', array('id'=>$olditem->id));
                 $DB->delete_records('scorm_scoes_data', array('scoid'=>$olditem->id));
-                if (isset($olditem->newid)) {
-                    $DB->set_field('scorm_scoes_track', 'scoid', $olditem->newid, array('scoid' => $olditem->id));
-                }
                 $DB->delete_records('scorm_scoes_track', array('scoid'=>$olditem->id));
                 $DB->delete_records('scorm_seq_objective', array('scoid'=>$olditem->id));
                 $DB->delete_records('scorm_seq_mapinfo', array('scoid'=>$olditem->id));
@@ -701,7 +718,8 @@ function scorm_get_parent($sco) {
 function scorm_get_children($sco) {
     global $DB;
 
-    if ($children = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) {//originally this said parent instead of childrean
+    $children = $DB->get_records('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->identifier), 'sortorder, id');
+    if (!empty($children)) {
         return $children;
     }
     return null;
@@ -710,7 +728,7 @@ function scorm_get_children($sco) {
 function scorm_get_available_children($sco) {
     global $DB;
 
-    $res = $DB->get_records('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->identifier));
+    $res = $DB->get_records('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->identifier), 'sortorder, id');
     if (!$res || $res == null) {
         return false;
     } else {
@@ -738,7 +756,7 @@ function scorm_get_available_descendent($descend = array(), $sco) {
 function scorm_get_siblings($sco) {
     global $DB;
 
-    if ($siblings = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->parent))) {
+    if ($siblings = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->parent), 'sortorder, id')) {
         unset($siblings[$sco->id]);
         if (!empty($siblings)) {
             return $siblings;
index 794bbe8..d69f1ea 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/scorm/db" VERSION="20120326" COMMENT="XMLDB file for Moodle mod/scorm"
+<XMLDB PATH="mod/scorm/db" VERSION="20130826" COMMENT="XMLDB file for Moodle mod/scorm"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
 >
@@ -61,6 +61,7 @@
         <FIELD NAME="launch" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="scormtype" TYPE="char" LENGTH="5" NOTNULL="true" SEQUENCE="false"/>
         <FIELD NAME="title" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
+        <FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="order of scoes"/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
old mode 100644 (file)
new mode 100755 (executable)
index d6c1cff..870a988 100644 (file)
@@ -114,6 +114,21 @@ function xmldb_scorm_upgrade($oldversion) {
         upgrade_mod_savepoint(true, 2013081302, 'scorm');
     }
 
+    if ($oldversion < 2013081303) {
+
+        // Define field sortorder to be added to scorm_scoes.
+        $table = new xmldb_table('scorm_scoes');
+        $field = new xmldb_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'title');
+
+        // Conditionally launch add field sortorder.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Scorm savepoint reached.
+        upgrade_mod_savepoint(true, 2013081303, 'scorm');
+    }
+
     return true;
 }
 
index 8fc726e..a3d17cd 100644 (file)
@@ -388,7 +388,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
     if ($orgs = $DB->get_records_select('scorm_scoes', 'scorm = ? AND '.
                                          $DB->sql_isempty('scorm_scoes', 'launch', false, true).' AND '.
                                          $DB->sql_isempty('scorm_scoes', 'organization', false, false),
-                                         array($scorm->id), 'id', 'id,identifier,title')) {
+                                         array($scorm->id), 'sortorder, id', 'id, identifier, title')) {
         if (count($orgs) <= 1) {
             unset($orgs);
             $orgs = array();
@@ -407,7 +407,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
             }
             $report .= "<ul id='0' class='$liststyle'>";
                 $conditions['scorm'] = $scorm->id;
-            if ($scoes = $DB->get_records('scorm_scoes', $conditions, "id ASC")) {
+            if ($scoes = $DB->get_records('scorm_scoes', $conditions, "sortorder, id")) {
                 // drop keys so that we can access array sequentially
                 $scoes = array_values($scoes);
                 $level=0;
@@ -1403,4 +1403,4 @@ function scorm_check_mode($scorm, $newattempt, &$attempt, $userid, &$mode) {
     } else if (($mode == 'browse') && ($scorm->hidebrowse == 1)) { // Prevent Browse mode if hidebrowse is set.
         $mode = 'normal';
     }
-}
\ No newline at end of file
+}
index 65611e6..8b39f3e 100644 (file)
@@ -83,7 +83,7 @@ if (!empty($scoid)) {
                     'scorm_scoes',
                     'scorm = ? AND '.$DB->sql_isnotempty('scorm_scoes', 'launch', false, true).' AND id > ?',
                     array($scorm->id, $sco->id),
-                    'id ASC')) {
+                    'sortorder, id')) {
                 $sco = current($scoes);
             }
         }
@@ -97,7 +97,7 @@ if (!isset($sco)) {
         'scorm_scoes',
         'scorm = ? AND '.$DB->sql_isnotempty('scorm_scoes', 'launch', false, true),
         array($scorm->id),
-        'id ASC'
+        'sortorder, id'
     );
     $sco = current($scoes);
 }
index 728a5ff..53d6e42 100644 (file)
@@ -367,13 +367,12 @@ function scorm_get_sco($id, $what=SCO_ALL) {
 function scorm_get_scoes($id, $organisation=false) {
     global $DB;
 
-    $organizationsql = '';
     $queryarray = array('scorm'=>$id);
     if (!empty($organisation)) {
         $queryarray['organization'] = $organisation;
     }
-    if ($scoes = $DB->get_records('scorm_scoes', $queryarray, 'id ASC')) {
-        // drop keys so that it is a simple array as expected
+    if ($scoes = $DB->get_records('scorm_scoes', $queryarray, 'sortorder, id')) {
+        // Drop keys so that it is a simple array as expected.
         $scoes = array_values($scoes);
         foreach ($scoes as $sco) {
             if ($scodatas = $DB->get_records('scorm_scoes_data', array('scoid'=>$sco->id))) {
@@ -627,7 +626,7 @@ function scorm_grade_user_attempt($scorm, $userid, $attempt=1) {
     $attemptscore->sum = 0;
     $attemptscore->lastmodify = 0;
 
-    if (!$scoes = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id))) {
+    if (!$scoes = $DB->get_records('scorm_scoes', array('scorm' => $scorm->id), 'sortorder, id')) {
         return null;
     }
 
@@ -814,7 +813,7 @@ function scorm_view_display ($user, $scorm, $action, $cm) {
     if ($orgs = $DB->get_records_select_menu('scorm_scoes', 'scorm = ? AND '.
                                          $DB->sql_isempty('scorm_scoes', 'launch', false, true).' AND '.
                                          $DB->sql_isempty('scorm_scoes', 'organization', false, false),
-                                         array($scorm->id), 'id', 'id,title')) {
+                                         array($scorm->id), 'sortorder, id', 'id,title')) {
         if (count($orgs) > 1) {
             $select = new single_select(new moodle_url($action), 'organization', $orgs, $organization, null);
             $select->label = get_string('organizations', 'scorm');
@@ -900,7 +899,8 @@ function scorm_simple_play($scorm, $user, $context, $cmid) {
     if ($scorm->scormtype != SCORM_TYPE_LOCAL && $scorm->updatefreq == SCORM_UPDATE_EVERYTIME) {
         scorm_parse($scorm, false);
     }
-    $scoes = $DB->get_records_select('scorm_scoes', 'scorm = ? AND '.$DB->sql_isnotempty('scorm_scoes', 'launch', false, true), array($scorm->id), 'id', 'id');
+    $scoes = $DB->get_records_select('scorm_scoes', 'scorm = ? AND '.
+        $DB->sql_isnotempty('scorm_scoes', 'launch', false, true), array($scorm->id), 'sortorder, id', 'id');
 
     if ($scoes) {
         $orgidentifier = '';
@@ -1461,7 +1461,6 @@ function scorm_get_toc_get_parent_child(&$result) {
     $final = array();
     $level = 0;
     $prevparent = '/';
-    ksort($result);
 
     foreach ($result as $sco) {
         if ($sco->parent == '/') {
index c4bb765..5c55e9c 100644 (file)
@@ -137,7 +137,7 @@ class scorm_basic_report extends scorm_default_report {
             $headers[]= get_string('last', 'scorm');
             $columns[]= 'score';
             $headers[]= get_string('score', 'scorm');
-            if ($detailedrep && $scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'id')) {
+            if ($detailedrep && $scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'sortorder, id')) {
                 foreach ($scoes as $sco) {
                     if ($sco->launch!='') {
                         $columns[]= 'scograde'.$sco->id;
index d9d532b..58e426f 100644 (file)
@@ -46,7 +46,7 @@ class scorm_graphs_report extends scorm_default_report {
             groups_print_activity_menu($cm, new moodle_url($PAGE->url));
         }
 
-        if ($scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'id')) {
+        if ($scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'sortorder, id')) {
             foreach ($scoes as $sco) {
                 if ($sco->launch != '') {
                     $imageurl = new moodle_url('/mod/scorm/report/graphs/graph.php',
index 2550a9f..8a2881c 100644 (file)
@@ -148,7 +148,7 @@ class scorm_interactions_report extends scorm_default_report {
             $headers[] = get_string('last', 'scorm');
             $columns[] = 'score';
             $headers[] = get_string('score', 'scorm');
-            $scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'id');
+            $scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id');
             foreach ($scoes as $sco) {
                 if ($sco->launch != '') {
                     $columns[] = 'scograde'.$sco->id;
index d5a2000..3593961 100644 (file)
@@ -148,7 +148,7 @@ class scorm_objectives_report extends scorm_default_report {
             $headers[] = get_string('last', 'scorm');
             $columns[] = 'score';
             $headers[] = get_string('score', 'scorm');
-            $scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'id');
+            $scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id');
             foreach ($scoes as $sco) {
                 if ($sco->launch != '') {
                     $columns[] = 'scograde'.$sco->id;
index d4a2ff4..f1e3ee1 100644 (file)
@@ -72,7 +72,7 @@ require($CFG->dirroot . '/mod/scorm/report/userreporttabs.php');
 $output = $PAGE->get_renderer('mod_scorm');
 echo $output->view_user_heading($user, $course, $PAGE->url, $attempt, $attemptids);
 
-if ($scoes = $DB->get_records_select('scorm_scoes', "scorm = ? ORDER BY id", array($scorm->id))) {
+if ($scoes = $DB->get_records('scorm_scoes', array('scorm' => $scorm->id), 'sortorder, id')) {
     // Print general score data.
     $table = new html_table();
     $table->head = array(
index 9f2d6c1..56084ad 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2013081302;       // The current module version (Date: YYYYMMDDXX)
+$module->version   = 2013081303;       // The current module version (Date: YYYYMMDDXX)
 $module->requires  = 2013050100;    // Requires this Moodle version
 $module->component = 'mod_scorm'; // Full name of the plugin (used for diagnostics)
 $module->cron      = 300;
index 29e531c..9884d0a 100644 (file)
@@ -4,13 +4,12 @@ M.mod_scormform.init = function(Y) {
     var cwidth = scormplayerdata.cwidth;
     var cheight = scormplayerdata.cheight;
     var poptions = scormplayerdata.popupoptions;
-    var courseid = scormplayerdata.courseid;
     var launch = scormplayerdata.launch;
     var currentorg = scormplayerdata.currentorg;
     var sco = scormplayerdata.sco;
     var scorm = scormplayerdata.scorm;
     var launch_url = M.cfg.wwwroot+"/mod/scorm/player.php?a="+scorm+"&currentorg="+currentorg+"&scoid="+sco+"&sesskey="+M.cfg.sesskey;
-    var course_url = M.cfg.wwwroot+"/course/view.php?id="+courseid+"&sesskey="+M.cfg.sesskey;
+    var course_url = scormplayerdata.courseurl;
 
     if ((cwidth==100) && (cheight==100)) {
         poptions = poptions+',width='+screen.availWidth+',height='+screen.availHeight+',left=0,top=0';
index e9027d1..692dcb4 100644 (file)
@@ -16,6 +16,7 @@
 
 require_once("../../config.php");
 require_once($CFG->dirroot.'/mod/scorm/locallib.php');
+require_once($CFG->dirroot.'/course/lib.php');
 
 $id = optional_param('id', '', PARAM_INT);       // Course Module ID, or
 $a = optional_param('a', '', PARAM_INT);         // scorm ID
@@ -83,11 +84,19 @@ if (!empty($scorm->popup)) {
             $launch = true;
         }
     }
+    // Redirect back to the section with one section per page ?
+
+    $courseformat = course_get_format($course)->get_course();
+    $sectionid = '';
+    if (isset($courseformat->coursedisplay) && $courseformat->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
+        $sectionid = $cm->section;
+    }
+
     $PAGE->requires->data_for_js('scormplayerdata', Array('launch' => $launch,
                                                            'currentorg' => $orgidentifier,
                                                            'sco' => $scoid,
                                                            'scorm' => $scorm->id,
-                                                           'courseid' => $scorm->course,
+                                                           'courseurl' => course_get_url($course, $sectionid)->out(false),
                                                            'cwidth' => $scorm->width,
                                                            'cheight' => $scorm->height,
                                                            'popupoptions' => $scorm->options), true);
index f30c717..d95b927 100644 (file)
 #page-course-publish-metadata .hublink {}
 #page-course-publish-backup .courseuploadtextinfo {text-align:center;}
 #page-course-publish-backup .sharecoursecontinue  {text-align:center;}
+
+.sitetopic .section .activity .commands,
+.course-content .section .activity .commands {float: right;}
index 32a4634..158b01d 100644 (file)
@@ -347,10 +347,10 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager
     $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"');
     $mform->setType('idnumber', PARAM_NOTAGS);
 
-    $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="40" size="25"');
+    $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="255" size="25"');
     $mform->setType('institution', PARAM_TEXT);
 
-    $mform->addElement('text', 'department', get_string('department'), 'maxlength="30" size="25"');
+    $mform->addElement('text', 'department', get_string('department'), 'maxlength="255" size="25"');
     $mform->setType('department', PARAM_TEXT);
 
     $mform->addElement('text', 'phone1', get_string('phone'), 'maxlength="20" size="25"');
@@ -359,7 +359,7 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager
     $mform->addElement('text', 'phone2', get_string('phone2'), 'maxlength="20" size="25"');
     $mform->setType('phone2', PARAM_NOTAGS);
 
-    $mform->addElement('text', 'address', get_string('address'), 'maxlength="70" size="25"');
+    $mform->addElement('text', 'address', get_string('address'), 'maxlength="255" size="25"');
     $mform->setType('address', PARAM_TEXT);
 
 
index 31357b8..c9cd6f4 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2013091300.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2013091300.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.