Merge branch 'MDL-43619-master' of git://github.com/sammarshallou/moodle
authorDan Poltawski <dan@moodle.com>
Wed, 15 Jan 2014 00:19:49 +0000 (08:19 +0800)
committerDan Poltawski <dan@moodle.com>
Wed, 15 Jan 2014 00:19:49 +0000 (08:19 +0800)
198 files changed:
admin/settings/plugins.php
admin/tests/behat/behat_admin.php
admin/tests/behat/filter_users.feature
auth/tests/behat/behat_auth.php
backup/moodle2/restore_course_task.class.php
backup/moodle2/restore_stepslib.php
backup/util/ui/tests/behat/behat_backup.php
blocks/activity_modules/tests/behat/block_activity_modules.feature
blocks/comments/tests/behat/behat_block_comments.php
blocks/private_files/styles.css [new file with mode: 0644]
blocks/tests/behat/behat_blocks.php
calendar/lib.php
cohort/tests/behat/add_cohort.feature
cohort/tests/behat/behat_cohort.php
config-dist.php
course/dnduploadlib.php
course/tests/externallib_test.php
course/yui/build/moodle-course-modchooser/moodle-course-modchooser-debug.js
course/yui/build/moodle-course-modchooser/moodle-course-modchooser-min.js
course/yui/build/moodle-course-modchooser/moodle-course-modchooser.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js
course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js
course/yui/src/modchooser/js/modchooser.js
course/yui/src/toolboxes/js/toolbox.js
filter/upgrade.txt
grade/grading/form/guide/styles.css
grade/report/user/lib.php
grade/tests/behat/behat_grade.php [new file with mode: 0644]
grade/tests/behat/grade_view.feature [new file with mode: 0644]
group/tests/behat/behat_groups.php
group/tests/behat/create_groups.feature
lang/en/admin.php
lang/en/block.php
lang/en/moodle.php
lang/en/question.php
lib/adminlib.php
lib/cronlib.php
lib/customcheckslib.php
lib/db/install.xml
lib/db/upgrade.php
lib/dml/moodle_database.php
lib/dml/mssql_native_moodle_database.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/oci_native_moodle_database.php
lib/dml/pgsql_native_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/dml/tests/dml_test.php
lib/environmentlib.php
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-debug.js [new file with mode: 0644]
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js [new file with mode: 0644]
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask.js [new file with mode: 0644]
lib/form/yui/passwordunmask/passwordunmask.js [deleted file]
lib/form/yui/src/passwordunmask/build.json [new file with mode: 0644]
lib/form/yui/src/passwordunmask/js/passwordunmask.js [new file with mode: 0644]
lib/form/yui/src/passwordunmask/meta/passwordunmask.json [new file with mode: 0644]
lib/google/curlio.php
lib/grade/tests/fixtures/lib.php
lib/htaccess
lib/javascript-static.js
lib/outputrenderers.php
lib/phpunit/bootstrap.php
lib/setuplib.php
lib/tests/behat/behat_deprecated.php
lib/tests/behat/behat_hooks.php
lib/upgrade.txt
lib/weblib.php
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-debug.js
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js
lib/yui/src/chooserdialogue/js/chooserdialogue.js
lib/yui/src/notification/js/dialogue.js
login/signup_form.php
message/lib.php
message/tests/behat/behat_message.php
message/tests/behat/display_history.feature
message/tests/behat/manage_contacts.feature
message/tests/behat/search_history.feature
mod/assign/backup/moodle2/backup_assign_stepslib.php
mod/assign/db/install.xml
mod/assign/db/upgrade.php
mod/assign/externallib.php
mod/assign/lang/en/assign.php
mod/assign/locallib.php
mod/assign/mod_form.php
mod/assign/quickgradingform.php
mod/assign/settings.php
mod/assign/tests/behat/group_submission.feature
mod/assign/tests/generator/lib.php
mod/assign/tests/locallib_test.php
mod/assign/tests/upgradelib_test.php
mod/assign/upgrade.txt
mod/assign/upgradelib.php
mod/assign/version.php
mod/assignment/assignment.js [deleted file]
mod/assignment/backup/moodle2/restore_assignment_activity_task.class.php
mod/assignment/backup/moodle2/restore_assignment_stepslib.php
mod/assignment/classes/plugininfo/assignment.php
mod/assignment/db/install.xml
mod/assignment/db/upgrade.php
mod/assignment/db/upgradelib.php [new file with mode: 0644]
mod/assignment/delete.php [deleted file]
mod/assignment/grade.php [deleted file]
mod/assignment/lang/en/assignment.php
mod/assignment/lib.php
mod/assignment/locallib.php [deleted file]
mod/assignment/mod_form.php
mod/assignment/renderer.php [deleted file]
mod/assignment/settings.php [deleted file]
mod/assignment/styles.css [deleted file]
mod/assignment/submissions.php [deleted file]
mod/assignment/tests/generator_test.php [deleted file]
mod/assignment/type/offline/assignment.class.php [deleted file]
mod/assignment/type/online/all.php [deleted file]
mod/assignment/type/online/assignment.class.php [deleted file]
mod/assignment/type/online/classes/event/assessable_uploaded.php [deleted file]
mod/assignment/type/online/file.php [deleted file]
mod/assignment/type/upgrade.txt
mod/assignment/type/upload/assignment.class.php [deleted file]
mod/assignment/type/upload/classes/event/assessable_submitted.php [deleted file]
mod/assignment/type/upload/classes/event/assessable_uploaded.php [deleted file]
mod/assignment/type/upload/notes.php [deleted file]
mod/assignment/type/upload/upload.php [deleted file]
mod/assignment/type/upload/upload_form.php [deleted file]
mod/assignment/type/uploadsingle/assignment.class.php [deleted file]
mod/assignment/type/uploadsingle/upload.php [deleted file]
mod/assignment/type/uploadsingle/upload_form.php [deleted file]
mod/assignment/upload.php [deleted file]
mod/assignment/version.php
mod/assignment/view.php
mod/forum/lib.php
mod/forum/maildigest.php
mod/lesson/locallib.php
mod/lti/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/lti/classes/event/course_module_viewed.php [new file with mode: 0644]
mod/lti/index.php
mod/lti/launch.php
mod/lti/view.php
mod/quiz/editlib.php
mod/quiz/startattempt.php
mod/quiz/summary.php
mod/scorm/classes/event/attempt_deleted.php [new file with mode: 0644]
mod/scorm/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/scorm/classes/event/course_module_viewed.php [new file with mode: 0644]
mod/scorm/classes/event/interactions_viewed.php [new file with mode: 0644]
mod/scorm/classes/event/report_viewed.php [new file with mode: 0644]
mod/scorm/classes/event/sco_launched.php [new file with mode: 0644]
mod/scorm/classes/event/tracks_viewed.php [new file with mode: 0644]
mod/scorm/classes/event/user_report_viewed.php [new file with mode: 0644]
mod/scorm/index.php
mod/scorm/lang/en/scorm.php
mod/scorm/loadSCO.php
mod/scorm/locallib.php
mod/scorm/player.php
mod/scorm/report.php
mod/scorm/report/basic/report.php
mod/scorm/report/interactions/report.php
mod/scorm/report/objectives/report.php
mod/scorm/report/userreport.php
mod/scorm/report/userreportinteractions.php
mod/scorm/report/userreporttracks.php
mod/scorm/request.js
mod/scorm/tests/event_test.php [new file with mode: 0644]
mod/scorm/view.php
mod/wiki/edit_form.php
mod/wiki/pagelib.php
question/classes/bank/search/category_condition.php [new file with mode: 0755]
question/classes/bank/search/condition.php [new file with mode: 0755]
question/classes/bank/search/hidden_condition.php [new file with mode: 0755]
question/editlib.php
question/engine/bank.php
question/upgrade.txt
question/yui/build/moodle-question-searchform/moodle-question-searchform-debug.js [new file with mode: 0644]
question/yui/build/moodle-question-searchform/moodle-question-searchform-min.js [new file with mode: 0644]
question/yui/build/moodle-question-searchform/moodle-question-searchform.js [new file with mode: 0644]
question/yui/src/searchform/build.json [new file with mode: 0644]
question/yui/src/searchform/js/searchform.js [new file with mode: 0644]
question/yui/src/searchform/meta/searchform.json [new file with mode: 0644]
report/security/lang/en/report_security.php
report/security/locallib.php
repository/tests/behat/behat_filepicker.php
theme/base/style/blocks.css
theme/bootstrapbase/less/moodle.less
theme/bootstrapbase/less/moodle/blocks.less
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/grade.less [new file with mode: 0644]
theme/bootstrapbase/less/moodle/user.less
theme/bootstrapbase/renderers/core_renderer.php
theme/bootstrapbase/style/moodle.css
theme/boxxie/style/core.css
theme/canvas/style/mods.css
theme/formfactor/style/mods.css
theme/fusion/style/core.css
theme/standard/style/modules.css
version.php

index 283d02a..2fa4e27 100644 (file)
@@ -25,6 +25,9 @@
 */
 
 if ($hassiteconfig) {
+    /* @var admin_root $ADMIN */
+    $ADMIN->locate('modules')->set_sorting(true);
+
     $ADMIN->add('modules', new admin_page_pluginsoverview());
 
     // activity modules
@@ -142,31 +145,7 @@ if ($hassiteconfig) {
     // "filtersettings" settingpage
     $temp = new admin_settingpage('commonfiltersettings', new lang_string('commonfiltersettings', 'admin'));
     if ($ADMIN->fulltree) {
-        $cachetimes = array(
-            604800 => new lang_string('numdays','',7),
-            86400 => new lang_string('numdays','',1),
-            43200 => new lang_string('numhours','',12),
-            10800 => new lang_string('numhours','',3),
-            7200 => new lang_string('numhours','',2),
-            3600 => new lang_string('numhours','',1),
-            2700 => new lang_string('numminutes','',45),
-            1800 => new lang_string('numminutes','',30),
-            900 => new lang_string('numminutes','',15),
-            600 => new lang_string('numminutes','',10),
-            540 => new lang_string('numminutes','',9),
-            480 => new lang_string('numminutes','',8),
-            420 => new lang_string('numminutes','',7),
-            360 => new lang_string('numminutes','',6),
-            300 => new lang_string('numminutes','',5),
-            240 => new lang_string('numminutes','',4),
-            180 => new lang_string('numminutes','',3),
-            120 => new lang_string('numminutes','',2),
-            60 => new lang_string('numminutes','',1),
-            30 => new lang_string('numseconds','',30),
-            0 => new lang_string('no')
-        );
         $items = array();
-        $items[] = new admin_setting_configselect('cachetext', new lang_string('cachetext', 'admin'), new lang_string('configcachetext', 'admin'), 60, $cachetimes);
         $items[] = new admin_setting_configselect('filteruploadedfiles', new lang_string('filteruploadedfiles', 'admin'), new lang_string('configfilteruploadedfiles', 'admin'), 0,
                 array('0' => new lang_string('none'), '1' => new lang_string('allfiles'), '2' => new lang_string('htmlfilesonly')));
         $items[] = new admin_setting_configcheckbox('filtermatchoneperpage', new lang_string('filtermatchoneperpage', 'admin'), new lang_string('configfiltermatchoneperpage', 'admin'), 0);
index 58b7775..2a02183 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * Steps definitions related with administration.
  *
- * @package   core
+ * @package   core_admin
  * @category  test
  * @copyright 2013 David Monllaó
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -35,7 +35,7 @@ use Behat\Behat\Context\Step\Given as Given,
 /**
  * Site administration level steps definitions.
  *
- * @package    core
+ * @package    core_admin
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
index bb5e657..4b7f6ef 100644 (file)
@@ -8,9 +8,9 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
     Given the following "users" exists:
       | username | firstname | lastname | email | auth | confirmed |
       | user1 | User | One | one@asd.com | manual | 0 |
-      | user2 | User | Two | one@asd.com | ldap | 1 |
-      | user3 | User | Three | one@asd.com | manual | 1 |
-      | user4 | User | Four | one@asd.com | ldap | 0 |
+      | user2 | User | Two | two@asd.com | ldap | 1 |
+      | user3 | User | Three | three@asd.com | manual | 1 |
+      | user4 | User | Four | four@asd.com | ldap | 0 |
     And the following "cohorts" exists:
       | name | idnumber |
       | Cohort 1 | CH1 |
@@ -23,8 +23,8 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
       | user2 | C1 | student |
       | user3 | C1 | student |
     And I log in as "admin"
-    And I add "user2" user to "CH1" cohort
-    And I add "user3" user to "CH1" cohort
+    And I add "User Two (two@asd.com)" user to "CH1" cohort members
+    And I add "User Three (three@asd.com)" user to "CH1" cohort members
     And I follow "Browse list of users"
 
   @javascript
index 4ced154..d8ada6b 100644 (file)
@@ -18,7 +18,7 @@
 /**
  * Basic authentication steps definitions.
  *
- * @package    core
+ * @package    core_auth
  * @category   test
  * @copyright  2012 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -34,7 +34,7 @@ use Behat\Behat\Context\Step\When as When;
 /**
  * Log in log out steps definitions.
  *
- * @package    core
+ * @package    core_auth
  * @category   test
  * @copyright  2012 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
index e9058b8..d32e1e2 100644 (file)
@@ -124,6 +124,7 @@ class restore_course_task extends restore_task {
         $contents = array();
 
         $contents[] = new restore_decode_content('course', 'summary');
+        $contents[] = new restore_decode_content('event', 'description');
 
         return $contents;
     }
index a4e42ef..930a26a 100644 (file)
@@ -2223,6 +2223,7 @@ class restore_calendarevents_structure_step extends restore_structure_step {
         $result = $DB->record_exists_sql($sql, $arg);
         if (empty($result)) {
             $newitemid = $DB->insert_record('event', $params);
+            $this->set_mapping('event', $oldid, $newitemid);
             $this->set_mapping('event_description', $oldid, $newitemid, $restorefiles);
         }
 
index 84fb672..463f278 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * Backup and restore actions to help behat feature files writting.
  *
- * @package    core
+ * @package    core_backup
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -35,7 +35,7 @@ use Behat\Gherkin\Node\TableNode as TableNode,
 /**
  * Backup-related steps definitions.
  *
- * @package    core
+ * @package    core_backup
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
index ba76908..f0ed3f5 100644 (file)
@@ -11,13 +11,11 @@ Feature: Block activity modules
     And I expand "Activity modules" node
     And I follow "Manage activities"
     And I click on "//a[@title=\"Show\"]" "xpath_element" in the "Feedback" "table_row"
-    And I click on "//a[@title=\"Show\"]" "xpath_element" in the "Assignment (2.2)" "table_row"
 
   Scenario: Add activities block on the frontpage
     And the following "activities" exists:
       | activity   | name                        | intro                              | course               | idnumber    |
       | assign     | Frontpage assignment name   | Frontpage assignment description   | Acceptance test site | assign0     |
-      | assignment | Frontpage assignment22 name | Frontpage assignment22 description | Acceptance test site | assignment0 |
       | book       | Frontpage book name         | Frontpage book description         | Acceptance test site | book0       |
       | chat       | Frontpage chat name         | Frontpage chat description         | Acceptance test site | chat0       |
       | choice     | Frontpage choice name       | Frontpage choice description       | Acceptance test site | choice0     |
@@ -45,9 +43,6 @@ Feature: Block activity modules
     And I click on "Assignments" "link" in the "Activities" "block"
     Then I should see "Frontpage assignment name"
     And I am on homepage
-    And I click on "Assignments (2.2)" "link" in the "Activities" "block"
-    And I should see "Frontpage assignment22 name"
-    And I am on homepage
     And I click on "Chats" "link" in the "Activities" "block"
     And I should see "Frontpage chat name"
     And I am on homepage
@@ -99,7 +94,6 @@ Feature: Block activity modules
     And the following "activities" exists:
       | activity   | name                   | intro                         | course | idnumber    |
       | assign     | Test assignment name   | Test assignment description   | C1     | assign1     |
-      | assignment | Test assignment22 name | Test assignment22 description | C1     | assignment1 |
       | book       | Test book name         | Test book description         | C1     | book1       |
       | chat       | Test chat name         | Test chat description         | C1     | chat1       |
       | choice     | Test choice name       | Test choice description       | C1     | choice1     |
@@ -128,9 +122,6 @@ Feature: Block activity modules
     And I click on "Assignments" "link" in the "Activities" "block"
     Then I should see "Test assignment name"
     And I follow "Course 1"
-    And I click on "Assignments (2.2)" "link" in the "Activities" "block"
-    And I should see "Test assignment22 name"
-    And I follow "Course 1"
     And I click on "Chats" "link" in the "Activities" "block"
     And I should see "Test chat name"
     And I follow "Course 1"
index 059fe1d..094c668 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * Commenting system steps definitions.
  *
- * @package    core_comment
+ * @package    block_comments
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -33,7 +33,7 @@ use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
 /**
  * Steps definitions to deal with the commenting system
  *
- * @package    core_comment
+ * @package    block_comments
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
diff --git a/blocks/private_files/styles.css b/blocks/private_files/styles.css
new file mode 100644 (file)
index 0000000..95fd6bb
--- /dev/null
@@ -0,0 +1,5 @@
+/* Rule so that the table tree view works with word-wrap: break-word. */
+.block_private_files .content table {
+    table-layout: fixed;
+    width: 100%;
+}
\ No newline at end of file
index 28d59ca..056bfbd 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * Steps definitions related with blocks.
  *
- * @package   core
+ * @package   core_block
  * @category  test
  * @copyright 2012 David Monllaó
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -32,7 +32,7 @@ use Behat\Behat\Context\Step\Given as Given;
 /**
  * Blocks management steps definitions.
  *
- * @package    core
+ * @package    core_block
  * @category   test
  * @copyright  2012 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
index be9f906..69de81d 100644 (file)
@@ -575,32 +575,6 @@ function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxeve
                         continue;
                     }
                 }
-                if ($event->modulename == 'assignment'){
-                    // create calendar_event to test edit_event capability
-                    // this new event will also prevent double creation of calendar_event object
-                    $checkevent = new calendar_event($event);
-                    // TODO: rewrite this hack somehow
-                    if (!calendar_edit_event_allowed($checkevent)){ // cannot manage entries, eg. student
-                        if (!$assignment = $DB->get_record('assignment', array('id'=>$event->instance))) {
-                            // print_error("invalidid", 'assignment');
-                            continue;
-                        }
-                        // assign assignment to assignment object to use hidden_is_hidden method
-                        require_once($CFG->dirroot.'/mod/assignment/lib.php');
-
-                        if (!file_exists($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php')) {
-                            continue;
-                        }
-                        require_once ($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php');
-
-                        $assignmentclass = 'assignment_'.$assignment->assignmenttype;
-                        $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm);
-
-                        if ($assignmentinstance->description_is_hidden()){//force not to show description before availability
-                            $event->description = get_string('notavailableyet', 'assignment');
-                        }
-                    }
-                }
             }
 
             if ($processed >= $display->maxevents) {
index 2c6ba7b..2021edc 100644 (file)
@@ -35,8 +35,8 @@ Feature: Add cohorts of users
 
   @javascript
   Scenario: Add users to a cohort selecting them from the system users list
-    When I add "user1" user to "333" cohort
-    And I add "user2" user to "333" cohort
+    When I add "First User (first@user.com)" user to "333" cohort members
+    And I add "Second User (second@user.com)" user to "333" cohort members
     Then I should see "2" in the "#cohorts" "css_element"
     And I follow "Assign"
     And the "Current users" select box should contain "First User (first@user.com)"
index 887533b..fc0c854 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * Cohorts steps definitions.
  *
- * @package    core
+ * @package    core_cohort
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -32,7 +32,7 @@ use Behat\Behat\Context\Step\Given as Given;
 /**
  * Steps definitions for cohort actions.
  *
- * @package    core
+ * @package    core_cohort
  * @category   test
  * @copyright  2013 David Monllaó
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -40,39 +40,49 @@ use Behat\Behat\Context\Step\Given as Given;
 class behat_cohort extends behat_base {
 
     /**
-     * Adds the user to the specified cohort.
+     * Adds the user to the specified cohort. The user should be specified like "Firstname Lastname (user@email.com)".
      *
-     * @Given /^I add "(?P<user_username_string>(?:[^"]|\\")*)" user to "(?P<cohort_idnumber_string>(?:[^"]|\\")*)" cohort$/
-     * @param string $username
+     * @Given /^I add "(?P<user_fullname_string>(?:[^"]|\\")*)" user to "(?P<cohort_idnumber_string>(?:[^"]|\\")*)" cohort members$/
+     * @param string $user
      * @param string $cohortidnumber
      */
-    public function i_add_user_to_cohort($username, $cohortidnumber) {
-        global $DB;
-
-        // The user was created by the data generator, executed by the same PHP process that is
-        // running this step, not by any Selenium action.
-        $userid = $DB->get_field('user', 'id', array('username' => $username));
+    public function i_add_user_to_cohort_members($user, $cohortidnumber) {
 
         $steps = array(
             new Given('I click on "' . get_string('assign', 'cohort') . '" "link" in the "' . $this->escape($cohortidnumber) . '" "table_row"'),
-            new Given('I select "' . $userid . '" from "' . get_string('potusers', 'cohort') . '"'),
+            new Given('I select "' . $this->escape($user) . '" from "' . get_string('potusers', 'cohort') . '"'),
             new Given('I press "' . get_string('add') . '"'),
             new Given('I press "' . get_string('backtocohorts', 'cohort') . '"')
         );
 
         // If we are not in the cohorts management we should move there before anything else.
         if (!$this->getSession()->getPage()->find('css', 'input#cohort_search_q')) {
-            $steps = array_merge(
-                array(
-                    new Given('I am on homepage'),
-                    new Given('I collapse "' . get_string('frontpagesettings', 'admin') . '" node'),
-                    new Given('I expand "' . get_string('administrationsite') . '" node'),
-                    new Given('I expand "' . get_string('users', 'admin') . '" node'),
-                    new Given('I expand "' . get_string('accounts', 'admin') . '" node'),
-                    new Given('I follow "' . get_string('cohorts', 'cohort') . '"')
-                ),
-                $steps
-            );
+
+            // With JS enabled we should expand a few tree nodes.
+            if ($this->running_javascript()) {
+                $steps = array_merge(
+                    array(
+                        new Given('I am on homepage'),
+                        new Given('I collapse "' . get_string('frontpagesettings', 'admin') . '" node'),
+                        new Given('I expand "' . get_string('administrationsite') . '" node'),
+                        new Given('I expand "' . get_string('users', 'admin') . '" node'),
+                        new Given('I expand "' . get_string('accounts', 'admin') . '" node'),
+                        new Given('I follow "' . get_string('cohorts', 'cohort') . '"')
+                    ),
+                    $steps
+                );
+
+            } else {
+                // JS disabled.
+                $steps = array_merge(
+                    array(
+                        new Given('I am on homepage'),
+                        new Given('I follow "' . get_string('administrationsite') . '" node'),
+                        new Given('I follow "' . get_string('cohorts', 'cohort') . '"')
+                    ),
+                    $steps
+                );
+            }
         }
 
         return $steps;
index 964a646..6733547 100644 (file)
@@ -654,6 +654,10 @@ $CFG->admin = 'admin';
 // Example:
 //   $CFG->behat_additionalfeatures = array('/home/developer/code/wipfeatures');
 //
+// You can make behat save a screenshot when a scenario fails.
+// Example:
+//   $CFG->behat_screenshots_path = '/my/path/to/save/screenshots';
+//
 //=========================================================================
 // 12. DEVELOPER DATA GENERATOR
 //=========================================================================
index 84aea52..62054d9 100644 (file)
@@ -162,22 +162,6 @@ class dndupload_handler {
         }
     }
 
-    /**
-     * No external code should be directly adding new types - they should be added via a 'addtypes' array, returned
-     * by MODNAME_dndupload_register.
-     *
-     * @deprecated deprecated since Moodle 2.5
-     * @param string $identifier
-     * @param array $datatransfertypes
-     * @param string $addmessage
-     * @param string $namemessage
-     * @param int $priority
-     */
-    public function add_type($identifier, $datatransfertypes, $addmessage, $namemessage, $priority=100) {
-        debugging('add_type() is deprecated. Plugins should be using the MODNAME_dndupload_register callback.');
-        $this->register_type($identifier, $datatransfertypes, $addmessage, $namemessage, '', $priority);
-    }
-
     /**
      * Used to add a new mime type that can be drag and dropped onto a
      * course displayed in a browser window
@@ -210,23 +194,6 @@ class dndupload_handler {
         $this->types[$identifier] = $add;
     }
 
-    /**
-     * No external code should be directly adding new type handlers - they should be added via a 'addtypes' array, returned
-     * by MODNAME_dndupload_register.
-     *
-     * @deprecated deprecated since Moodle 2.5
-     * @param string $type The name of the type (as declared in add_type)
-     * @param string $module The name of the module to handle this type
-     * @param string $message The message to show the user if more than one handler is registered
-     *                        for a type and the user needs to make a choice between them
-     * @param bool $noname If true, the 'name' dialog should be disabled in the pop-up.
-     * @throws coding_exception
-     */
-    public function add_type_handler($type, $module, $message, $noname) {
-        debugging('add_type_handler() is deprecated. Plugins should be using the MODNAME_dndupload_register callback.');
-        $this->register_type_handler($type, $module, $message, $noname);
-    }
-
     /**
      * Used to declare that a particular module will handle a particular type
      * of dropped data
@@ -252,21 +219,6 @@ class dndupload_handler {
         $this->types[$type]->handlers[] = $add;
     }
 
-    /**
-     * No external code should be directly adding new file handlers - they should be added via a 'files' array, returned
-     * by MODNAME_dndupload_register.
-     *
-     * @deprecated deprecated since Moodle 2.5
-     * @param string $extension The file extension to handle ('*' for all types)
-     * @param string $module The name of the module to handle this type
-     * @param string $message The message to show the user if more than one handler is registered
-     *                        for a type and the user needs to make a choice between them
-     */
-    public function add_file_handler($extension, $module, $message) {
-        debugging('add_file_handler() is deprecated. Plugins should be using the MODNAME_dndupload_register callback.');
-        $this->register_file_handler($extension, $module, $message);
-    }
-
     /**
      * Used to declare that a particular module will handle a particular type
      * of dropped file
index 994161a..a83ca83 100644 (file)
@@ -900,13 +900,13 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $record = new stdClass();
         $record->course = $course->id;
         $module1 = self::getDataGenerator()->create_module('forum', $record);
-        $module2 = self::getDataGenerator()->create_module('assignment', $record);
+        $module2 = self::getDataGenerator()->create_module('assign', $record);
 
         // Check the forum was correctly created.
         $this->assertEquals(1, $DB->count_records('forum', array('id' => $module1->id)));
 
         // Check the assignment was correctly created.
-        $this->assertEquals(1, $DB->count_records('assignment', array('id' => $module2->id)));
+        $this->assertEquals(1, $DB->count_records('assign', array('id' => $module2->id)));
 
         // Check data exists in the course modules table.
         $this->assertEquals(2, $DB->count_records_select('course_modules', 'id = :module1 OR id = :module2',
@@ -939,7 +939,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $this->assertEquals(0, $DB->count_records('forum', array('id' => $module1->id)));
 
         // Check the assignment was deleted.
-        $this->assertEquals(0, $DB->count_records('assignment', array('id' => $module2->id)));
+        $this->assertEquals(0, $DB->count_records('assign', array('id' => $module2->id)));
 
         // Check we retrieve no data in the course modules table.
         $this->assertEquals(0, $DB->count_records_select('course_modules', 'id = :module1 OR id = :module2',
@@ -955,7 +955,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
 
         // Create two modules.
         $module1 = self::getDataGenerator()->create_module('forum', $record);
-        $module2 = self::getDataGenerator()->create_module('assignment', $record);
+        $module2 = self::getDataGenerator()->create_module('assign', $record);
 
         // Since these modules were recreated the user will not have capabilities
         // to delete them, ensure exception is thrown if they try.
index d3bf0c1..183420c 100644 (file)
Binary files a/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-debug.js and b/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-debug.js differ
index f9bddf4..0425628 100644 (file)
Binary files a/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-min.js and b/course/yui/build/moodle-course-modchooser/moodle-course-modchooser-min.js differ
index d3bf0c1..183420c 100644 (file)
Binary files a/course/yui/build/moodle-course-modchooser/moodle-course-modchooser.js and b/course/yui/build/moodle-course-modchooser/moodle-course-modchooser.js differ
index 3268417..7eb72a7 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-debug.js differ
index 67d01c9..7a2e8e5 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes-min.js differ
index 3268417..7eb72a7 100644 (file)
Binary files a/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js and b/course/yui/build/moodle-course-toolboxes/moodle-course-toolboxes.js differ
index b1033e3..f9627d2 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 var CSS = {
-    PAGECONTENT : 'div#page-content',
+    PAGECONTENT : 'body',
     SECTION : 'li.section',
     SECTIONMODCHOOSER : 'span.section-modchooser-link',
     SITEMENU : 'div.block_site_main_menu',
index 7fdfaac..7fd7b3b 100644 (file)
@@ -47,7 +47,7 @@ var CSS = {
         INSTANCENAME : 'span.instancename',
         MODINDENTDIV : '.mod-indent',
         MODINDENTOUTER : '.mod-indent-outer',
-        PAGECONTENT : 'div#page-content',
+        PAGECONTENT : 'body',
         SECTIONLI : 'li.section',
         SHOW : 'a.'+CSS.SHOW,
         SHOWHIDE : 'a.editing_showhide'
index 8ece768..d7bfb3d 100644 (file)
@@ -1,6 +1,12 @@
 This file describes API changes in core filter API and plugins,
 information provided here is intended especially for developers.
 
+=== 2.7 ===
+
+* Finally filter may use $PAGE and $OUTPUT, yay!
+* Old global text caching was removed, each filter is now responsible
+  for own caching.
+
 === 2.6 ===
 
 * filtersettings.php is now deprecated, migrate to standard settings.php
index 8ea947c..715d56e 100644 (file)
@@ -11,8 +11,8 @@
 .gradingform_guide .criterion .remark {vertical-align: top;}
 
 .gradingform_guide.editor .criterion .controls,
-.gradingform_guide .criterion .description,
-.gradingform_guide .criterion .remark {padding:3px;}
+.gradingform_guide.editor .criterion .description,
+.gradingform_guide.editor .criterion .remark {padding:3px;}
 
 .gradingform_guide .criteria {height:100%;}
 .gradingform_guide .criterion {border:1px solid #DDD;overflow: hidden;}
 .gradingform_guide.editor .hiddenelement {display:none;}
 .gradingform_guide.editor .pseudotablink {background-color:transparent;border:0 solid;height:1px;width:1px;color:transparent;padding:0;margin:0;position:relative;float:right;}
 
-.gradingform_guide .markingguidecomment {cursor: pointer;}
-.jsenabled .gradingform_guide .markingguidecomment:before {content: url([[pix:t/add]]);padding-right:2px;}
+.jsenabled .gradingform_guide .markingguidecomment {cursor: pointer;}
+.jsenabled .gradingform_guide .markingguidecomment:before {
+    content: url([[pix:t/add]]);
+    padding-right:2px;
+}
+.dir-rtl.jsenabled .gradingform_guide .markingguidecomment:before {
+    padding-right: 0;
+    padding-left: 2px;
+}
 .gradingform_guide .commentheader  {font-weight:bold;font-size:1.1em;padding-bottom:5px;}
 
 .jsenabled .gradingform_guide .criterionnamelabel {display: none;}
 .jsenabled .gradingform_guide .criterionshortname {font-weight:bold;}
 .gradingform_guide table {width: 100%}
+.gradingform_guide .descriptionreadonly {
+    vertical-align: top;
+}
 .gradingform_guide .criteriondescriptionmarkers {width: 300px;}
-.gradingform_guide .markingguideremark {width: 100%;}
-.gradingform_guide .criteriondescriptionscore {display: inline;}
\ No newline at end of file
+.gradingform_guide .markingguideremark {
+    margin: 0;
+    width: 100%;
+    -moz-box-sizing: border-box;
+         box-sizing: border-box;
+}
+.gradingform_guide .criteriondescriptionscore {display: inline;}
+.gradingform_guide .score label {
+    display: block;
+}
+.gradingform_guide .score input {
+    margin: 0;
+    width: auto;
+}
index adb3bad..c215827 100644 (file)
@@ -415,7 +415,7 @@ class grade_report_user extends grade_report {
                     $data['weight']['headers'] = "$header_cat $header_row weight";
                     // has a weight assigned, might be extra credit
                     if ($grade_object->aggregationcoef > 0 && $type <> 'courseitem') {
-                        $data['weight']['content'] = number_format($grade_object->aggregationcoef,2).'%';
+                        $data['weight']['content'] = number_format($grade_object->aggregationcoef,2);
                     }
                 }
 
diff --git a/grade/tests/behat/behat_grade.php b/grade/tests/behat/behat_grade.php
new file mode 100644 (file)
index 0000000..19b1c3e
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Behat grade related steps definitions.
+ *
+ * @package    core_grades
+ * @category   test
+ * @copyright  2014 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
+
+require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
+
+use Behat\Behat\Context\Step\Given as Given;
+
+class behat_grade extends behat_base {
+
+    /**
+     * Enters a grade via the gradebook for a specific grade item and user when viewing the 'Grader report' with editing mode turned on.
+     *
+     * @Given /^I give the grade "(?P<grade_number>(?:[^"]|\\")*)" to the user "(?P<username_string>(?:[^"]|\\")*)" for the grade item "(?P<grade_activity_string>(?:[^"]|\\")*)"$/
+     * @param int $grade
+     * @param string $userfullname the user's fullname as returned by fullname()
+     * @param string $itemname
+     * @return Given
+     */
+    public function i_give_the_grade($grade, $userfullname, $itemname) {
+        $gradelabel = $userfullname . ' ' . $itemname;
+        $fieldstr = get_string('useractivitygrade', 'gradereport_grader', $gradelabel);
+
+        return new Given('I fill in "' . $this->escape($fieldstr) . '" with "' . $grade . '"');
+    }
+}
diff --git a/grade/tests/behat/grade_view.feature b/grade/tests/behat/grade_view.feature
new file mode 100644 (file)
index 0000000..24e5458
--- /dev/null
@@ -0,0 +1,76 @@
+@core @core_grades
+Feature: We can enter in grades and view reports from the gradebook
+  In order to check the expected results are displayed
+  As a teacher
+  I need to assign grades and check that they display correctly in the gradebook.
+  I need to enable grade weightings and check that they are displayed correctly.
+
+  Background:
+    Given the following "courses" exists:
+      | fullname | shortname | format |
+      | Course 1 | C1 | topics |
+    And the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@asd.com |
+      | student1 | Student | 1 | student1@asd.com |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment name |
+      | Description | Submit your online text |
+      | assignsubmission_onlinetext_enabled | 1 |
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Test assignment name"
+    When I press "Add submission"
+    And I fill the moodle form with:
+      | Online text | This is a submission |
+    And I press "Save changes"
+    Then I should see "Submitted for grading"
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I follow "Grades"
+    And I turn editing mode on
+    And I give the grade "80.00" to the user "Student 1" for the grade item "Test assignment name"
+    And I press "Update"
+
+  @javascript
+  Scenario: Grade a grade item and ensure the results display correctly in the gradebook
+    When I select "User report" from "Grade report"
+    And the "Grade report" select box should contain "Grader report"
+    And the "Grade report" select box should contain "Outcomes report"
+    And the "Grade report" select box should contain "User report"
+    And the "Select all or one user" select box should contain "All users (1)"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Grades"
+    And I should see "80.00" in the "Test assignment name" "table_row"
+    And I select "Overview report" from "Grade report"
+    And I should see "80.00" in the "overview-grade" "table"
+
+  @javascript
+  Scenario: We can add a weighting to a grade item and it is displayed properly in the user report
+    When I select "Full view" from "Grade report"
+    And I select "Weighted mean of grades" from "Aggregation"
+    And I fill the moodle form with:
+      | Extra credit value for Test assignment name | 0.72 |
+    And I press "Save changes"
+    And I select "User report" from "Grade report"
+    And I follow "Course grade settings"
+    And I fill the moodle form with:
+      | Show weightings | Show |
+    And I press "Save changes"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Grades"
+    Then I should see "0.72" in the "Test assignment name" "table_row"
+    And I should not see "0.72%" in the "Test assignment name" "table_row"
index f32ce79..625a9a1 100644 (file)
@@ -40,18 +40,16 @@ use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
 class behat_groups extends behat_base {
 
     /**
-     * Add the specified user to the group. You should be in the groups page when running this step.
+     * Add the specified user to the group. You should be in the groups page when running this step. The user should be specified like "Firstname Lastname (user@email.com)".
      *
-     * @Given /^I add "(?P<username_string>(?:[^"]|\\")*)" user to "(?P<group_name_string>(?:[^"]|\\")*)" group$/
+     * @Given /^I add "(?P<user_fullname_string>(?:[^"]|\\")*)" user to "(?P<group_name_string>(?:[^"]|\\")*)" group members$/
      * @throws ElementNotFoundException Thrown by behat_base::find
      * @param string $username
      * @param string $groupname
      */
-    public function i_add_user_to_group($username, $groupname) {
-        global $DB;
+    public function i_add_user_to_group_members($userfullname, $groupname) {
 
-        $user = $DB->get_record('user', array('username' => $username));
-        $userfullname = $this->getSession()->getSelectorsHandler()->xpathLiteral(fullname($user));
+        $userfullname = $this->getSession()->getSelectorsHandler()->xpathLiteral($userfullname);
 
         // Using a xpath liternal to avoid problems with quotes and double quotes.
         $groupname = $this->getSession()->getSelectorsHandler()->xpathLiteral($groupname);
index 7ec7622..e2ce592 100644 (file)
@@ -35,10 +35,10 @@ Feature: Organize students into groups
     And I fill the moodle form with:
       | Group name | Group 2 |
     And I press "Save changes"
-    When I add "student0" user to "Group 1" group
-    And I add "student1" user to "Group 1" group
-    And I add "student2" user to "Group 2" group
-    And I add "student3" user to "Group 2" group
+    When I add "Student 0 (student0@asd.com)" user to "Group 1" group members
+    And I add "Student 1 (student1@asd.com)" user to "Group 1" group members
+    And I add "Student 2 (student2@asd.com)" user to "Group 2" group members
+    And I add "Student 3 (student3@asd.com)" user to "Group 2" group members
     Then I select "Group 1 (2)" from "groups"
     And the "members" select box should contain "Student 0"
     And the "members" select box should contain "Student 1"
index d3671be..2ef3ae1 100644 (file)
@@ -92,7 +92,6 @@ $string['bookmarkdeleted'] = 'Bookmark deleted.';
 $string['bookmarkthispage'] = 'Bookmark this page';
 $string['cachejs'] = 'Cache Javascript';
 $string['cachejs_help'] = 'Javascript caching and compression greatly improves page loading performance. it is strongly recommended for production sites. Developers will probably want to disable this feature.';
-$string['cachetext'] = 'Text cache lifetime';
 $string['calendarexportsalt'] = 'Calendar export salt';
 $string['calendarsettings'] = 'Calendar';
 $string['calendartype'] = 'Calendar type';
@@ -147,7 +146,6 @@ $string['configauthenticationplugins'] = 'Please choose the authentication plugi
 $string['configautolang'] = 'Detect default language from browser setting, if disabled site default is used.';
 $string['configautologinguests'] = 'Should visitors be logged in as guests automatically when entering courses with guest access?';
 $string['configbloglevel'] = 'This setting allows you to restrict the level to which user blogs can be viewed on this site.  Note that they specify the maximum context of the VIEWER not the poster or the types of blog posts.  Blogs can also be disabled completely if you don\'t want them at all.';
-$string['configcachetext'] = 'For larger sites or sites that use text filters, this setting can really speed things up.  Copies of texts will be retained in their processed form for the time specified here.  Setting this too small may actually slow things down slightly,  but setting it too large may mean texts take too long to refresh (with new links, for example).';
 $string['configcalendarcustomexport'] = 'Enable custom date range export of calendar';
 $string['configcalendarexportsalt'] = 'This random text is used for improving of security of authentication tokens used for exporting of calendars. Please note that all current tokens are invalidated if you change this hash salt.';
 $string['configclamactlikevirus'] = 'Treat files like viruses';
@@ -382,10 +380,8 @@ $string['cronerrorclionly'] = 'Sorry, internet access to this page has been disa
 $string['cronerrorpassword'] = 'Sorry, you have not provided a valid password to access this page';
 $string['cronremotepassword'] = 'Cron password for remote access';
 $string['cronwarning'] = 'The <a href="cron.php">cron.php maintenance script</a> has not been run for at least 24 hours.';
-$string['ctyperecommended'] = 'Installing the optional ctype PHP extension is highly recommended in order to improve site performance, particularly if your site is supporting non-latin languages.';
 $string['ctyperequired'] = 'The ctype PHP extension is now required by Moodle, in order to improve site performance and to offer multilingual compatibility.';
 $string['curlcache'] = 'cURL cache TTL';
-$string['curlrecommended'] = 'Installing the optional cURL library is highly recommended in order to enable Moodle Networking functionality.';
 $string['curlrequired'] = 'The cURL PHP extension is now required by Moodle, in order to communicate with Moodle repositories.';
 $string['curltimeoutkbitrate'] = 'Bitrate to use when calculating cURL timeouts (Kbps)';
 $string['curltimeoutkbitrate_help'] = 'This setting is used to calculate an appropriate timeout during large cURL requests. As part of this calculation an HTTP HEAD request is made to determine the size of the content. Setting this to 0 disables this request from being made.';
@@ -396,14 +392,6 @@ $string['custommenuitems'] = 'Custom menu items';
 $string['datarootsecurityerror'] = '<p><strong>SECURITY WARNING!</strong></p><p>Your dataroot directory is in the wrong location and is exposed to the web. This means that all your private files are available to anyone in the world, and some of them could be used by a cracker to obtain unauthorised administrative access to your site!</p>
 <p>You <em>must</em> move dataroot directory ({$a}) to a new location that is not within your public web directory, and update the <code>$CFG->dataroot</code> setting in your config.php accordingly.</p>';
 $string['datarootsecuritywarning'] = 'Your site configuration might not be secure. Please make sure that your dataroot directory ({$a}) is not directly accessible via web.';
-$string['dbmigrate'] = 'Moodle database migration';
-$string['dbmigrateconnecerror'] = 'Could not connect to the database specified.';
-$string['dbmigrateencodingerror'] = 'The database specified has encoding {$a} rather than required UNICODE/UTF8.<br />Please specify another.';
-$string['dbmigratepostgres'] = 'It seems that you are using PostgreSQL as the database server. To continue the migration process you need to manually create a new database with encoding "UNICODE"(PostgreSQL 7) or "UTF8" (PostgreSQL 8) to store the migrated data. Please enter your new database connection settings below to continue:';
-$string['dbmigratewarning'] = 'Please make sure that you have backed up your Moodle database before commencing this procedure. If you are unsure of how to do that, please contact your system admin. Your Moodle site will be put under maintenance mode after you start the migration process';
-$string['dbmigratewarning2'] = '<b>Warning: You are about to start the database migration process. Please be very sure that your entire Moodle database is backed up.</b>';
-$string['dbmigrationdeprecateddb'] = '<font color="#ff0000">This database is migrated to a new UTF8 database and deprecated. Please edit your config.php and use the new database for this moodle.</font>';
-$string['dbmigrationdupfailed'] = 'Database duplication failed with possible error:<font color="#ff0000"><pre>{$a}</pre></font>';
 $string['dbsessions'] = 'Use database for session information';
 $string['debug'] = 'Debug messages';
 $string['debugall'] = 'ALL: Show all reasonable PHP debug messages';
@@ -549,12 +537,10 @@ $string['frontpageroles'] = 'Front page roles';
 $string['frontpagesettings'] = 'Front page settings';
 $string['fullnamedisplay'] = 'Full name format';
 $string['fullnamedisplayprivate'] = 'Full name format - private';
-$string['gdrecommended'] = 'GD extension is used for conversion of images, some features such as user profile images will not be available if missing.';
 $string['gdrequired'] = 'The GD extension is now required by Moodle for image conversion.';
 $string['generalsettings'] = 'General settings';
 $string['geoipfile'] = 'GeoIP city data file';
 $string['getremoteaddrconf'] = 'Logged IP address source';
-$string['globalswarning'] = '<p><strong>SECURITY WARNING!</strong></p><p> To operate properly, Moodle requires <br />that you make certain changes to your current PHP settings.</p><p>You <em>must</em> set <code>register_globals=off</code>.</p><p>This setting is controlled by editing your <code>php.ini</code>, Apache/IIS <br />configuration or <code>.htaccess</code> file.</p>';
 $string['groupenrolmentkeypolicy'] = 'Group enrolment key policy';
 $string['groupenrolmentkeypolicy_desc'] = 'Turning this on will make Moodle check group enrolment keys against a valid password policy.';
 $string['googlemapkey3'] = 'Google Maps API V3 key';
@@ -592,7 +578,6 @@ $string['change'] = 'change';
 $string['checkboxno'] = 'No';
 $string['checkboxyes'] = 'Yes';
 $string['choosefiletoedit'] = 'Choose file to edit';
-$string['iconvrecommended'] = 'Installing the optional ICONV library is highly recommended in order to improve site performance, particularly if your site is supporting non-Latin languages.';
 $string['iconvrequired'] = 'Installing ICONV extension is required.';
 $string['ignore'] = 'Ignore';
 $string['includemoduleuserdata'] = 'Include module user data';
@@ -740,8 +725,6 @@ $string['mymoodleredirect'] = 'Force users to use My Moodle';
 $string['mypage'] = 'Default My home page';
 $string['myprofile'] = 'Default profile page';
 $string['mypagelocked'] = 'Lock default page';
-$string['mysql416bypassed'] = 'However, if your site is using iso-8859-1 (latin) languages ONLY, you may continue using your currently installed MySQL 4.1.12 (or higher).';
-$string['mysql416required'] = 'MySQL 4.1.16 is the minimum version required for Moodle 1.6 in order to guarantee that all data can be converted to UTF-8 in the future.';
 $string['navadduserpostslinks'] = 'Add links to view user posts';
 $string['navadduserpostslinks_help'] = 'If enabled two links will be added to each user in the navigation to view discussions the user has started and posts the user has made in forums throughout the site or in specific courses.';
 $string['navigationupgrade'] = 'This upgrade introduces two new navigation blocks that will replace these blocks: Administration, Courses, Activities and Participants.  If you had set any special permissions on those blocks you should check to make sure everything is behaving as you want it.';
@@ -798,9 +781,7 @@ $string['perfdebug'] = 'Performance info';
 $string['performance'] = 'Performance';
 $string['pgcluster'] = 'PostgreSQL Cluster';
 $string['pgclusterdescription'] = 'PostgreSQL version/cluster parameter for command line operations. If you only have one postgresql on your system or you are not sure what this is, leave this blank.';
-$string['php533warning'] = 'PHP 5.3.3 and upwards is recommended';
 $string['phpfloatproblem'] = 'Detected unexpected problem in handling of PHP float numbers - {$a}';
-$string['php50restricted'] = 'PHP 5.0.x has a number of known problems, please upgrade to 5.1.x or downgrade to 4.3.x or 4.4.x';
 $string['pleaserefreshregistration'] = 'Your site has been registered with moodle.org, please consider updating the registration if significant changes happened since your last update, on {$a}';
 $string['pleaseregister'] = 'Please register your site to remove this button';
 $string['plugin'] = 'Plugin';
@@ -887,8 +868,6 @@ $string['proxypassword'] = 'Proxy password';
 $string['proxyport'] = 'Proxy port';
 $string['proxytype'] = 'Proxy type';
 $string['proxyuser'] = 'Proxy username';
-$string['qtyperqpwillberemoved'] = 'During the upgrade, the RQP question type will be removed. You were not using this question type, so you should not experience any problems.';
-$string['qtyperqpwillberemovedanyway'] = 'During the upgrade, the RQP question type will be removed. You have some RQP questions in your database, and these will stop working unless you reinstall the code from http://moodle.org/mod/data/view.php?d=13&amp;rid=797 before continuing with the upgrade.';
 $string['quarantinedir'] = 'Quarantine directory';
 $string['question'] = 'Question';
 $string['questionbehaviours'] = 'Question behaviours';
@@ -1034,7 +1013,6 @@ $string['tools'] = 'Admin tools';
 $string['toolsmanage'] = 'Manage admin tools';
 $string['unattendedoperation'] = 'Unattended operation';
 $string['unbookmarkthispage'] = 'Unbookmark this page';
-$string['unicoderecommended'] = 'Storing all your data in Unicode (UTF-8) is recommended. New installations should be performed into databases that have their default character set as Unicode.  If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
 $string['unicoderequired'] = 'It is required that you store all your data in Unicode format (UTF-8). New installations must be performed into databases that have their default character set as Unicode.  If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
 $string['uninstallplugin'] = 'Uninstall';
 $string['unlockaccount'] = 'Unlock account';
@@ -1097,9 +1075,6 @@ $string['upgradesure'] = '<p>Your Moodle files have been changed, and you are ab
 <p>Once you do this you can not go back again. Please note that this process can take a long time.</p>
 <p>Are you sure you want to upgrade this server to this version?</p>';
 $string['upgradetimedout'] = 'Upgrade timed out, please restart the upgrade.';
-$string['upgrade197notice'] = '<p>Moodle 1.9.7 contains a number of security fixes to user passwords and backups to protect the user data on your site. As a result some of your settings and permissions relating to backups may have changed.<br />
-See the <a href="http://docs.moodle.org/dev/Moodle_1.9.7_release_notes" target="_blank">Moodle 1.9.7 release notes</a> for full details.</p>';
-$string['upgrade197noticesubject'] = 'Moodle 1.9.7 upgrade security notices';
 $string['upgradingdata'] = 'Upgrading data';
 $string['upgradinglogs'] = 'Upgrading logs';
 $string['upgradingversion'] = 'Upgrading to new version';
index 00527cd..e38b5a4 100644 (file)
@@ -50,6 +50,7 @@ $string['hidepanel'] = 'Hide panel';
 $string['moveblock'] = 'Move {$a} block';
 $string['moveblockafter'] = 'Move block to after {$a} block';
 $string['moveblockbefore'] = 'Move block to before {$a} block';
+$string['moveblockinregion'] = 'Move block to {$a} region';
 $string['movingthisblockcancel'] = 'Moving this block ({$a})';
 $string['onthispage'] = 'On this page';
 $string['pagetypes'] = 'Page types';
index da2502e..9c08415 100644 (file)
@@ -1121,8 +1121,6 @@ $string['minute'] = 'minute';
 $string['minutes'] = 'minutes';
 $string['miscellaneous'] = 'Miscellaneous';
 $string['missingcategory'] = 'You need to choose a category';
-$string['missingcity'] = 'Missing city/town';
-$string['missingcountry'] = 'Missing country';
 $string['missingdescription'] = 'Missing description';
 $string['missingemail'] = 'Missing email address';
 $string['missingfirstname'] = 'Missing given name';
index 092e50f..d2923b1 100644 (file)
@@ -25,6 +25,7 @@
 $string['addmorechoiceblanks'] = 'Blanks for {no} more choices';
 $string['addcategory'] = 'Add category';
 $string['adminreport'] = 'Report on possible problems in your question database.';
+$string['advancedsearchoptions'] = 'Search options';
 $string['answers'] = 'Answers';
 $string['availableq'] = 'Available?';
 $string['badbase'] = 'Bad base before **: {$a}**';
index 41c86ef..043e0af 100644 (file)
@@ -750,8 +750,8 @@ interface parentable_part_of_admin_tree extends part_of_admin_tree {
  */
 class admin_category implements parentable_part_of_admin_tree {
 
-    /** @var mixed An array of part_of_admin_tree objects that are this object's children */
-    public $children;
+    /** @var part_of_admin_tree[] An array of part_of_admin_tree objects that are this object's children */
+    protected $children;
     /** @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects */
     public $name;
     /** @var string The displayed name for this category. Usually obtained through get_string() */
@@ -766,6 +766,15 @@ class admin_category implements parentable_part_of_admin_tree {
     /** @var array fast lookup category cache, all categories of one tree point to one cache */
     protected $category_cache;
 
+    /** @var bool If set to true children will be sorted when calling {@link admin_category::get_children()} */
+    protected $sort = false;
+    /** @var bool If set to true children will be sorted in ascending order. */
+    protected $sortasc = true;
+    /** @var bool If set to true sub categories and pages will be split and then sorted.. */
+    protected $sortsplit = true;
+    /** @var bool $sorted True if the children have been sorted and don't need resorting */
+    protected $sorted = false;
+
     /**
      * Constructor for an empty admin category
      *
@@ -830,7 +839,7 @@ class admin_category implements parentable_part_of_admin_tree {
      */
     public function search($query) {
         $result = array();
-        foreach ($this->children as $child) {
+        foreach ($this->get_children() as $child) {
             $subsearch = $child->search($query);
             if (!is_array($subsearch)) {
                 debugging('Incorrect search result from '.$child->name);
@@ -991,6 +1000,104 @@ class admin_category implements parentable_part_of_admin_tree {
         }
         return false;
     }
+
+    /**
+     * Sets sorting on this category.
+     *
+     * Please note this function doesn't actually do the sorting.
+     * It can be called anytime.
+     * Sorting occurs when the user calls get_children.
+     * Code using the children array directly won't see the sorted results.
+     *
+     * @param bool $sort If set to true children will be sorted, if false they won't be.
+     * @param bool $asc If true sorting will be ascending, otherwise descending.
+     * @param bool $split If true we sort pages and sub categories separately.
+     */
+    public function set_sorting($sort, $asc = true, $split = true) {
+        $this->sort = (bool)$sort;
+        $this->sortasc = (bool)$asc;
+        $this->sortsplit = (bool)$split;
+    }
+
+    /**
+     * Returns the children associated with this category.
+     *
+     * @return part_of_admin_tree[]
+     */
+    public function get_children() {
+        // If we should sort and it hasn't already been sorted.
+        if ($this->sort && !$this->sorted) {
+            if ($this->sortsplit) {
+                $categories = array();
+                $pages = array();
+                foreach ($this->children as $child) {
+                    if ($child instanceof admin_category) {
+                        $categories[] = $child;
+                    } else {
+                        $pages[] = $child;
+                    }
+                }
+                core_collator::asort_objects_by_property($categories, 'visiblename');
+                core_collator::asort_objects_by_property($pages, 'visiblename');
+                if (!$this->sortasc) {
+                    $categories = array_reverse($categories);
+                    $pages = array_reverse($pages);
+                }
+                $this->children = array_merge($pages, $categories);
+            } else {
+                core_collator::asort_objects_by_property($this->children, 'visiblename');
+                if (!$this->sortasc) {
+                    $this->children = array_reverse($this->children);
+                }
+            }
+            $this->sorted = true;
+        }
+        return $this->children;
+    }
+
+    /**
+     * Magically gets a property from this object.
+     *
+     * @param $property
+     * @return part_of_admin_tree[]
+     * @throws coding_exception
+     */
+    public function __get($property) {
+        if ($property === 'children') {
+            return $this->get_children();
+        }
+        throw new coding_exception('Invalid property requested.');
+    }
+
+    /**
+     * Magically sets a property against this object.
+     *
+     * @param string $property
+     * @param mixed $value
+     * @throws coding_exception
+     */
+    public function __set($property, $value) {
+        if ($property === 'children') {
+            $this->sorted = false;
+            $this->children = $value;
+        } else {
+            throw new coding_exception('Invalid property requested.');
+        }
+    }
+
+    /**
+     * Checks if an inaccessible property is set.
+     *
+     * @param string $property
+     * @return bool
+     * @throws coding_exception
+     */
+    public function __isset($property) {
+        if ($property === 'children') {
+            return isset($this->children);
+        }
+        throw new coding_exception('Invalid property requested.');
+    }
 }
 
 
index 37e09ba..703c1fb 100644 (file)
@@ -133,14 +133,6 @@ function cron_run() {
         }
 
 
-        // Delete old cached texts
-        if (!empty($CFG->cachetext)) {   // Defined in config.php
-            $cachelifetime = time() - $CFG->cachetext - 60;  // Add an extra minute to allow for really heavy sites
-            $DB->delete_records_select('cache_text', "timemodified < ?", array($cachelifetime));
-            mtrace(" Deleted old cache_text records");
-        }
-
-
         if (!empty($CFG->usetags)) {
             require_once($CFG->dirroot.'/tag/lib.php');
             tag_cron();
index 7c63c50..b14ac79 100644 (file)
  */
 
 defined('MOODLE_INTERNAL') || die();
-
-/**
- * This function will look for the risky PHP setting register_globals
- * in order to inform about. MDL-12914
- *
- * @param object $result the environment_results object to be modified
- * @return mixed null if the test is irrelevant or environment_results object with
- *               status set to true (test passed) or false (test failed)
- */
-function php_check_register_globals($result) {
-
-/// Check for register_globals. If enabled, security warning
-    if (ini_get_bool('register_globals')) {
-        $result->status = false;
-    } else {
-        $result = null;
-    }
-
-    return $result;
-}
-
-function php_check_php533($result) {
-    if (version_compare(phpversion(), '5.3.3') < 0) {
-        $result->status = false;
-    } else {
-        $result = null;
-    }
-    return $result;
-}
index ec46f1d..99a8360 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20131009" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20140112" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
         <INDEX NAME="filter_md5key" UNIQUE="false" FIELDS="filter, md5key"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="cache_text" COMMENT="For storing temporary copies of processed texts">
-      <FIELDS>
-        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
-        <FIELD NAME="md5key" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="formattedtext" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
-      </FIELDS>
-      <KEYS>
-        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
-      </KEYS>
-      <INDEXES>
-        <INDEX NAME="md5key" UNIQUE="false" FIELDS="md5key"/>
-        <INDEX NAME="timemodified" UNIQUE="false" FIELDS="timemodified" COMMENT="Mainly to help deletion of expired records from cron"/>
-      </INDEXES>
-    </TABLE>
     <TABLE NAME="log" COMMENT="Every action is logged as far as possible">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
index 94a6b04..9650b7f 100644 (file)
@@ -2903,5 +2903,21 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013122400.01);
     }
 
+    if ($oldversion < 2014011000.01) {
+
+        // Define table cache_text to be dropped.
+        $table = new xmldb_table('cache_text');
+
+        // Conditionally launch drop table for cache_text.
+        if ($dbman->table_exists($table)) {
+            $dbman->drop_table($table);
+        }
+
+        unset_config('cachetext');
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2014011000.01);
+    }
+
     return true;
 }
index 4828dcf..070f0cb 100644 (file)
@@ -924,6 +924,54 @@ abstract class moodle_database {
         }
     }
 
+    /**
+     * Ensures that limit params are numeric and positive integers, to be passed to the database.
+     * We explicitly treat null, '' and -1 as 0 in order to provide compatibility with how limit
+     * values have been passed historically.
+     *
+     * @param int $limitfrom Where to start results from
+     * @param int $limitnum How many results to return
+     * @return array Normalised limit params in array($limitfrom, $limitnum)
+     */
+    protected function normalise_limit_from_num($limitfrom, $limitnum) {
+        global $CFG;
+
+        // We explicilty treat these cases as 0.
+        if ($limitfrom === null || $limitfrom === '' || $limitfrom === -1) {
+            $limitfrom = 0;
+        }
+        if ($limitnum === null || $limitnum === '' || $limitnum === -1) {
+            $limitnum = 0;
+        }
+
+        if ($CFG->debugdeveloper) {
+            if (!is_numeric($limitfrom)) {
+                $strvalue = var_export($limitfrom, true);
+                debugging("Non-numeric limitfrom parameter detected: $strvalue, did you pass the correct arguments?",
+                    DEBUG_DEVELOPER);
+            } else if ($limitfrom < 0) {
+                debugging("Negative limitfrom parameter detected: $limitfrom, did you pass the correct arguments?",
+                    DEBUG_DEVELOPER);
+            }
+
+            if (!is_numeric($limitnum)) {
+                $strvalue = var_export($limitnum, true);
+                debugging("Non-numeric limitnum parameter detected: $strvalue, did you pass the correct arguments?",
+                    DEBUG_DEVELOPER);
+            } else if ($limitnum < 0) {
+                debugging("Negative limitnum parameter detected: $limitnum, did you pass the correct arguments?",
+                    DEBUG_DEVELOPER);
+            }
+        }
+
+        $limitfrom = (int)$limitfrom;
+        $limitnum  = (int)$limitnum;
+        $limitfrom = max(0, $limitfrom);
+        $limitnum  = max(0, $limitnum);
+
+        return array($limitfrom, $limitnum);
+    }
+
     /**
      * Return tables in database WITHOUT current prefix.
      * @param bool $usecache if true, returns list of cached tables.
index 70bd6f3..0a324b1 100644 (file)
@@ -693,10 +693,9 @@ class mssql_native_moodle_database extends moodle_database {
      * @throws dml_exception A DML specific exception is thrown for any errors.
      */
     public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
-        $limitfrom = (int)$limitfrom;
-        $limitnum  = (int)$limitnum;
-        $limitfrom = ($limitfrom < 0) ? 0 : $limitfrom;
-        $limitnum  = ($limitnum < 0)  ? 0 : $limitnum;
+
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
+
         if ($limitfrom or $limitnum) {
             if ($limitnum >= 1) { // Only apply TOP clause if we have any limitnum (limitfrom offset is handled later)
                 $fetch = $limitfrom + $limitnum;
index 34320d9..3cb62a3 100644 (file)
@@ -912,10 +912,8 @@ class mysqli_native_moodle_database extends moodle_database {
      * @throws dml_exception A DML specific exception is thrown for any errors.
      */
     public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
-        $limitfrom = (int)$limitfrom;
-        $limitnum  = (int)$limitnum;
-        $limitfrom = ($limitfrom < 0) ? 0 : $limitfrom;
-        $limitnum  = ($limitnum < 0)  ? 0 : $limitnum;
+
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
 
         if ($limitfrom or $limitnum) {
             if ($limitnum < 1) {
@@ -976,10 +974,8 @@ class mysqli_native_moodle_database extends moodle_database {
      * @throws dml_exception A DML specific exception is thrown for any errors.
      */
     public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
-        $limitfrom = (int)$limitfrom;
-        $limitnum  = (int)$limitnum;
-        $limitfrom = ($limitfrom < 0) ? 0 : $limitfrom;
-        $limitnum  = ($limitnum < 0)  ? 0 : $limitnum;
+
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
 
         if ($limitfrom or $limitnum) {
             if ($limitnum < 1) {
index 0c6f700..00f79d6 100644 (file)
@@ -712,11 +712,7 @@ class oci_native_moodle_database extends moodle_database {
      */
     private function get_limit_sql($sql, array $params = null, $limitfrom=0, $limitnum=0) {
 
-        $limitfrom = (int)$limitfrom;
-        $limitnum  = (int)$limitnum;
-        $limitfrom = ($limitfrom < 0) ? 0 : $limitfrom;
-        $limitnum  = ($limitnum < 0)  ? 0 : $limitnum;
-
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
         // TODO: Add the /*+ FIRST_ROWS */ hint if there isn't another hint
 
         if ($limitfrom and $limitnum) {
index 5c369a7..2ee1635 100644 (file)
@@ -681,10 +681,9 @@ class pgsql_native_moodle_database extends moodle_database {
      * @throws dml_exception A DML specific exception is thrown for any errors.
      */
     public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
-        $limitfrom = (int)$limitfrom;
-        $limitnum  = (int)$limitnum;
-        $limitfrom = ($limitfrom < 0) ? 0 : $limitfrom;
-        $limitnum  = ($limitnum < 0)  ? 0 : $limitnum;
+
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
+
         if ($limitfrom or $limitnum) {
             if ($limitnum < 1) {
                 $limitnum = "ALL";
@@ -724,10 +723,9 @@ class pgsql_native_moodle_database extends moodle_database {
      * @throws dml_exception A DML specific exception is thrown for any errors.
      */
     public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
-        $limitfrom = (int)$limitfrom;
-        $limitnum  = (int)$limitnum;
-        $limitfrom = ($limitfrom < 0) ? 0 : $limitfrom;
-        $limitnum  = ($limitnum < 0)  ? 0 : $limitnum;
+
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
+
         if ($limitfrom or $limitnum) {
             if ($limitnum < 1) {
                 $limitnum = "ALL";
index 6f12524..f6cab36 100644 (file)
@@ -762,10 +762,8 @@ class sqlsrv_native_moodle_database extends moodle_database {
      * @throws dml_exception A DML specific exception is thrown for any errors.
      */
     public function get_recordset_sql($sql, array $params = null, $limitfrom = 0, $limitnum = 0) {
-        $limitfrom = (int)$limitfrom;
-        $limitnum = (int)$limitnum;
-        $limitfrom = max(0, $limitfrom);
-        $limitnum = max(0, $limitnum);
+
+        list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum);
 
         if ($limitfrom or $limitnum) {
             if ($limitnum >= 1) { // Only apply TOP clause if we have any limitnum (limitfrom offset is handled later)
index ceed3db..869d6ba 100644 (file)
@@ -4997,6 +4997,74 @@ class core_dml_testcase extends database_driver_testcase {
         $this->assertEquals(2, reset($records)->count);
         $this->assertEquals(2, end($records)->count);
     }
+
+    /**
+     * Test debugging messages about invalid limit number values.
+     */
+    public function test_invalid_limits_debugging() {
+        $DB = $this->tdb;
+        $dbman = $DB->get_manager();
+
+        // Setup test data.
+        $table = $this->get_test_table();
+        $tablename = $table->getName();
+        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+        $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+        $dbman->create_table($table);
+        $DB->insert_record($tablename, array('course' => '1'));
+
+        // Verify that get_records_sql throws debug notices with invalid limit params.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 'invalid');
+        $this->assertDebuggingCalled("Non-numeric limitfrom parameter detected: 'invalid', did you pass the correct arguments?");
+
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, 'invalid');
+        $this->assertDebuggingCalled("Non-numeric limitnum parameter detected: 'invalid', did you pass the correct arguments?");
+
+        // Verify that get_recordset_sql throws debug notices with invalid limit params.
+        $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}}", null, 'invalid');
+        $this->assertDebuggingCalled("Non-numeric limitfrom parameter detected: 'invalid', did you pass the correct arguments?");
+        $rs->close();
+
+        $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}}", null, 1, 'invalid');
+        $this->assertDebuggingCalled("Non-numeric limitnum parameter detected: 'invalid', did you pass the correct arguments?");
+        $rs->close();
+
+        // Verify that some edge cases do no create debugging messages.
+        // String form of integer values.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, '1');
+        $this->assertDebuggingNotCalled();
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, '2');
+        $this->assertDebuggingNotCalled();
+        // Empty strings.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, '');
+        $this->assertDebuggingNotCalled();
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, '');
+        $this->assertDebuggingNotCalled();
+        // Null values.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, null);
+        $this->assertDebuggingNotCalled();
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, null);
+        $this->assertDebuggingNotCalled();
+
+        // Verify that empty arrays DO create debugging mesages.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, array());
+        $this->assertDebuggingCalled("Non-numeric limitfrom parameter detected: array (\n), did you pass the correct arguments?");
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, array());
+        $this->assertDebuggingCalled("Non-numeric limitnum parameter detected: array (\n), did you pass the correct arguments?");
+
+        // Verify Negative number handling:
+        // -1 is explicitly treated as 0 for historical reasons.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, -1);
+        $this->assertDebuggingNotCalled();
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, -1);
+        $this->assertDebuggingNotCalled();
+        // Any other negative values should throw debugging messages.
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, -2);
+        $this->assertDebuggingCalled("Negative limitfrom parameter detected: -2, did you pass the correct arguments?");
+        $DB->get_records_sql("SELECT * FROM {{$tablename}}", null, 1, -2);
+        $this->assertDebuggingCalled("Negative limitnum parameter detected: -2, did you pass the correct arguments?");
+    }
 }
 
 /**
index 48b3292..30fa353 100644 (file)
@@ -1387,45 +1387,10 @@ class environment_results {
     }
 }
 
-/// Here all the bypass functions are coded to be used by the environment
-/// checker. All those functions will receive the result object and will
-/// return it modified as needed (status and bypass string)
-
-/**
- * This function will bypass MySQL 4.1.16 reqs if:
- *   - We are using MySQL > 4.1.12, informing about problems with non latin chars in the future
- *
- * @param object result object to handle
- * @return boolean true/false to determinate if the bypass has to be performed (true) or no (false)
- */
-function bypass_mysql416_reqs ($result) {
-/// See if we are running MySQL >= 4.1.12
-    if (version_compare($result->getCurrentVersion(), '4.1.12', '>=')) {
-        return true;
-    }
-
-    return false;
-}
-
 /// Here all the restrict functions are coded to be used by the environment
 /// checker. All those functions will receive the result object and will
 /// return it modified as needed (status and bypass string)
 
-/**
- * This function will restrict PHP reqs if:
- *   - We are using PHP 5.0.x, informing about the buggy version
- *
- * @param object $result object to handle
- * @return boolean true/false to determinate if the restrict has to be performed (true) or no (false)
- */
-function restrict_php50_version($result) {
-    if (version_compare($result->getCurrentVersion(), '5.0.0', '>=')
-      and version_compare($result->getCurrentVersion(), '5.0.99', '<')) {
-        return true;
-    }
-    return false;
-}
-
 /**
  * @param array $element the element from the environment.xml file that should have
  *      either a level="required" or level="optional" attribute.
diff --git a/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-debug.js b/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-debug.js
new file mode 100644 (file)
index 0000000..8ec50a7
Binary files /dev/null and b/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-debug.js differ
diff --git a/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js b/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js
new file mode 100644 (file)
index 0000000..6c426ff
Binary files /dev/null and b/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js differ
diff --git a/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask.js b/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask.js
new file mode 100644 (file)
index 0000000..8ec50a7
Binary files /dev/null and b/lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask.js differ
diff --git a/lib/form/yui/passwordunmask/passwordunmask.js b/lib/form/yui/passwordunmask/passwordunmask.js
deleted file mode 100644 (file)
index 1bbefcc..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-YUI.add('moodle-form-passwordunmask', function(Y) {
-    var PASSWORDUNMASK = function() {
-        PASSWORDUNMASK.superclass.constructor.apply(this, arguments);
-    }
-
-    Y.extend(PASSWORDUNMASK, Y.Base, {
-        //Initialize checkbox if id is passed
-        initializer : function(params) {
-            if (params && params.formid) {
-               this.add_checkbox(params.formid, params.checkboxlabel, params.checkboxname);
-            }
-        },
-        //Create checkbox for unmasking password
-        add_checkbox : function(elementid, checkboxlabel, checkboxname) {
-            var node = Y.one('#'+elementid);
-
-            //retaining unmask div from previous implementation.
-            var unmaskdiv = Y.Node.create('<div id="'+elementid+'unmaskdiv" class="unmask"></div>');
-
-            //Add checkbox for unmasking to unmaskdiv
-            var unmaskchb = Y.Node.create('<input id="'+elementid+'unmask" type="checkbox" name="'+
-                checkboxname+'unmask">');
-            unmaskdiv.appendChild(unmaskchb);
-            //Attach event using static javascript function for unmasking password.
-            unmaskchb.on('click', function() {unmaskPassword(elementid);});
-
-            //Add label for checkbox to unmaskdiv
-            var unmasklabel = Y.Node.create('<label for="'+elementid+'unmask">'+checkboxlabel+'</label>');
-            unmaskdiv.appendChild(unmasklabel);
-
-            //Insert unmask div in the same div as password input.
-            node.get('parentNode').insert(unmaskdiv, node.get('lastNode'));
-        }
-    });
-
-    M.form = M.form || {};
-    M.form.passwordunmask = function(params) {
-        return new PASSWORDUNMASK(params);
-    }
-}, '@VERSION@', {requires:['base', 'node']});
diff --git a/lib/form/yui/src/passwordunmask/build.json b/lib/form/yui/src/passwordunmask/build.json
new file mode 100644 (file)
index 0000000..9ad9dac
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "name": "moodle-form-passwordunmask",
+    "builds": {
+        "moodle-form-passwordunmask": {
+            "jsfiles": [
+                "passwordunmask.js"
+            ]
+        }
+    }
+}
diff --git a/lib/form/yui/src/passwordunmask/js/passwordunmask.js b/lib/form/yui/src/passwordunmask/js/passwordunmask.js
new file mode 100644 (file)
index 0000000..63b4748
--- /dev/null
@@ -0,0 +1,39 @@
+var PASSWORDUNMASK = function() {
+    PASSWORDUNMASK.superclass.constructor.apply(this, arguments);
+};
+
+Y.extend(PASSWORDUNMASK, Y.Base, {
+    // Initialize checkbox if id is passed.
+    initializer : function(params) {
+        if (params && params.formid) {
+            this.add_checkbox(params.formid, params.checkboxlabel, params.checkboxname);
+        }
+    },
+
+    // Create checkbox for unmasking password.
+    add_checkbox : function(elementid, checkboxlabel, checkboxname) {
+        var node = Y.one('#'+elementid);
+
+        // Retaining unmask div from previous implementation.
+        var unmaskdiv = Y.Node.create('<div id="'+elementid+'unmaskdiv" class="unmask"></div>');
+
+        // Add checkbox for unmasking to unmaskdiv.
+        var unmaskchb = Y.Node.create('<input id="'+elementid+'unmask" type="checkbox" name="'+
+            checkboxname+'unmask">');
+        unmaskdiv.appendChild(unmaskchb);
+        // Attach event using static javascript function for unmasking password.
+        unmaskchb.on('click', function() {unmaskPassword(elementid);});
+
+        // Add label for checkbox to unmaskdiv.
+        var unmasklabel = Y.Node.create('<label for="'+elementid+'unmask">'+checkboxlabel+'</label>');
+        unmaskdiv.appendChild(unmasklabel);
+
+        // Insert unmask div in the same div as password input.
+        node.get('parentNode').insert(unmaskdiv, node.get('lastNode'));
+    }
+});
+
+M.form = M.form || {};
+M.form.passwordunmask = function(params) {
+    return new PASSWORDUNMASK(params);
+};
diff --git a/lib/form/yui/src/passwordunmask/meta/passwordunmask.json b/lib/form/yui/src/passwordunmask/meta/passwordunmask.json
new file mode 100644 (file)
index 0000000..1830917
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "moodle-form-passwordunmask": {
+        "requires": [
+            "node",
+            "base"
+        ]
+    }
+}
index 654b9de..f3da219 100644 (file)
@@ -172,7 +172,7 @@ class moodle_google_curlio extends Google_CurlIO {
             if (!is_string($name)) {
                 $name = $this->get_option_name_from_constant($name);
             }
-            $safeParams[$name] = $vale;
+            $safeParams[$name] = $value;
         }
         parent::setOptions($safeParams);
     }
index cc3dbb0..52613b5 100644 (file)
@@ -81,11 +81,11 @@ abstract class grade_base_testcase extends advanced_testcase {
     }
 
     private function load_modules() {
-        $this->activities[0] = $this->getDataGenerator()->create_module('assignment', array('course'=>$this->course->id));
-        $this->course_module[0] = get_coursemodule_from_instance('assignment', $this->activities[0]->id);
+        $this->activities[0] = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id));
+        $this->course_module[0] = get_coursemodule_from_instance('assign', $this->activities[0]->id);
 
-        $this->activities[1] = $this->getDataGenerator()->create_module('assignment', array('course'=>$this->course->id));
-        $this->course_module[1] = get_coursemodule_from_instance('assignment', $this->activities[1]->id);
+        $this->activities[1] = $this->getDataGenerator()->create_module('assign', array('course'=>$this->course->id));
+        $this->course_module[1] = get_coursemodule_from_instance('assign', $this->activities[1]->id);
 
         $this->activities[2] = $this->getDataGenerator()->create_module('forum', array('course'=>$this->course->id));
         $this->course_module[2] = get_coursemodule_from_instance('forum', $this->activities[2]->id);
index eca6360..690c352 100644 (file)
@@ -27,7 +27,6 @@ DirectoryIndex index.php index.html index.htm
 
 ### Thirdly, set up some PHP variables that Moodle needs
 
-php_flag register_globals        0
 php_flag file_uploads            1
 php_flag short_open_tag          1
 php_flag session.auto_start      0
index 8fa85e9..066b625 100644 (file)
@@ -718,7 +718,9 @@ M.util.js_watch_io();
  * @return boolean - True if there is any pending js.
  */
 M.util.js_complete = function(uniqid) {
-    var index = M.util.pending_js.indexOf(uniqid);
+    // Use the Y.Array.indexOf instead of the native because some older browsers do not support
+    // the native function. Y.Array polyfills the native function if it does not exist.
+    var index = Y.Array.indexOf(M.util.pending_js, uniqid);
     if (index >= 0) {
         M.util.complete_js.push(M.util.pending_js.splice(index, 1));
     }
index af3fea5..d43d7c7 100644 (file)
@@ -1413,7 +1413,7 @@ class core_renderer extends renderer_base {
                 $output .= $this->block($bc, $region);
                 $lastblock = $bc->title;
             } else if ($bc instanceof block_move_target) {
-                $output .= $this->block_move_target($bc, $zones, $lastblock);
+                $output .= $this->block_move_target($bc, $zones, $lastblock, $region);
             } else {
                 throw new coding_exception('Unexpected type of thing (' . get_class($bc) . ') found in list of block contents.');
             }
@@ -1427,11 +1427,18 @@ class core_renderer extends renderer_base {
      * @param block_move_target $target with the necessary details.
      * @param array $zones array of areas where the block can be moved to
      * @param string $previous the block located before the area currently being rendered.
+     * @param string $region the name of the region
      * @return string the HTML to be output.
      */
-    public function block_move_target($target, $zones, $previous) {
+    public function block_move_target($target, $zones, $previous, $region) {
         if ($previous == null) {
-            $position = get_string('moveblockbefore', 'block', $zones[0]);
+            if (empty($zones)) {
+                // There are no zones, probably because there are no blocks.
+                $regions = $this->page->theme->get_all_block_regions();
+                $position = get_string('moveblockinregion', 'block', $regions[$region]);
+            } else {
+                $position = get_string('moveblockbefore', 'block', $zones[0]);
+            }
         } else {
             $position = get_string('moveblockafter', 'block', $previous);
         }
index 749bcfa..983e5e2 100644 (file)
@@ -205,7 +205,6 @@ ini_set('display_errors', '1');
 ini_set('log_errors', '1');
 
 $CFG->noemailever = true; // better not mail anybody from tests, override temporarily if necessary
-$CFG->cachetext = 0; // disable this very nasty setting
 
 // some ugly hacks
 $CFG->themerev = 1;
index 8c61eeb..0e6c477 100644 (file)
@@ -704,9 +704,6 @@ function ini_get_bool($ini_get_arg) {
 function setup_validate_php_configuration() {
    // this must be very fast - no slow checks here!!!
 
-   if (ini_get_bool('register_globals')) {
-       print_error('globalswarning', 'admin');
-   }
    if (ini_get_bool('session.auto_start')) {
        print_error('sessionautostartwarning', 'admin');
    }
index 2203702..ab6b291 100644 (file)
@@ -60,16 +60,7 @@ class behat_deprecated extends behat_base {
             '" in the "' . $this->escape($tablerowtext) . '" "table_row"';
         $this->deprecated_message($alternative);
 
-        // The table row container.
-        $nocontainerexception = new ElementNotFoundException($this->getSession(), '"' . $tablerowtext . '" row text ');
-        $tablerowtext = $this->getSession()->getSelectorsHandler()->xpathLiteral($tablerowtext);
-        $rownode = $this->find('xpath', "//tr[contains(., $tablerowtext)]", $nocontainerexception);
-
-        // Looking for the element DOM node inside the specified row.
-        list($selector, $locator) = $this->transform_selector($selectortype, $element);
-        $elementnode = $this->find($selector, $locator, false, $rownode);
-        $this->ensure_element_is_visible($elementnode);
-        $elementnode->click();
+        return new Given($alternative);
     }
 
     /**
@@ -233,6 +224,84 @@ class behat_deprecated extends behat_base {
         return array(new Given($alternative));
     }
 
+    /**
+     * Sends a message to the specified user from the logged user.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_message::i_send_message_to_user()
+     *
+     * @Given /^I send "(?P<message_contents_string>(?:[^"]|\\")*)" message to "(?P<username_string>(?:[^"]|\\")*)"$/
+     * @throws ElementNotFoundException
+     * @param string $messagecontent
+     * @param string $tousername
+     */
+    public function i_send_message_to_user($messagecontent, $tousername) {
+
+        global $DB;
+
+        // Runs by CLI, same PHP process that created the user.
+        $touser = $DB->get_record('user', array('username' => $tousername));
+        if (!$touser) {
+            throw new ElementNotFoundException($this->getSession(), '"' . $tousername . '" ');
+        }
+        $tofullname = fullname($touser);
+
+        $alternative = 'I send "' . $this->escape($messagecontent) . '" message to "' . $tofullname . '" user';
+        $this->deprecated_message($alternative);
+        return new Given($alternative);
+    }
+
+    /**
+     * Adds the user to the specified cohort.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_cohort::i_add_user_to_cohort_members()
+     *
+     * @Given /^I add "(?P<user_username_string>(?:[^"]|\\")*)" user to "(?P<cohort_idnumber_string>(?:[^"]|\\")*)" cohort$/
+     * @param string $username
+     * @param string $cohortidnumber
+     */
+    public function i_add_user_to_cohort($username, $cohortidnumber) {
+        global $DB;
+
+        // The user was created by the data generator, executed by the same PHP process that is
+        // running this step, not by any Selenium action.
+        $user = $DB->get_record('user', array('username' => $username));
+        $userlocator = $user->firstname . ' ' . $user->lastname . ' (' . $user->email . ')';
+
+        $alternative = 'I add "' . $this->escape($userlocator) .
+            '" user to "' . $this->escape($cohortidnumber) . '" cohort members';
+        $this->deprecated_message($alternative);
+
+        return new Given($alternative);
+    }
+
+    /**
+     * Add the specified user to the group. You should be in the groups page when running this step.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_groups::i_add_user_to_group_members()
+     *
+     * @Given /^I add "(?P<username_string>(?:[^"]|\\")*)" user to "(?P<group_name_string>(?:[^"]|\\")*)" group$/
+     * @param string $username
+     * @param string $groupname
+     */
+    public function i_add_user_to_group($username, $groupname) {
+        global $DB;
+
+        $user = $DB->get_record('user', array('username' => $username));
+        $userfullname = fullname($user);
+
+        $alternative = 'I add "' . $this->escape($userfullname) .
+            '" user to "' . $this->escape($groupname) . '" group members';
+        $this->deprecated_message($alternative);
+
+        return new Given($alternative);
+    }
+
     /**
      * Throws an exception if $CFG->behat_usedeprecated is not allowed.
      *
index 2478e78..a4c76ac 100644 (file)
@@ -77,6 +77,13 @@ class behat_hooks extends behat_base {
      */
     protected static $currentstepexception = null;
 
+    /**
+     * If we are saving screenshots on failures we should use the same parent dir during a run.
+     *
+     * @var The parent dir name
+     */
+    protected static $screenshotsdirname = false;
+
     /**
      * Gives access to moodle codebase, ensures all is ready and sets up the test lock.
      *
@@ -134,6 +141,10 @@ class behat_hooks extends behat_base {
             // Store the initial browser session opening.
             self::$lastbrowsersessionstart = time();
         }
+
+        if (!empty($CFG->behat_screenshots_path) && !is_writable($CFG->behat_screenshots_path)) {
+            throw new Exception('You set $CFG->behat_screenshots_path to a non-writable directory');
+        }
     }
 
     /**
@@ -258,6 +269,13 @@ class behat_hooks extends behat_base {
      * @AfterStep @javascript
      */
     public function after_step_javascript($event) {
+        global $CFG;
+
+        // Save a screenshot if the step failed.
+        if (!empty($CFG->behat_screenshots_path) &&
+                $event->getResult() === StepEvent::FAILED) {
+            $this->take_screenshot($event);
+        }
 
         try {
             $this->wait_for_pending_js();
@@ -278,6 +296,52 @@ class behat_hooks extends behat_base {
         }
     }
 
+    /**
+     * Getter for self::$screenshotsdirname
+     *
+     * @return string
+     */
+    protected function get_run_screenshots_dir() {
+        return self::$screenshotsdirname;
+    }
+
+    /**
+     * Take screenshot when a step fails.
+     *
+     * @throws Exception
+     * @param StepEvent $event
+     */
+    protected function take_screenshot(StepEvent $event) {
+        global $CFG;
+
+        // Goutte can't save screenshots.
+        if (!$this->running_javascript()) {
+            return false;
+        }
+
+        // All the run screenshots in the same parent dir.
+        if (!$screenshotsdirname = self::get_run_screenshots_dir()) {
+            $screenshotsdirname = self::$screenshotsdirname = date('Y-m-d_Hi');
+
+            $dir = $CFG->behat_screenshots_path . DIRECTORY_SEPARATOR . $screenshotsdirname;
+
+            if (!mkdir($dir, $CFG->directorypermissions, true)) {
+                // It shouldn't, we already checked that the directory is writable.
+                throw new Exception('No directories can be created inside $CFG->behat_screenshots_path, check the directory permissions.');
+            }
+        } else {
+            // We will always need to know the full path.
+            $dir = $CFG->behat_screenshots_path . DIRECTORY_SEPARATOR . $screenshotsdirname;
+        }
+
+        // The scenario title + the failed step text.
+        // We want a i-am-the-scenario-title_i-am-the-failed-step.png format.
+        $filename = $event->getStep()->getParent()->getTitle() . '_' . $event->getStep()->getText();
+        $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename) . '.png';
+
+        $this->saveScreenshot($filename, $dir);
+    }
+
     /**
      * Waits for all the JS to be loaded.
      *
index afc80e3..15a06ca 100644 (file)
@@ -3,6 +3,8 @@ information provided here is intended especially for developers.
 
 === 2.7 ===
 
+* $core_renderer->block_move_target() changed to support more verbose move-block-here descriptions.
+
 DEPRECATIONS:
 * Abstract class \core\event\course_module_instances_list_viewed is deprecated now, use \core\event\instances_list_viewed instead.
 * mod_book\event\instances_list_viewed has been deprecated. Please use mod_book\event\course_module_instance_list_viewed instead.
index a5780b0..43abf4d 100644 (file)
@@ -1097,7 +1097,6 @@ function format_text_menu() {
  */
 function format_text($text, $format = FORMAT_MOODLE, $options = null, $courseiddonotuse = null) {
     global $CFG, $DB, $PAGE;
-    static $croncache = array();
 
     if ($text === '' || is_null($text)) {
         // No need to do any filters and cleaning.
@@ -1166,34 +1165,6 @@ function format_text($text, $format = FORMAT_MOODLE, $options = null, $courseidd
         $filtermanager = new null_filter_manager();
     }
 
-    if (!empty($CFG->cachetext) and empty($options['nocache'])) {
-        $hashstr = $text.'-'.$filtermanager->text_filtering_hash($context).'-'.$context->id.'-'.current_language().'-'.
-                (int)$format.(int)$options['trusted'].(int)$options['noclean'].
-                (int)$options['para'].(int)$options['newlines'];
-
-        $time = time() - $CFG->cachetext;
-        $md5key = md5($hashstr);
-        if (CLI_SCRIPT) {
-            if (isset($croncache[$md5key])) {
-                return $croncache[$md5key];
-            }
-        }
-
-        if ($oldcacheitem = $DB->get_record('cache_text', array('md5key' => $md5key), '*', IGNORE_MULTIPLE)) {
-            if ($oldcacheitem->timemodified >= $time) {
-                if (CLI_SCRIPT) {
-                    if (count($croncache) > 150) {
-                        reset($croncache);
-                        $key = key($croncache);
-                        unset($croncache[$key]);
-                    }
-                    $croncache[$md5key] = $oldcacheitem->formattedtext;
-                }
-                return $oldcacheitem->formattedtext;
-            }
-        }
-    }
-
     switch ($format) {
         case FORMAT_HTML:
             if (!$options['noclean']) {
@@ -1257,65 +1228,15 @@ function format_text($text, $format = FORMAT_MOODLE, $options = null, $courseidd
         }
     }
 
-    // Warn people that we have removed this old mechanism, just in case they
-    // were stupid enough to rely on it.
-    if (isset($CFG->currenttextiscacheable)) {
-        debugging('Once upon a time, Moodle had a truly evil use of global variables ' .
-            'called $CFG->currenttextiscacheable. The good news is that this no ' .
-            'longer exists. The bad news is that you seem to be using a filter that '.
-            'relies on it. Please seek out and destroy that filter code.', DEBUG_DEVELOPER);
-    }
-
     if (!empty($options['overflowdiv'])) {
         $text = html_writer::tag('div', $text, array('class' => 'no-overflow'));
     }
 
-    if (empty($options['nocache']) and !empty($CFG->cachetext)) {
-        if (CLI_SCRIPT) {
-            // Special static cron cache - no need to store it in db if its not already there.
-            if (count($croncache) > 150) {
-                reset($croncache);
-                $key = key($croncache);
-                unset($croncache[$key]);
-            }
-            $croncache[$md5key] = $text;
-            return $text;
-        }
-
-        $newcacheitem = new stdClass();
-        $newcacheitem->md5key = $md5key;
-        $newcacheitem->formattedtext = $text;
-        $newcacheitem->timemodified = time();
-        if ($oldcacheitem) {
-            // See bug 4677 for discussion.
-            $newcacheitem->id = $oldcacheitem->id;
-            try {
-                // Update existing record in the cache table.
-                $DB->update_record('cache_text', $newcacheitem);
-            } catch (dml_exception $e) {
-                // It's unlikely that the cron cache cleaner could have
-                // deleted this entry in the meantime, as it allows
-                // some extra time to cover these cases.
-            }
-        } else {
-            try {
-                // Insert a new record in the cache table.
-                $DB->insert_record('cache_text', $newcacheitem);
-            } catch (dml_exception $e) {
-                // Again, it's possible that another user has caused this
-                // record to be created already in the time that it took
-                // to traverse this function.  That's OK too, as the
-                // call above handles duplicate entries, and eventually
-                // the cron cleaner will delete them.
-            }
-        }
-    }
-
     return $text;
 }
 
 /**
- * Resets all data related to filters, called during upgrade or when filter settings change.
+ * Resets some data related to filters, called during upgrade or when general filter settings change.
  *
  * @param bool $phpunitreset true means called from our PHPUnit integration test reset
  * @return void
@@ -1325,14 +1246,12 @@ function reset_text_filters_cache($phpunitreset = false) {
 
     if ($phpunitreset) {
         // HTMLPurifier does not change, DB is already reset to defaults,
-        // nothing to do here.
+        // nothing to do here, the dataroot was cleared too.
         return;
     }
 
-    $DB->delete_records('cache_text');
-
-    $purifdir = $CFG->cachedir.'/htmlpurifier';
-    remove_dir($purifdir, true);
+    // The purge_all_caches() deals with cachedir and localcachedir purging,
+    // the individual filter caches are invalidated as necessary elsewhere.
 
     // Update $CFG->filterall cache flag.
     if (empty($CFG->stringfilters)) {
index 1e19920..a31d211 100644 (file)
Binary files a/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-debug.js and b/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-debug.js differ
index ed61bb1..fa8b2e3 100644 (file)
Binary files a/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js and b/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js differ
index 1e19920..a31d211 100644 (file)
Binary files a/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue.js and b/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue.js differ
index b4b62ea..ff36c28 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js differ
index b289ee5..62cd2fe 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js differ
index 77dc52d..0c3269e 100644 (file)
Binary files a/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js and b/lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js differ
index 2371c65..a2af79d 100644 (file)
@@ -44,7 +44,8 @@ Y.extend(CHOOSERDIALOGUE, Y.Base, {
             zindex : 100, // Display in front of other items
             modal: true, // This dialogue should be modal.
             shim : true,
-            closeButtonTitle : this.get('closeButtonTitle')
+            closeButtonTitle : this.get('closeButtonTitle'),
+            render : false
         };
 
         // Override with additional options
index ae4a4d4..edd85e8 100644 (file)
@@ -39,15 +39,8 @@ DIALOGUE = function(c) {
     }
 
     config.srcNode =    '#'+id;
-    config.width =      config.width || '400px';
-    config.center =     config.centered && true;
-    config.centered =   false;
     config.COUNT = COUNT;
 
-    if (config.width === 'auto') {
-        delete config.width;
-    }
-
     // closeButton param to keep the stable versions API.
     if (config.closeButton === false) {
         config.buttons = null;
@@ -84,7 +77,9 @@ Y.extend(DIALOGUE, Y.Panel, {
     initializer : function(config) {
         var bb;
 
-        this.render();
+        if (this.get('render')) {
+            this.render();
+        }
         this.makeResponsive();
         this.after('visibleChange', this.visibilityChanged, this);
         if (config.center) {
@@ -448,4 +443,77 @@ Y.extend(DIALOGUE, Y.Panel, {
     }
 });
 
+Y.Base.modifyAttrs(DIALOGUE, {
+    /**
+     * String with units, or number, representing the width of the Widget.
+     * If a number is provided, the default unit, defined by the Widgets
+     * DEF_UNIT, property is used.
+     *
+     * If a value of 'auto' is used, then an empty String is instead
+     * returned.
+     *
+     * @attribute width
+     * @default '400px'
+     * @type {String|Number}
+     */
+    width: {
+        value: '400px',
+        setter: function(value) {
+            if (value === 'auto') {
+                return '';
+            }
+            return value;
+        }
+    },
+
+    /**
+     * Boolean indicating whether or not the Widget is visible.
+     *
+     * We override this from the default Widget attribute value.
+     *
+     * @attribute visible
+     * @default false
+     * @type Boolean
+     */
+    visible: {
+        value: false
+    },
+
+    /**
+     * A convenience Attribute, which can be used as a shortcut for the
+     * `align` Attribute.
+     *
+     * Note: We override this in Moodle such that it sets a value for the
+     * `center` attribute if set. The `centered` will always return false.
+     *
+     * @attribute centered
+     * @type Boolean|Node
+     * @default false
+     */
+    centered: {
+        setter: function(value) {
+            if (value) {
+                this.set('center', true);
+            }
+            return false;
+        }
+    },
+
+    /**
+     * Boolean determining whether to render the widget during initialisation.
+     *
+     * We override this to change the default from false to true for the dialogue.
+     * We then proceed to early render the dialogue during our initialisation rather than waiting
+     * for YUI to render it after that.
+     *
+     * @attribute render
+     * @type Boolean
+     * @default true
+     */
+    render : {
+        value : true,
+        writeOnce : true
+    }
+});
+
 M.core.dialogue = DIALOGUE;
index 3422c8d..71ad670 100644 (file)
@@ -73,7 +73,6 @@ class login_signup_form extends moodleform {
 
         $mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="20"');
         $mform->setType('city', PARAM_TEXT);
-        $mform->addRule('city', get_string('missingcity'), 'required', null, 'server');
         if (!empty($CFG->defaultcity)) {
             $mform->setDefault('city', $CFG->defaultcity);
         }
@@ -82,7 +81,6 @@ class login_signup_form extends moodleform {
         $default_country[''] = get_string('selectacountry');
         $country = array_merge($default_country, $country);
         $mform->addElement('select', 'country', get_string('country'), $country);
-        $mform->addRule('country', get_string('missingcountry'), 'required', null, 'server');
 
         if( !empty($CFG->country) ){
             $mform->setDefault('country', $CFG->country);
index 98e5775..4983b08 100644 (file)
@@ -2062,7 +2062,7 @@ function message_format_message($message, $format='', $keywords='', $class='othe
 
     return <<<TEMPLATE
 <div class='message $class'>
-    <a name="m'.{$message->id}.'"></a>
+    <a name="m{$message->id}"></a>
     <span class="message-meta"><span class="time">$time</span></span>: <span class="text">$messagetext</span>
 </div>
 TEMPLATE;
index ba5f6a5..02fbba6 100644 (file)
@@ -41,23 +41,13 @@ use Behat\Behat\Context\Step\Given as Given,
 class behat_message extends behat_base {
 
     /**
-     * Sends a message to the specified user from the logged user.
+     * Sends a message to the specified user from the logged user. The user full name should contain the first and last names.
      *
-     * @Given /^I send "(?P<message_contents_string>(?:[^"]|\\")*)" message to "(?P<username_string>(?:[^"]|\\")*)"$/
-     * @throws ElementNotFoundException
+     * @Given /^I send "(?P<message_contents_string>(?:[^"]|\\")*)" message to "(?P<user_full_name_string>(?:[^"]|\\")*)" user$/
      * @param string $messagecontent
-     * @param string $tousername
+     * @param string $userfullname
      */
-    public function i_send_message_to_user($messagecontent, $tousername) {
-
-        global $DB;
-
-        // Runs by CLI, same PHP process that created the user.
-        $touser = $DB->get_record('user', array('username' => $tousername));
-        if (!$touser) {
-            throw new ElementNotFoundException($this->getSession(), '"' . $tousername . '" ');
-        }
-        $tofullname = fullname($touser);
+    public function i_send_message_to_user($messagecontent, $userfullname) {
 
         $steps = array();
         $steps[] = new Given('I am on homepage');
@@ -67,9 +57,9 @@ class behat_message extends behat_base {
         }
 
         $steps[] = new Given('I follow "' . get_string('messages', 'message') . '"');
-        $steps[] = new Given('I fill in "' . get_string('searchcombined', 'message') . '" with "' . $this->escape($tofullname) . '"');
+        $steps[] = new Given('I fill in "' . get_string('searchcombined', 'message') . '" with "' . $this->escape($userfullname) . '"');
         $steps[] = new Given('I press "' . get_string('searchcombined', 'message') . '"');
-        $steps[] = new Given('I follow "' . $this->escape(get_string('sendmessageto', 'message', $tofullname)) . '"');
+        $steps[] = new Given('I follow "' . $this->escape(get_string('sendmessageto', 'message', $userfullname)) . '"');
         $steps[] = new Given('I fill in "id_message" with "' . $this->escape($messagecontent) . '"');
         $steps[] = new Given('I press "' . get_string('sendmessage', 'message') . '"');
 
index dbfae92..8fb9a7c 100644 (file)
@@ -10,16 +10,16 @@ Feature: Message history displays correctly
       | user1 | User | One | one@asd.com |
       | user2 | User | Two | two@asd.com |
     And I log in as "user1"
-    And I send "Message 1 from user1 to user2" message to "user2"
-    And I send "Message 2 from user1 to user2" message to "user2"
-    And I send "Message 3 from user1 to user2" message to "user2"
-    And I send "Message 4 from user1 to user2" message to "user2"
-    And I send "Message 5 from user1 to user2" message to "user2"
-    And I send "Message 6 from user1 to user2" message to "user2"
-    And I send "Message 7 from user1 to user2" message to "user2"
-    And I send "Message 8 from user1 to user2" message to "user2"
-    And I send "Message 9 from user1 to user2" message to "user2"
-    And I send "Message 10 from user1 to user2" message to "user2"
+    And I send "Message 1 from user1 to user2" message to "User Two" user
+    And I send "Message 2 from user1 to user2" message to "User Two" user
+    And I send "Message 3 from user1 to user2" message to "User Two" user
+    And I send "Message 4 from user1 to user2" message to "User Two" user
+    And I send "Message 5 from user1 to user2" message to "User Two" user
+    And I send "Message 6 from user1 to user2" message to "User Two" user
+    And I send "Message 7 from user1 to user2" message to "User Two" user
+    And I send "Message 8 from user1 to user2" message to "User Two" user
+    And I send "Message 9 from user1 to user2" message to "User Two" user
+    And I send "Message 10 from user1 to user2" message to "User Two" user
 
   Scenario: View sent messages
     When I expand "My profile" node
index b69204e..2685763 100644 (file)
@@ -10,8 +10,8 @@ Feature: Manage contacts
       | user1 | User | One | one@asd.com |
       | user2 | User | Two | two@asd.com |
     And I log in as "user1"
-    And I send "Message 1 from user1 to user2" message to "user2"
-    And I send "Message 2 from user1 to user2" message to "user2"
+    And I send "Message 1 from user1 to user2" message to "User Two" user
+    And I send "Message 2 from user1 to user2" message to "User Two" user
     And I expand "My profile" node
     And I click on "Messages" "link" in the "Navigation" "block"
     And I fill in "Search people and messages" with "User Two"
index b842a94..acfa6d4 100644 (file)
@@ -10,7 +10,7 @@ Feature: Users can search their message history
       | user1 | User | One | one@asd.com |
       | user2 | User | Two | two@asd.com |
     And I log in as "user1"
-    When I send "Give me your biscuits" message to "user2"
+    When I send "Give me your biscuits" message to "User Two" user
     And I expand "My profile" node
     And I click on "Messages" "link" in the "Navigation" "block"
     And I fill in "Search people and messages" with "your biscuits"
index 0373e33..3d07191 100644 (file)
@@ -51,6 +51,7 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
                                                   'submissiondrafts',
                                                   'sendnotifications',
                                                   'sendlatenotifications',
+                                                  'sendstudentnotifications',
                                                   'duedate',
                                                   'cutoffdate',
                                                   'allowsubmissionsfromdate',
index 4cd7e49..7befb9c 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/assign/db" VERSION="20130314" COMMENT="XMLDB file for Moodle mod/assign"
+<XMLDB PATH="mod/assign/db" VERSION="20131220" COMMENT="XMLDB file for Moodle mod/assign"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
 >
@@ -32,6 +32,7 @@
         <FIELD NAME="maxattempts" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="-1" SEQUENCE="false" COMMENT="What is the maximum number of student attempts allowed for this assignment? -1 means unlimited."/>
         <FIELD NAME="markingworkflow" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking workflow features will be used in this assignment."/>
         <FIELD NAME="markingallocation" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking allocation features will be used in this assignment"/>
+        <FIELD NAME="sendstudentnotifications" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Default for send student notifications checkbox when grading."/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment instance."/>
       </INDEXES>
     </TABLE>
   </TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
index b8e3eac..53142f0 100644 (file)
@@ -462,5 +462,27 @@ function xmldb_assign_upgrade($oldversion) {
     // Moodle v2.6.0 release upgrade line.
     // Put any upgrade step following this.
 
+    if ($oldversion < 2014010801) {
+
+        // Define field sendstudentnotifications to be added to assign.
+        $table = new xmldb_table('assign');
+        $field = new xmldb_field('sendstudentnotifications',
+                                 XMLDB_TYPE_INTEGER,
+                                 '2',
+                                 null,
+                                 XMLDB_NOTNULL,
+                                 null,
+                                 '1',
+                                 'markingallocation');
+
+        // Conditionally launch add field sendstudentnotifications.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Assign savepoint reached.
+        upgrade_mod_savepoint(true, 2014010801, 'assign');
+    }
+
     return true;
 }
index cf582ce..fd28223 100644 (file)
@@ -312,11 +312,29 @@ class mod_assign_external extends external_api {
                 unset($courses[$id]);
             }
         }
-        $extrafields='m.id as assignmentid, m.course, m.nosubmissions, m.submissiondrafts, m.sendnotifications, '.
-                     'm.sendlatenotifications, m.duedate, m.allowsubmissionsfromdate, m.grade, m.timemodified, '.
-                     'm.completionsubmit, m.cutoffdate, m.teamsubmission, m.requireallteammemberssubmit, '.
-                     'm.teamsubmissiongroupingid, m.blindmarking, m.revealidentities, m.attemptreopenmethod, '.
-                     'm.maxattempts, m.markingworkflow, m.markingallocation, m.requiresubmissionstatement';
+        $extrafields='m.id as assignmentid, ' .
+                     'm.course, ' .
+                     'm.nosubmissions, ' .
+                     'm.submissiondrafts, ' .
+                     'm.sendnotifications, '.
+                     'm.sendlatenotifications, ' .
+                     'm.sendstudentnotifications, ' .
+                     'm.duedate, ' .
+                     'm.allowsubmissionsfromdate, '.
+                     'm.grade, ' .
+                     'm.timemodified, '.
+                     'm.completionsubmit, ' .
+                     'm.cutoffdate, ' .
+                     'm.teamsubmission, ' .
+                     'm.requireallteammemberssubmit, '.
+                     'm.teamsubmissiongroupingid, ' .
+                     'm.blindmarking, ' .
+                     'm.revealidentities, ' .
+                     'm.attemptreopenmethod, '.
+                     'm.maxattempts, ' .
+                     'm.markingworkflow, ' .
+                     'm.markingallocation, ' .
+                     'm.requiresubmissionstatement';
         $coursearray = array();
         foreach ($courses as $id => $course) {
             $assignmentarray = array();
@@ -359,6 +377,7 @@ class mod_assign_external extends external_api {
                         'submissiondrafts' => $module->submissiondrafts,
                         'sendnotifications' => $module->sendnotifications,
                         'sendlatenotifications' => $module->sendlatenotifications,
+                        'sendstudentnotifications' => $module->sendstudentnotifications,
                         'duedate' => $module->duedate,
                         'allowsubmissionsfromdate' => $module->allowsubmissionsfromdate,
                         'grade' => $module->grade,
@@ -412,6 +431,7 @@ class mod_assign_external extends external_api {
                 'submissiondrafts' => new external_value(PARAM_INT, 'submissions drafts'),
                 'sendnotifications' => new external_value(PARAM_INT, 'send notifications'),
                 'sendlatenotifications' => new external_value(PARAM_INT, 'send notifications'),
+                'sendstudentnotifications' => new external_value(PARAM_INT, 'send student notifications (default)'),
                 'duedate' => new external_value(PARAM_INT, 'assignment due date'),
                 'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'allow submissions from date'),
                 'grade' => new external_value(PARAM_INT, 'grade type'),
index 2c61ed0..b677b20 100644 (file)
@@ -312,6 +312,10 @@ $string['savegradingresult'] = 'Grade';
 $string['saveallquickgradingchanges'] = 'Save all quick grading changes';
 $string['savenext'] = 'Save and show next';
 $string['scale'] = 'Scale';
+$string['sendstudentnotificationsdefault'] = 'Default setting for "Notify students"';
+$string['sendstudentnotificationsdefault_help'] = 'Set the default value for the "Notify students" checkbox on the grading form.';
+$string['sendstudentnotifications'] = 'Notify students';
+$string['sendstudentnotifications_help'] = 'If enabled, students receive a message about the updated grade or feedback.';
 $string['sendnotifications'] = 'Notify graders about submissions';
 $string['sendnotifications_help'] = 'If enabled, graders (usually teachers) receive a message whenever a student submits an assignment, early, on time and late. Message methods are configurable.';
 $string['selectlink'] = 'Select...';
index 2d5acfd..404b695 100644 (file)
@@ -538,6 +538,7 @@ class assign {
      */
     public function add_instance(stdClass $formdata, $callplugins) {
         global $DB;
+        $adminconfig = $this->get_admin_config();
 
         $err = '';
 
@@ -555,6 +556,10 @@ class assign {
         $update->requiresubmissionstatement = $formdata->requiresubmissionstatement;
         $update->sendnotifications = $formdata->sendnotifications;
         $update->sendlatenotifications = $formdata->sendlatenotifications;
+        $update->sendstudentnotifications = $adminconfig->sendstudentnotifications;
+        if (isset($formdata->sendstudentnotifications)) {
+            $update->sendstudentnotifications = $formdata->sendstudentnotifications;
+        }
         $update->duedate = $formdata->duedate;
         $update->cutoffdate = $formdata->cutoffdate;
         $update->allowsubmissionsfromdate = $formdata->allowsubmissionsfromdate;
@@ -878,6 +883,7 @@ class assign {
      */
     public function update_instance($formdata) {
         global $DB;
+        $adminconfig = $this->get_admin_config();
 
         $update = new stdClass();
         $update->id = $formdata->instance;
@@ -891,6 +897,10 @@ class assign {
         $update->requiresubmissionstatement = $formdata->requiresubmissionstatement;
         $update->sendnotifications = $formdata->sendnotifications;
         $update->sendlatenotifications = $formdata->sendlatenotifications;
+        $update->sendstudentnotifications = $adminconfig->sendstudentnotifications;
+        if (isset($formdata->sendstudentnotifications)) {
+            $update->sendstudentnotifications = $formdata->sendstudentnotifications;
+        }
         $update->duedate = $formdata->duedate;
         $update->cutoffdate = $formdata->cutoffdate;
         $update->allowsubmissionsfromdate = $formdata->allowsubmissionsfromdate;
@@ -3107,7 +3117,9 @@ class assign {
         if ($showquickgrading && $quickgrading) {
             $gradingtable = new assign_grading_table($this, $perpage, $filter, 0, true);
             $table = $this->get_renderer()->render($gradingtable);
-            $quickformparams = array('cm'=>$this->get_course_module()->id, 'gradingtable'=>$table);
+            $quickformparams = array('cm'=>$this->get_course_module()->id,
+                                     'gradingtable'=>$table,
+                                     'sendstudentnotifications'=>$this->get_instance()->sendstudentnotifications);
             $quickgradingform = new mod_assign_quick_grading_form(null, $quickformparams);
 
             $o .= $this->get_renderer()->render(new assign_form('quickgradingform', $quickgradingform));
@@ -4401,6 +4413,7 @@ class assign {
 
         $info = new stdClass();
         if ($blindmarking) {
+            $userfrom = clone($userfrom);
             $info->username = get_string('participant', 'assign') . ' ' . $uniqueidforuser;
             $userfrom->firstname = get_string('participant', 'assign');
             $userfrom->lastname = $uniqueidforuser;
@@ -4928,7 +4941,10 @@ class assign {
                 $this->update_user_flags($flags);
             }
             $this->update_grade($grade);
-            $this->notify_grade_modified($grade);
+            // Allow teachers to skip sending notifications.
+            if (optional_param('sendstudentnotifications', true, PARAM_BOOL)) {
+                $this->notify_grade_modified($grade);
+            }
 
             // Save outcomes.
             if ($CFG->enableoutcomes) {
@@ -5720,6 +5736,8 @@ class assign {
                 $mform->setDefault('addattempt', 0);
             }
         }
+        $mform->addElement('selectyesno', 'sendstudentnotifications', get_string('sendstudentnotifications', 'assign'));
+        $mform->setDefault('sendstudentnotifications', $this->get_instance()->sendstudentnotifications);
 
         $mform->addElement('hidden', 'action', 'submitgrade');
         $mform->setType('action', PARAM_ALPHA);
@@ -6215,7 +6233,11 @@ class assign {
             }
         }
         $this->update_grade($grade);
-        $this->notify_grade_modified($grade);
+        // Note the default if not provided for this option is true (e.g. webservices).
+        // This is for backwards compatibility.
+        if (!isset($formdata->sendstudentnotifications) || $formdata->sendstudentnotifications) {
+            $this->notify_grade_modified($grade);
+        }
 
         $addtolog = $this->add_to_log('grade submission', $this->format_grade_for_log($grade), '', true);
         $params = array(
index 1cd183c..eead2ae 100644 (file)
@@ -159,6 +159,10 @@ class mod_assign_mod_form extends moodleform_mod {
         $mform->addHelpButton('sendlatenotifications', 'sendlatenotifications', 'assign');
         $mform->disabledIf('sendlatenotifications', 'sendnotifications', 'eq', 1);
 
+        $name = get_string('sendstudentnotificationsdefault', 'assign');
+        $mform->addElement('selectyesno', 'sendstudentnotifications', $name);
+        $mform->addHelpButton('sendstudentnotifications', 'sendstudentnotificationsdefault', 'assign');
+
         // Plagiarism enabling form.
         if (!empty($CFG->enableplagiarism)) {
             require_once($CFG->libdir . '/plagiarismlib.php');
index 2e93df7..bff0294 100644 (file)
@@ -52,6 +52,10 @@ class mod_assign_quick_grading_form extends moodleform {
         $mform->addElement('hidden', 'action', 'quickgrade');
         $mform->setType('action', PARAM_ALPHA);
 
+        // Skip notifications option.
+        $mform->addElement('selectyesno', 'sendstudentnotifications', get_string('sendstudentnotifications', 'assign'));
+        $mform->setDefault('sendstudentnotifications', $instance['sendstudentnotifications']);
+
         // Buttons.
         $savemessage = get_string('saveallquickgradingchanges', 'assign');
         $mform->addElement('submit', 'savequickgrades', $savemessage);
index 04575f4..c923788 100644 (file)
@@ -213,6 +213,16 @@ if ($ADMIN->fulltree) {
     $setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
     $settings->add($setting);
 
+    $name = new lang_string('sendstudentnotificationsdefault', 'mod_assign');
+    $description = new lang_string('sendstudentnotificationsdefault_help', 'mod_assign');
+    $setting = new admin_setting_configcheckbox('assign/sendstudentnotifications',
+                                                    $name,
+                                                    $description,
+                                                    1);
+    $setting->set_advanced_flag_options(admin_setting_flag::ENABLED, false);
+    $setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
+    $settings->add($setting);
+
     $name = new lang_string('blindmarking', 'mod_assign');
     $description = new lang_string('blindmarking_help', 'mod_assign');
     $setting = new admin_setting_configcheckbox('assign/blindmarking',
index 62675ce..1487284 100644 (file)
@@ -50,8 +50,8 @@ Feature: Group assignment submissions
     And I press "Save changes"
     And I expand "Users" node
     And I follow "Groups"
-    And I add "student0" user to "Group 1" group
-    And I add "student1" user to "Group 1" group
+    And I add "Student 0 (student0@asd.com)" user to "Group 1" group members
+    And I add "Student 1 (student1@asd.com)" user to "Group 1" group members
     And I follow "Course 1"
     And I follow "Test assignment name"
     And I follow "View/grade all submissions"
index 2e88966..07600d8 100644 (file)
@@ -34,6 +34,7 @@ class mod_assign_generator extends testing_module_generator {
             'submissiondrafts'                  => 1,
             'requiresubmissionstatement'        => 0,
             'sendnotifications'                 => 0,
+            'sendstudentnotifications'          => 1,
             'sendlatenotifications'             => 0,
             'duedate'                           => 0,
             'allowsubmissionsfromdate'          => 0,
index 77c0897..a1ca542 100644 (file)
@@ -527,7 +527,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
 
         // Now create an assignment and add some feedback.
         $this->setUser($this->editingteachers[0]);
-        $assign = $this->create_instance();
+        $assign = $this->create_instance(array('sendstudentnotifications'=>1));
 
         // Simulate adding a grade.
         $this->setUser($this->teachers[0]);
@@ -536,6 +536,9 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         $assign->testable_apply_grade_to_user($data, $this->students[0]->id, 0);
         $assign->testable_apply_grade_to_user($data, $this->students[1]->id, 0);
 
+        $data->sendstudentnotifications = false;
+        $assign->testable_apply_grade_to_user($data, $this->students[2]->id, 0);
+
         // Now run cron and see that one message was sent.
         $this->preventResetByRollback();
         $sink = $this->redirectMessages();
@@ -544,6 +547,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
         assign::cron();
 
         $messages = $sink->get_messages();
+        // The sent count should be 2, because the 3rd one was marked as do not send notifications.
         $this->assertEquals(2, count($messages));
         $this->assertEquals(1, $messages[0]->notification);
         $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
index 2c71b5c..7de1d26 100644 (file)
@@ -53,15 +53,13 @@ class mod_assign_upgradelib_testcase extends mod_assign_base_testcase {
         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
         $params = array('course'=>$this->course->id,
                         'assignmenttype'=>'upload');
-        $record = $generator->create_instance($params);
-
-        $assignment = new assignment_base($record->cmid);
+        $assignment = $generator->create_instance($params);
 
         $this->setAdminUser();
         $log = '';
         $upgrader = new assign_upgrade_manager();
 
-        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->id, $log));
         $record = $DB->get_record('assign', array('course'=>$this->course->id));
 
         $cm = get_coursemodule_from_instance('assign', $record->id);
@@ -99,15 +97,13 @@ class mod_assign_upgradelib_testcase extends mod_assign_base_testcase {
         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
         $params = array('course'=>$this->course->id,
                         'assignmenttype'=>'uploadsingle');
-        $record = $generator->create_instance($params);
-
-        $assignment = new assignment_base($record->cmid);
+        $assignment = $generator->create_instance($params);
 
         $this->setAdminUser();
         $log = '';
         $upgrader = new assign_upgrade_manager();
 
-        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->id, $log));
         $record = $DB->get_record('assign', array('course'=>$this->course->id));
 
         $cm = get_coursemodule_from_instance('assign', $record->id);
@@ -145,15 +141,13 @@ class mod_assign_upgradelib_testcase extends mod_assign_base_testcase {
         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
         $params = array('course'=>$this->course->id,
                         'assignmenttype'=>'online');
-        $record = $generator->create_instance($params);
-
-        $assignment = new assignment_base($record->cmid);
+        $assignment = $generator->create_instance($params);
 
         $this->setAdminUser();
         $log = '';
         $upgrader = new assign_upgrade_manager();
 
-        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->id, $log));
         $record = $DB->get_record('assign', array('course'=>$this->course->id));
 
         $cm = get_coursemodule_from_instance('assign', $record->id);
@@ -191,15 +185,13 @@ class mod_assign_upgradelib_testcase extends mod_assign_base_testcase {
         $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
         $params = array('course'=>$this->course->id,
                         'assignmenttype'=>'offline');
-        $record = $generator->create_instance($params);
-
-        $assignment = new assignment_base($record->cmid);
+        $assignment = $generator->create_instance($params);
 
         $this->setAdminUser();
         $log = '';
         $upgrader = new assign_upgrade_manager();
 
-        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->id, $log));
         $record = $DB->get_record('assign', array('course'=>$this->course->id));
 
         $cm = get_coursemodule_from_instance('assign', $record->id);
index 601d8b5..ec94096 100644 (file)
@@ -1,4 +1,7 @@
 This files describes API changes in the assign code.
+=== 2.7 ===
+* Added setting sendstudentnotifications to assign DB table with admin defaults. This sets the default value for the
+  "Notify students" option on the grading forms. This setting can be retrieved via webservices.
 
 === 2.6.1 ===
 
index 1b26b56..aef0f14 100644 (file)
@@ -299,6 +299,15 @@ class assign_upgrade_manager {
             $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?';
             $DB->execute($sql, $params);
 
+            // Create a mapping record to map urls from the old to the new assignment.
+            $mapping = new stdClass();
+            $mapping->oldcmid = $oldcoursemodule->id;
+            $mapping->oldinstance = $oldassignment->id;
+            $mapping->newcmid = $newcoursemodule->id;
+            $mapping->newinstance = $newassignment->get_instance()->id;
+            $mapping->timecreated = time();
+            $DB->insert_record('assignment_upgrade', $mapping);
+
             $gradesdone = true;
 
         } catch (Exception $exception) {
index 60a2aa6..a2e1f9a 100644 (file)
@@ -25,7 +25,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $module->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
-$module->version  = 2014010700;    // The current module version (Date: YYYYMMDDXX).
+$module->version  = 2014010801;    // The current module version (Date: YYYYMMDDXX).
 $module->requires = 2013110500;    // Requires this Moodle version.
 $module->cron     = 60;
 
diff --git a/mod/assignment/assignment.js b/mod/assignment/assignment.js
deleted file mode 100644 (file)
index 07c1af3..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-var assignment = {};
-
-function setNext(){
-    document.getElementById('submitform').mode.value = 'next';
-    document.getElementById('submitform').userid.value = assignment.nextid;
-}
-
-function saveNext(){
-    document.getElementById('submitform').mode.value = 'saveandnext';
-    document.getElementById('submitform').userid.value = assignment.nextid;
-    document.getElementById('submitform').saveuserid.value = assignment.userid;
-    document.getElementById('submitform').menuindex.value = document.getElementById('submitform').grade.selectedIndex;
-}
-
-function initNext(nextid, usserid) {
-    assignment.nextid = nextid;
-    assignment.userid = userid;
-}
-
-M.mod_assignment = {};
-
-M.mod_assignment.init_tree = function(Y, expand_all, htmlid) {
-    Y.use('yui2-treeview', function(Y) {
-        var tree = new Y.YUI2.widget.TreeView(htmlid);
-
-        tree.subscribe("clickEvent", function(node, event) {
-            // we want normal clicking which redirects to url
-            return false;
-        });
-
-        if (expand_all) {
-            tree.expandAll();
-        }
-
-        tree.render();
-    });
-};
-
-M.mod_assignment.init_grade_change = function(Y) {
-    var gradenode = Y.one('#id_grade');
-    if (gradenode) {
-        var originalvalue = gradenode.get('value');
-        gradenode.on('change', function() {
-            if (gradenode.get('value') != originalvalue) {
-                alert(M.str.mod_assignment.changegradewarning);
-            }
-        });
-    }
-};
index e5d8a7f..072e87f 100644 (file)
@@ -109,4 +109,13 @@ class restore_assignment_activity_task extends restore_activity_task {
 
         return $rules;
     }
+
+    /**
+     * Expose the restore mode so we can skip automatic upgrade for MODE_IMPORT (e.g. duplicate).
+     *
+     * @return int
+     */
+    public function get_mode() {
+        return $this->plan->get_mode();
+    }
 }
index b7f8f56..11ee37d 100644 (file)
@@ -98,6 +98,46 @@ class restore_assignment_activity_structure_step extends restore_activity_struct
         $this->set_mapping(restore_gradingform_plugin::itemid_mapping('submission'), $oldid, $newitemid);
     }
 
+    /**
+     * This function will attempt to upgrade the newly restored assignment to an instance of mod_assign if
+     * mod_assignment is currently disabled and mod_assign is enabled and mod_assign says it can upgrade this assignment.
+     *
+     * @return none
+     */
+    private function upgrade_mod_assign() {
+        global $DB, $CFG;
+
+        // The current module must exist.
+        $pluginmanager = core_plugin_manager::instance();
+
+        $plugininfo = $pluginmanager->get_plugin_info('mod_assign');
+
+        // Check that the assignment module is installed.
+        if ($plugininfo && $plugininfo->is_installed_and_upgraded()) {
+            // Include the required mod assign upgrade code.
+            require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
+            require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+            // Get the id and type of this assignment.
+            $newinstance = $this->task->get_activityid();
+
+            $record = $DB->get_record('assignment', array('id'=>$newinstance), 'assignmenttype', MUST_EXIST);
+            $type = $record->assignmenttype;
+
+            $subplugininfo = $pluginmanager->get_plugin_info('assignment_' . $type);
+
+            // See if it is possible to upgrade.
+            if (assign::can_upgrade_assignment($type, $subplugininfo->versiondb)) {
+                $assignment_upgrader = new assign_upgrade_manager();
+                $log = '';
+                $success = $assignment_upgrader->upgrade_assignment($newinstance, $log);
+                if (!$success) {
+                    throw new restore_step_exception('mod_assign_upgrade_failed', $log);
+                }
+            }
+        }
+    }
+
     protected function after_execute() {
         // Add assignment related files, no need to match by itemname (just internally handled context)
         $this->add_related_files('mod_assignment', 'intro', null);
@@ -106,6 +146,17 @@ class restore_assignment_activity_structure_step extends restore_activity_struct
         $this->add_related_files('mod_assignment', 'response', 'assignment_submission');
     }
 
+    /**
+     * Hook to execute assignment upgrade after restore.
+     */
+    protected function after_restore() {
+
+        if ($this->get_task()->get_mode() != backup::MODE_IMPORT) {
+            // Moodle 2.2 assignment upgrade
+            $this->upgrade_mod_assign();
+        }
+    }
+
     /**
      * Determine if a sub-plugin is supported or not
      *
index e76cc0a..656a963 100644 (file)
@@ -29,7 +29,17 @@ defined('MOODLE_INTERNAL') || die();
 
 
 class assignment extends base {
-    public function is_uninstall_allowed() {
+    /**
+     * Returns the information about plugin availability
+     *
+     * True means that the plugin is enabled. False means that the plugin is
+     * disabled. Null means that the information is not available, or the
+     * plugin does not support configurable availability or the availability
+     * can not be changed.
+     *
+     * @return null|bool
+     */
+    public function is_enabled() {
         return false;
     }
 }
index c517366..a820de3 100644 (file)
         <INDEX NAME="timemarked" UNIQUE="false" FIELDS="timemarked"/>
       </INDEXES>
     </TABLE>
+    <TABLE NAME="assignment_upgrade" COMMENT="Info about upgraded assignments">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
+        <FIELD NAME="oldcmid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
+        <FIELD NAME="oldinstance" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
+        <FIELD NAME="newcmid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
+        <FIELD NAME="newinstance" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
+        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="oldcmid" UNIQUE="false" FIELDS="oldcmid"/>
+        <INDEX NAME="oldinstance" UNIQUE="false" FIELDS="oldinstance"/>
+      </INDEXES>
+    </TABLE>
   </TABLES>
-</XMLDB>
\ No newline at end of file
+</XMLDB>
index cc74faf..a6c69cd 100644 (file)
@@ -23,8 +23,9 @@
 function xmldb_assignment_upgrade($oldversion) {
     global $CFG, $DB, $OUTPUT;
 
-    $dbman = $DB->get_manager();
+    require_once(__DIR__.'/upgradelib.php');
 
+    $dbman = $DB->get_manager();
 
     // Moodle v2.2.0 release upgrade line
     // Put any upgrade step following this
@@ -81,6 +82,55 @@ function xmldb_assignment_upgrade($oldversion) {
     // Moodle v2.6.0 release upgrade line.
     // Put any upgrade step following this.
 
+    if ($oldversion < 2013121900) {
+        // Define table assignment_upgrade to be created.
+        $table = new xmldb_table('assignment_upgrade');
+
+        // Adding fields to table assignment_upgrade.
+        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+        $table->add_field('oldcmid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+        $table->add_field('oldinstance', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+        $table->add_field('newcmid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+        $table->add_field('newinstance', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+
+        // Adding keys to table assignment_upgrade.
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+
+        // Adding indexes to table assignment_upgrade.
+        $table->add_index('oldcmid', XMLDB_INDEX_NOTUNIQUE, array('oldcmid'));
+        $table->add_index('oldinstance', XMLDB_INDEX_NOTUNIQUE, array('oldinstance'));
+
+        // Conditionally launch create table for assignment_upgrade.
+        if (!$dbman->table_exists($table)) {
+            $dbman->create_table($table);
+        }
+
+        if ($module = $DB->get_record("modules", array("name" => "assignment"))) {
+            $DB->set_field("modules", "visible", "0", array("id" => $module->id)); // Hide module.
+            // Hide all course modules.
+            $sql = "UPDATE {course_modules}
+                       SET visibleold = visible, visible = 0
+                     WHERE module = ?";
+            $DB->execute($sql, array($module->id));
+            // Increment course.cacherev for courses where we just made something invisible.
+            // This will force cache rebuilding on the next request.
+            increment_revision_number('course', 'cacherev',
+                    "id IN (SELECT DISTINCT course
+                                    FROM {course_modules}
+                                   WHERE visibleold = 1 AND module = ?)",
+                    array($module->id));
+        }
+
+        $count = $DB->count_records('assignment');
+        if ($count) {
+            mod_assignment_pending_upgrades_notification($count);
+        }
+
+        // Assignment savepoint reached.
+        upgrade_mod_savepoint(true, 2013121900, 'assignment');
+    }
+
     return true;
 }
 
diff --git a/mod/assignment/db/upgradelib.php b/mod/assignment/db/upgradelib.php
new file mode 100644 (file)
index 0000000..d245d35
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Assignment upgrade script.
+ *
+ * @package   mod_assignment
+ * @copyright 2013 Damyon Wiese
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Inform admins about assignments that still need upgrading.
+ */
+function mod_assignment_pending_upgrades_notification($count) {
+    $admins = get_admins();
+
+    if (empty($admins)) {
+        return;
+    }
+
+    $a = new stdClass;
+    $a->count = $count;
+    $a->docsurl = get_docs_url('Assignment_upgrade_tool');
+    foreach ($admins as $admin) {
+        $message = new stdClass();
+        $message->component         = 'moodle';
+        $message->name              = 'notices';
+        $message->userfrom          = \core_user::get_noreply_user();
+        $message->userto            = $admin;
+        $message->smallmessage      = get_string('pendingupgrades_message_small', 'mod_assignment');
+        $message->subject           = get_string('pendingupgrades_message_subject', 'mod_assignment');
+        $message->fullmessage       = get_string('pendingupgrades_message_content', 'mod_assignment', $a);
+        $message->fullmessagehtml   = get_string('pendingupgrades_message_content', 'mod_assignment', $a);
+        $message->fullmessageformat = FORMAT_PLAIN;
+        $message->notification      = 1;
+        message_send($message);
+    }
+}
diff --git a/mod/assignment/delete.php b/mod/assignment/delete.php
deleted file mode 100644 (file)
index c5cbea7..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-require_once('../../config.php');
-require_once('lib.php');
-
-$id = optional_param('id', 0, PARAM_INT);  // Course module ID
-$a  = optional_param('a', 0, PARAM_INT);   // Assignment ID
-
-$url = new moodle_url('/mod/assignment/delete.php');
-if ($id) {
-    if (! $cm = get_coursemodule_from_id('assignment', $id)) {
-        print_error('invalidcoursemodule');
-    }
-
-    if (! $assignment = $DB->get_record('assignment', array('id'=>$cm->instance))) {
-        print_error('invalidid', 'assignment');
-    }
-
-    if (! $course = $DB->get_record('course', array('id'=>$assignment->course))) {
-        print_error('coursemisconf', 'assignment');
-    }
-    $url->param('id', $id);
-} else {
-    if (!$assignment = $DB->get_record('assignment', array('id'=>$a))) {
-        print_error('invalidcoursemodule');
-    }
-    if (! $course = $DB->get_record('course', array('id'=>$assignment->course))) {
-        print_error('coursemisconf', 'assignment');
-    }
-    if (! $cm = get_coursemodule_from_instance('assignment', $assignment->id, $course->id)) {
-        print_error('invalidcoursemodule');
-    }
-    $url->param('a', $a);
-}
-
-$PAGE->set_url($url);
-require_login($course, false, $cm);
-
-/// Load up the required assignment code
-require($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php');
-$assignmentclass = 'assignment_'.$assignment->assignmenttype;
-$assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course);
-
-$assignmentinstance->delete();   // delete something
\ No newline at end of file
diff --git a/mod/assignment/grade.php b/mod/assignment/grade.php
deleted file mode 100644 (file)
index 543b762..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Redirect the user to the appropriate submission related page within /mod/assignment
- *
- * Based on the supplied parameters and the user's capabilities the user will be redirected
- * to either their own submission, a particular student's submission or a summary of all submissions
- *
- * @package   mod_assignment
- * @category  grade
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once("../../config.php");
-
-$id   = required_param('id', PARAM_INT);          // Course module ID
-$userid = optional_param('userid', 0, PARAM_INT); // Graded user ID (optional)
-
-$PAGE->set_url('/mod/assignment/grade.php', array('id'=>$id));
-if (! $cm = get_coursemodule_from_id('assignment', $id)) {
-    print_error('invalidcoursemodule');
-}
-
-if (! $assignment = $DB->get_record("assignment", array("id"=>$cm->instance))) {
-    print_error('invalidid', 'assignment');
-}
-
-if (! $course = $DB->get_record("course", array("id"=>$assignment->course))) {
-    print_error('coursemisconf', 'assignment');
-}
-
-require_login($course, false, $cm);
-
-if (has_capability('mod/assignment:grade', context_module::instance($cm->id))) {
-    if ($userid) {
-        redirect('submissions.php?id='.$cm->id.'&userid='.$userid.'&mode=single&filter=0&offset=0');
-    } else {
-        redirect('submissions.php?id='.$cm->id);
-    }
-} else {
-    // user will view his own submission, parameter $userid is ignored
-    redirect('view.php?id='.$cm->id);
-}
index ad94134..9e0c70c 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['activityoverview'] = 'You have assignments that need attention';
-$string['allowdeleting'] = 'Allow deleting';
-$string['allowdeleting_help'] = 'If enabled, students may delete uploaded files at any time before submitting for grading.';
-$string['allowmaxfiles'] = 'Maximum number of uploaded files';
-$string['allowmaxfiles_help'] = 'The maximum number of files which may be uploaded. As this figure is not displayed anywhere, it is suggested that it is mentioned in the assignment description.';
-$string['allownotes'] = 'Allow notes';
-$string['allownotes_help'] = 'If enabled, students may enter notes into a text area, as in an online text assignment.';
-$string['allowresubmit'] = 'Allow resubmitting';
-$string['allowresubmit_help'] = 'If enabled, students will be allowed to resubmit assignments after they have been graded (for them to be re-graded).';
-$string['alreadygraded'] = 'Your assignment has already been graded and resubmission is not allowed.';
 $string['assignment:addinstance'] = 'Add a new assignment';
-$string['assignmentdetails'] = 'Assignment details';
 $string['assignment:exportownsubmission'] = 'Export own submission';
 $string['assignment:exportsubmission'] = 'Export submission';
 $string['assignment:grade'] = 'Grade assignment';
-$string['assignmentmail'] = '{$a->teacher} has posted some feedback on your
-assignment submission for \'{$a->assignment}\'
-
-You can see it appended to your assignment submission:
-
-    {$a->url}';
-$string['assignmentmailhtml'] = '<p>{$a->teacher} has posted some feedback on your
-assignment submission for \'<i>{$a->assignment}</i>\'.</p>
-<p>You can see it appended to your <a href="{$a->url}">assignment submission</a>.</p>';
-$string['assignmentmailsmall'] = '{$a->teacher} has posted some feedback on your
-assignment submission for \'{$a->assignment}\' You can see it appended to your submission';
-$string['assignmentname'] = 'Assignment name';
 $string['assignment:submit'] = 'Submit assignment';
-$string['assignmentsubmission'] = 'Assignment submissions';
-$string['assignmenttype'] = 'Assignment type';
 $string['assignment:view'] = 'View assignment';
-$string['availabledate'] = 'Available from';
-$string['cannotdeletefiles'] = 'An error occurred and files could not be deleted';
-$string['cannotviewassignment'] = 'You can not view this assignment';
-$string['changegradewarning'] = 'This assignment has graded submissions and changing the grade will not automatically re-calculate existing submission grades. You must re-grade all existing submissions, if you wish to change the grade.';
-$string['closedassignment'] = 'This assignment is closed, as the submission deadline has passed.';
-$string['comment'] = 'Comment';
-$string['commentinline'] = 'Comment inline';
-$string['commentinline_help'] = 'If enabled, the submission text will be copied into the feedback comment field during grading, making it easier to comment inline (using a different colour, perhaps) or to edit the original text.';
-$string['configitemstocount'] = 'Nature of items to be counted for student submissions in online assignments.';
-$string['configmaxbytes'] = 'Default maximum assignment size for all assignments on the site (subject to course limits and other local settings)';
-$string['configshowrecentsubmissions'] = 'Everyone can see notifications of submissions in recent activity reports.';
-$string['confirmdeletefile'] = 'Are you absolutely sure you want to delete this file?<br /><strong>{$a}</strong>';
-$string['coursemisconf'] = 'Course is misconfigured';
-$string['currentgrade'] = 'Current grade in gradebook';
-$string['deleteallsubmissions'] = 'Delete all submissions';
-$string['deletefilefailed'] = 'Deleting of file failed.';
-$string['description'] = 'Description';
-$string['downloadall'] = 'Download all assignments as a zip';
-$string['draft'] = 'Draft';
-$string['due'] = 'Assignment due';
-$string['duedate'] = 'Due date';
-$string['duedateno'] = 'No due date';
-$string['early'] = '{$a} early';
-$string['editmysubmission'] = 'Edit my submission';
-$string['editthesefiles'] = 'Edit these files';
-$string['editthisfile'] = 'Update this file';
-$string['addsubmission'] = 'Add submission';
-$string['emailstudents'] = 'Email alerts to students';
-$string['emailteachermail'] = '{$a->username} has updated their assignment submission
-for \'{$a->assignment}\' at {$a->timeupdated}
-
-It is available here:
-
-    {$a->url}';
-$string['emailteachermailhtml'] = '<p>{$a->username} has updated their assignment submission for <i>\'{$a->assignment}\' at {$a->timeupdated}</i>.</p>
-<p>It is <a href="{$a->url}">available on the site</a>.</p>';
-$string['emailteachers'] = 'Email alerts to teachers';
-$string['emailteachers_help'] = 'If enabled, teachers receive email notification whenever students add or update an assignment submission.
-
-Only teachers who are able to grade the particular assignment are notified. So, for example, if the course uses separate groups, teachers restricted to particular groups won\'t receive notification about students in other groups.';
-$string['emptysubmission'] = 'You have not submitted anything yet';
-$string['enablenotification'] = 'Send notifications';
-$string['enablenotification_help'] = 'If enabled, students will be notified when their assignment submissions are graded.';
-$string['errornosubmissions'] = 'There are no submissions to download';
-$string['existingfiledeleted'] = 'Existing file has been deleted: {$a}';
-$string['failedupdatefeedback'] = 'Failed to update submission feedback for user {$a}';
-$string['feedback'] = 'Feedback';
-$string['feedbackfromteacher'] = 'Feedback from {$a}';
-$string['feedbackupdated'] = 'Submissions feedback updated for {$a} people';
-$string['finalize'] = 'Prevent submission updates';
-$string['finalizeerror'] = 'An error occurred and that submission could not be finalised';
-$string['futureaassignment'] = 'This assignment is not yet available.';
-$string['graded'] = 'Graded';
-$string['guestnosubmit'] = 'Sorry, guests are not allowed to submit an assignment. You have to log in/ register before you can submit your answer.';
-$string['guestnoupload'] = 'Sorry, guests are not allowed to upload';
-$string['helpoffline'] = '<p>This is useful when the assignment is performed outside of Moodle.  It could be
-   something elsewhere on the web or face-to-face.</p><p>Students can see a description of the assignment,
-   but can\'t upload files or anything.  Grading works normally, and students will get notifications of
-   their grades.</p>';
-$string['helponline'] = '<p>This assignment type asks users to edit a text, using the normal
-   editing tools.  Teachers can grade them online, and even add inline comments or changes.</p>
-   <p>(If you are familiar with older versions of Moodle, this Assignment
-   type does the same thing as the old Journal module used to do.)</p>';
-$string['helpupload'] = '<p>This type of assignment allows each participant to upload one or more files in any format.
-   These might be a Word processor documents, images, a zipped web site, or anything you ask them to submit.</p>
-   <p>This type also allows you to upload multiple response files. Response files can be also uploaded before submission which
-   can be used to give each participant different file to work with.</p>
-   <p>Participants may also enter notes describing the submitted files, progress status or any other text information.</p>
-   <p>Submission of this type of assignment must be manually finalised by the participant. You can review the current status
-   at any time, unfinished assignments are marked as Draft. You can revert any ungraded assignment back to draft status.</p>';
-$string['helpuploadsingle'] = '<p>This type of assignment allows each participant to upload a
-   single file, of any type.</p> <p>This might be a Word processor document, an image,
-   a zipped web site, or anything you ask them to submit.</p>';
-$string['hideintro'] = 'Hide description before available date';
-$string['hideintro_help'] = 'If enabled, the assignment description is hidden before the "Available from" date. Only the assignment name is displayed.';
-$string['invalidassignment'] = 'Invalid assignment';
-$string['invalidfileandsubmissionid'] = 'Missing file or submission ID';
-$string['invalidid'] = 'Invalid assignment ID';
-$string['invalidsubmissionid'] = 'Invalid submission ID';
-$string['invalidtype'] = 'Invalid assignment type';
-$string['invaliduserid'] = 'Invalid user ID';
-$string['itemstocount'] = 'Count';
-$string['lastgrade'] = 'Last grade';
-$string['late'] = '{$a} late';
-$string['maximumgrade'] = 'Maximum grade';
-$string['maximumsize'] = 'Maximum size';
-$string['maxpublishstate'] = 'Maximum visibility for blog entry before due date';
+$string['assignmentneedsupgrade'] = 'The legacy "Assignment 2.2" activity has been disabled. Please request that your site administrator runs the assignment upgrade tool for all legacy assignments in this site.';
 $string['messageprovider:assignment_updates'] = 'Assignment (2.2) notifications';
-$string['modulename'] = 'Assignment (2.2)';
-$string['modulename_help'] = 'Assignments enable the teacher to specify a task either on or offline which can then be graded.';
-$string['modulenameplural'] = 'Assignments (2.2)';
-$string['newsubmissions'] = 'Assignments submitted';
-$string['noassignments'] = 'There are no assignments yet';
-$string['noattempts'] = 'No attempts have been made on this assignment';
-$string['noblogs'] = 'You have no blog entries to submit!';
-$string['nofiles'] = 'No files were submitted';
-$string['nofilesyet'] = 'No files submitted yet';
-$string['nomoresubmissions'] = 'No further submissions are allowed.';
-$string['notavailableyet'] = 'Sorry, this assignment is not yet available.<br />Assignment instructions will be displayed here on the date given below.';
-$string['notes'] = 'Notes';
-$string['notesempty'] = 'No entry';
-$string['notesupdateerror'] = 'Error when updating notes';
-$string['notgradedyet'] = 'Not graded yet';
-$string['norequiregrading'] = 'There are no assignments that require grading';
-$string['nosubmisson'] = 'No assignments have been submit';
-$string['notsubmittedyet'] = 'Not submitted yet';
-$string['onceassignmentsent'] = 'Once the assignment is sent for marking, you will no longer be able to delete or attach file(s). Do you want to continue?';
-$string['operation'] = 'Operation';
-$string['optionalsettings'] = 'Optional settings';
-$string['overwritewarning'] = 'Warning: uploading again will REPLACE your current submission';
+$string['assignmentdisabled'] = 'The legacy "Assignment 2.2" activity is disabled.';
+$string['modulename'] = 'Assignment 2.2 (Disabled)';
+$string['modulename_help'] = 'Legacy activity module that has been removed from Moodle.';
+$string['modulenameplural'] = 'Assignments 2.2 (Disabled)';
 $string['page-mod-assignment-x'] = 'Any assignment module page';
 $string['page-mod-assignment-view'] = 'Assignment module main page';
 $string['page-mod-assignment-submissions'] = 'Assignment module submission page';
-$string['pagesize'] = 'Submissions shown per page';
-$string['popupinnewwindow'] = 'Open in a popup window';
-$string['pluginadministration'] = 'Assignment administration';
-$string['pluginname'] = 'Assignment (2.2)';
-$string['preventlate'] = 'Prevent late submissions';
-$string['quickgrade'] = 'Allow quick grading';
-$string['quickgrade_help'] = 'If enabled, multiple assignments can be graded on one page. Add grades and comments then click the "Save all my feedback" button to save all changes for that page.';
-$string['requiregrading'] = 'Require grading';
-$string['responsefiles'] = 'Response files';
-$string['reviewed'] = 'Reviewed';
-$string['saveallfeedback'] = 'Save all my feedback';
-$string['selectblog'] = 'Select which blog entry you wish to submit';
-$string['sendformarking'] = 'Send for marking';
-$string['showrecentsubmissions'] = 'Show recent submissions';
-$string['submission'] = 'Submission';
-$string['submissiondraft'] = 'Submission draft';
-$string['submissionfeedback'] = 'Submission feedback';
-$string['submissions'] = 'Submissions';
-$string['submissionsaved'] = 'Your changes have been saved';
-$string['submissionsnotgraded'] = '{$a} submissions not graded';
-$string['submitassignment'] = 'Submit your assignment using this form';
-$string['submitedformarking'] = 'Assignment was already submitted for marking and can not be updated';
-$string['submitformarking'] = 'Final submission for assignment marking';
-$string['submitted'] = 'Submitted';
-$string['submittedfiles'] = 'Submitted files';
-$string['subplugintype_assignment'] = 'Assignment type';
-$string['subplugintype_assignment_plural'] = 'Assignment types';
-$string['trackdrafts'] = 'Enable "Send for marking" button';
-$string['trackdrafts_help'] = 'The "Send for marking" button allows students to indicate to the teacher that they have finished working on an assignment. The teacher may choose to revert the assignment to draft status (if it requires further work, for example).';
-$string['typeblog'] = 'Blog post';
-$string['typeoffline'] = 'Offline activity';
-$string['typeonline'] = 'Online text';
-$string['typeupload'] = 'Advanced uploading of files';
-$string['typeuploadsingle'] = 'Upload a single file';
-$string['unfinalize'] = 'Revert to draft';
-$string['unfinalize_help'] = 'Reverting to draft enables the student to make further updates to their assignment';
-$string['unfinalizeerror'] = 'An error occurred and that submission could not be reverted to draft';
+$string['pluginname'] = 'Assignment 2.2 (Disabled)';
 $string['upgradenotification'] = 'This activity is based on an older assignment module.';
-$string['uploadafile'] = 'Upload a file';
-$string['uploadfiles'] = 'Upload files';
-$string['uploadbadname'] = 'This filename contained strange characters and couldn\'t be uploaded';
-$string['uploadedfiles'] = 'uploaded files';
-$string['uploaderror'] = 'An error happened while saving the file on the server';
-$string['uploadfailnoupdate'] = 'File was uploaded OK but could not update your submission!';
-$string['uploadfiletoobig'] = 'Sorry, but that file is too big (limit is {$a} bytes)';
-$string['uploadnofilefound'] = 'No file was found - are you sure you selected one to upload?';
-$string['uploadnotregistered'] = '\'{$a}\' was uploaded OK but submission did not register!';
-$string['uploadsuccess'] = 'Uploaded \'{$a}\' successfully';
-$string['usermisconf'] = 'User is misconfigured';
-$string['usernosubmit'] = 'Sorry, you are not allowed to submit an assignment.';
 $string['viewassignmentupgradetool'] = 'View the assignment upgrade tool';
-$string['viewfeedback'] = 'View assignment grades and feedback';
-$string['viewmysubmission'] = 'View my submission';
-$string['viewsubmissions'] = 'View {$a} submitted assignments';
-$string['yoursubmission'] = 'Your submission';
-$string['unsupportedsubplugin'] = 'The assignment type of \'{$a}\' is not currently supported. You may wait until the assignment type is made available, or delete the assignment.';
+$string['pendingupgrades_message_small'] = 'This plugin has been disabled. All remaining assignments must be upgraded to the new assignment module using the assignment upgrade tool.';
+$string['pendingupgrades_message_subject'] = 'Important information regarding Assignment 2.2';
+$string['pendingupgrades_message_content'] = 'As part of the upgrade to Moodle 2.7, the legacy Assignment 2.2 activity has been disabled. Backups from the legacy Assignment 2.2 activity will seamlessly restore to the newer Assignment activity. All remaining instances of the legacy Assignment 2.2 activity must be upgraded using the assignment upgrade tool {$a->docsurl}. There are {$a->count} instances of the legacy Assignment 2.2 activity on this site that require upgrading. Users will not be able to access the content of these activities until they have been upgraded.';
+$string['pluginadministration'] = 'Assignment 2.2 (Disabled) administration';
index 5bf9d03..bd90f8b 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-/** Include eventslib.php */
-require_once($CFG->libdir.'/eventslib.php');
-/** Include formslib.php */
-require_once($CFG->libdir.'/formslib.php');
-/** Include calendar/lib.php */
-require_once($CFG->dirroot.'/calendar/lib.php');
-
-/** ASSIGNMENT_COUNT_WORDS = 1 */
-define('ASSIGNMENT_COUNT_WORDS', 1);
-/** ASSIGNMENT_COUNT_LETTERS = 2 */
-define('ASSIGNMENT_COUNT_LETTERS', 2);
-
-/**
- * Standard base class for all assignment submodules (assignment types).
- *
- * @package   mod-assignment
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class assignment_base {
-
-    const FILTER_ALL             = 0;
-    const FILTER_SUBMITTED       = 1;
-    const FILTER_REQUIRE_GRADING = 2;
-
-    /** @var object */
-    var $cm;
-    /** @var object */
-    var $course;
-    /** @var stdClass */
-    var $coursecontext;
-    /** @var object */
-    var $assignment;
-    /** @var string */
-    var $strassignment;
-    /** @var string */
-    var $strassignments;
-    /** @var string */
-    var $strsubmissions;
-    /** @var string */
-    var $strlastmodified;
-    /** @var string */
-    var $pagetitle;
-    /**
-     * @todo document this var
-     */
-    var $defaultformat;
-    /**
-     * @todo document this var
-     */
-    var $context;
-    /** @var string */
-    var $type;
-
-    /**
-     * Constructor for the base assignment class
-     *
-     * Constructor for the base assignment class.
-     * If cmid is set create the cm, course, assignment objects.
-     * If the assignment is hidden and the user is not a teacher then
-     * this prints a page header and notice.
-     *
-     * @global object
-     * @global object
-     * @param int $cmid the current course module id - not set for new assignments
-     * @param object $assignment usually null, but if we have it we pass it to save db access
-     * @param object $cm usually null, but if we have it we pass it to save db access
-     * @param object $course usually null, but if we have it we pass it to save db access
-     */
-    function assignment_base($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
-        global $COURSE, $DB;
-
-        if ($cmid == 'staticonly') {
-            //use static functions only!
-            return;
-        }
-
-        global $CFG;
-
-        if ($cm) {
-            $this->cm = $cm;
-        } else if (! $this->cm = get_coursemodule_from_id('assignment', $cmid)) {
-            print_error('invalidcoursemodule');
-        }
-
-        $this->context = context_module::instance($this->cm->id);
-
-        if ($course) {
-            $this->course = $course;
-        } else if ($this->cm->course == $COURSE->id) {
-            $this->course = $COURSE;
-        } else if (! $this->course = $DB->get_record('course', array('id'=>$this->cm->course))) {
-            print_error('invalidid', 'assignment');
-        }
-        $this->coursecontext = context_course::instance($this->course->id);
-        $courseshortname = format_text($this->course->shortname, true, array('context' => $this->coursecontext));
-
-        if ($assignment) {
-            $this->assignment = $assignment;
-        } else if (! $this->assignment = $DB->get_record('assignment', array('id'=>$this->cm->instance))) {
-            print_error('invalidid', 'assignment');
-        }
-
-        $this->assignment->cmidnumber = $this->cm->idnumber; // compatibility with modedit assignment obj
-        $this->assignment->courseid   = $this->course->id; // compatibility with modedit assignment obj
-
-        $this->strassignment = get_string('modulename', 'assignment');
-        $this->strassignments = get_string('modulenameplural', 'assignment');
-        $this->strsubmissions = get_string('submissions', 'assignment');
-        $this->strlastmodified = get_string('lastmodified');
-        $this->pagetitle = strip_tags($courseshortname.': '.$this->strassignment.': '.format_string($this->assignment->name, true, array('context' => $this->context)));
-
-        // visibility handled by require_login() with $cm parameter
-        // get current group only when really needed
-
-    /// Set up things for a HTML editor if it's needed
-        $this->defaultformat = editors_get_preferred_format();
-    }
-
-    /**
-     * Display the assignment, used by view.php
-     *
-     * This in turn calls the methods producing individual parts of the page
-     */
-    function view() {
-
-        $context = context_module::instance($this->cm->id);
-        require_capability('mod/assignment:view', $context);
-
-        add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}",
-                   $this->assignment->id, $this->cm->id);
-
-        $this->view_header();
-
-        $this->view_intro();
-
-        $this->view_dates();
-
-        $this->view_feedback();
-
-        $this->view_footer();
-    }
-
-    /**
-     * Display the header and top of a page
-     *
-     * (this doesn't change much for assignment types)
-     * This is used by the view() method to print the header of view.php but
-     * it can be used on other pages in which case the string to denote the
-     * page in the navigation trail should be passed as an argument
-     *
-     * @global object
-     * @param string $subpage Description of subpage to be used in navigation trail
-     */
-    function view_header($subpage='') {
-        global $CFG, $PAGE, $OUTPUT;
-
-        if ($subpage) {
-            $PAGE->navbar->add($subpage);
-        }
-
-        $PAGE->set_title($this->pagetitle);
-        $PAGE->set_heading($this->course->fullname);
-
-        echo $OUTPUT->header();
-
-        groups_print_activity_menu($this->cm, $CFG->wwwroot . '/mod/assignment/view.php?id=' . $this->cm->id);
-
-        echo '<div class="reportlink">'.$this->submittedlink().'</div>';
-        echo '<div class="clearer"></div>';
-        if (has_capability('moodle/site:config', context_system::instance())) {
-            echo $OUTPUT->notification(get_string('upgradenotification', 'assignment'));
-            $adminurl = new moodle_url('/admin/tool/assignmentupgrade/listnotupgraded.php');
-            echo $OUTPUT->single_button($adminurl, get_string('viewassignmentupgradetool', 'assignment'));
-        }
-    }
-
-
-    /**
-     * Display the assignment intro
-     *
-     * This will most likely be extended by assignment type plug-ins
-     * The default implementation prints the assignment description in a box
-     */
-    function view_intro() {
-        global $OUTPUT;
-        echo $OUTPUT->box_start('generalbox boxaligncenter', 'intro');
-        echo format_module_intro('assignment', $this->assignment, $this->cm->id);
-        echo $OUTPUT->box_end();
-        echo plagiarism_print_disclosure($this->cm->id);
-    }
-
-    /**
-     * Display the assignment dates
-     *
-     * Prints the assignment start and end dates in a box.
-     * This will be suitable for most assignment types
-     */
-    function view_dates() {
-        global $OUTPUT;
-        if (!$this->assignment->timeavailable && !$this->assignment->timedue) {
-            return;
-        }
-
-        echo $OUTPUT->box_start('generalbox boxaligncenter', 'dates');
-        echo '<table>';
-        if ($this->assignment->timeavailable) {
-            echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>';
-            echo '    <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
-        }
-        if ($this->assignment->timedue) {
-            echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>';
-            echo '    <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
-        }
-        echo '</table>';
-        echo $OUTPUT->box_end();
-    }
-
-
-    /**
-     * Display the bottom and footer of a page
-     *
-     * This default method just prints the footer.
-     * This will be suitable for most assignment types
-     */
-    function view_footer() {
-        global $OUTPUT;
-        echo $OUTPUT->footer();
-    }
-
-    /**
-     * Display the feedback to the student
-     *
-     * This default method prints the teacher picture and name, date when marked,
-     * grade and teacher submissioncomment.
-     * If advanced grading is used the method render_grade from the
-     * advanced grading controller is called to display the grade.
-     *
-     * @global object
-     * @global object
-     * @global object
-     * @param object $submission The submission object or NULL in which case it will be loaded
-     * @return bool
-     */
-    function view_feedback($submission=NULL) {
-        global $USER, $CFG, $DB, $OUTPUT, $PAGE;
-        require_once($CFG->libdir.'/gradelib.php');
-        require_once("$CFG->dirroot/grade/grading/lib.php");
-
-        if (!$submission) { /// Get submission for this assignment
-            $userid = $USER->id;
-            $submission = $this->get_submission($userid);
-        } else {
-            $userid = $submission->userid;
-        }
-        // Check the user can submit
-        $canviewfeedback = ($userid == $USER->id && has_capability('mod/assignment:submit', $this->context, $USER->id, false));
-        // If not then check if the user still has the view cap and has a previous submission
-        $canviewfeedback = $canviewfeedback || (!empty($submission) && $submission->userid == $USER->id && has_capability('mod/assignment:view', $this->context));
-        // Or if user can grade (is a teacher or admin)
-        $canviewfeedback = $canviewfeedback || has_capability('mod/assignment:grade', $this->context);
-
-        if (!$canviewfeedback) {
-            // can not view or submit assignments -> no feedback
-            return false;
-        }
-
-        $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $userid);
-        $item = $grading_info->items[0];
-        $grade = $item->grades[$userid];
-
-        if ($grade->hidden or $grade->grade === false) { // hidden or error
-            return false;
-        }
-
-        if ($grade->grade === null and empty($grade->str_feedback)) { // No grade to show yet
-            // If sumbission then check if feedback is avaiable to show else return.
-            if (!$submission) {
-                return false;
-            }
-
-            $fs = get_file_storage();
-            $noresponsefiles = $fs->is_area_empty($this->context->id, 'mod_assignment', 'response', $submission->id);
-            if (empty($submission->submissioncomment) && $noresponsefiles) { // Nothing to show yet
-                return false;
-            }
-
-            // We need the teacher info
-            if (!$teacher = $DB->get_record('user', array('id'=>$submission->teacher))) {
-                print_error('cannotfindteacher');
-            }
-
-            $feedbackdate = $submission->timemarked;
-            $feedback = format_text($submission->submissioncomment, $submission->format);
-            $strlonggrade = '-';
-        }
-        else {
-            // We need the teacher info
-            if (!$teacher = $DB->get_record('user', array('id'=>$grade->usermodified))) {
-                print_error('cannotfindteacher');
-            }
-
-            $feedbackdate = $grade->dategraded;
-            $feedback = $grade->str_feedback;
-            $strlonggrade = $grade->str_long_grade;
-        }
-
-        // Print the feedback
-        echo $OUTPUT->heading(get_string('submissionfeedback', 'assignment'), 3);
-
-        echo '<table cellspacing="0" class="feedback">';
-
-        echo '<tr>';
-        echo '<td class="left picture">';
-        if ($teacher) {
-            echo $OUTPUT->user_picture($teacher);
-        }
-        echo '</td>';
-        echo '<td class="topic">';
-        echo '<div class="from">';
-        if ($teacher) {
-            echo '<div class="fullname">'.fullname($teacher).'</div>';
-        }
-        echo '<div class="time">'.userdate($feedbackdate).'</div>';
-        echo '</div>';
-        echo '</td>';
-        echo '</tr>';
-
-        echo '<tr>';
-        echo '<td class="left side">&nbsp;</td>';
-        echo '<td class="content">';
-
-        if ($this->assignment->grade) {
-            $gradestr = '<div class="grade">'. get_string("grade").': '.$strlonggrade. '</div>';
-            if (!empty($submission) && $controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
-                $controller->set_grade_range(make_grades_menu($this->assignment->grade));
-                echo $controller->render_grade($PAGE, $submission->id, $item, $gradestr, has_capability('mod/assignment:grade', $this->context));
-            } else {
-                echo $gradestr;
-            }
-            echo '<div class="clearer"></div>';
-        }
-
-        echo '<div class="comment">';
-        echo $feedback;
-        echo '</div>';
-        echo '</tr>';
-        if (method_exists($this, 'view_responsefile')) {
-            $this->view_responsefile($submission);
-        }
-        echo '</table>';
-
-        return true;
-    }
-
-    /**
-     * Returns a link with info about the state of the assignment submissions
-     *
-     * This is used by view_header to put this link at the top right of the page.
-     * For teachers it gives the number of submitted assignments with a link
-     * For students it gives the time of their submission.
-     * This will be suitable for most assignment types.
-     *
-     * @global object
-     * @global object
-     * @param bool $allgroup print all groups info if user can access all groups, suitable for index.php
-     * @return string
-     */
-    function submittedlink($allgroups=false) {
-        global $USER;
-        global $CFG;
-
-        $submitted = '';
-        $urlbase = "{$CFG->wwwroot}/mod/assignment/";
-
-        $context = context_module::instance($this->cm->id);
-        if (has_capability('mod/assignment:grade', $context)) {
-            if ($allgroups and has_capability('moodle/site:accessallgroups', $context)) {
-                $group = 0;
-            } else {
-                $group = groups_get_activity_group($this->cm);
-            }
-            if ($this->type == 'offline') {
-                $submitted = '<a href="'.$urlbase.'submissions.php?id='.$this->cm->id.'">'.
-                             get_string('viewfeedback', 'assignment').'</a>';
-            } else if ($count = $this->count_real_submissions($group)) {
-                $submitted = '<a href="'.$urlbase.'submissions.php?id='.$this->cm->id.'">'.
-                             get_string('viewsubmissions', 'assignment', $count).'</a>';
-            } else {
-                $submitted = '<a href="'.$urlbase.'submissions.php?id='.$this->cm->id.'">'.
-                             get_string('noattempts', 'assignment').'</a>';
-            }
-        } else {
-            if (isloggedin()) {
-                if ($submission = $this->get_submission($USER->id)) {
-                    // If the submission has been completed
-                    if ($this->is_submitted_with_required_data($submission)) {
-                        if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
-                            $submitted = '<span class="early">'.userdate($submission->timemodified).'</span>';
-                        } else {
-                            $submitted = '<span class="late">'.userdate($submission->timemodified).'</span>';
-                        }
-                    }
-                }
-            }
-        }
-
-        return $submitted;
-    }
-
-    /**
-     * Returns whether the assigment supports lateness information
-     *
-     * @return bool This assignment type supports lateness (true, default) or no (false)
-     */
-    function supports_lateness() {
-        return true;
-    }
-
-    /**
-     * @todo Document this function
-     */
-    function setup_elements(&$mform) {
-
-    }
-
-    /**
-     * Any preprocessing needed for the settings form for
-     * this assignment type
-     *
-     * @param array $default_values - array to fill in with the default values
-     *      in the form 'formelement' => 'value'
-     * @param object $form - the form that is to be displayed
-     * @return none
-     */
-    function form_data_preprocessing(&$default_values, $form) {
-    }
-
-    /**
-     * Any extra validation checks needed for the settings
-     * form for this assignment type
-     *
-     * See lib/formslib.php, 'validation' function for details
-     */
-    function form_validation($data, $files) {
-        return array();
-    }
-
-    /**
-     * Create a new assignment activity
-     *
-     * Given an object containing all the necessary data,
-     * (defined by the form in mod_form.php) this function
-     * will create a new instance and return the id number
-     * of the new instance.
-     * The due data is added to the calendar
-     * This is common to all assignment types.
-     *
-     * @global object
-     * @global object
-     * @param object $assignment The data from the form on mod_form.php
-     * @return int The id of the assignment
-     */
-    function add_instance($assignment) {
-        global $COURSE, $DB;
-
-        $assignment->timemodified = time();
-        $assignment->courseid = $assignment->course;
-
-        $returnid = $DB->insert_record("assignment", $assignment);
-        $assignment->id = $returnid;
-
-        if ($assignment->timedue) {
-            $event = new stdClass();
-            $event->name        = $assignment->name;
-            $event->description = format_module_intro('assignment', $assignment, $assignment->coursemodule);
-            $event->courseid    = $assignment->course;
-            $event->groupid     = 0;
-            $event->userid      = 0;
-            $event->modulename  = 'assignment';
-            $event->instance    = $returnid;
-            $event->eventtype   = 'due';
-            $event->timestart   = $assignment->timedue;
-            $event->timeduration = 0;
-
-            calendar_event::create($event);
-        }
-
-        assignment_grade_item_update($assignment);
-
-        return $returnid;
-    }
-
-    /**
-     * Deletes an assignment activity
-     *
-     * Deletes all database records, files and calendar events for this assignment.
-     *
-     * @global object
-     * @global object
-     * @param object $assignment The assignment to be deleted
-     * @return boolean False indicates error
-     */
-    function delete_instance($assignment) {
-        global $CFG, $DB;
-
-        $assignment->courseid = $assignment->course;
-
-        $result = true;
-
-        // now get rid of all files
-        $fs = get_file_storage();
-        if ($cm = get_coursemodule_from_instance('assignment', $assignment->id)) {
-            $context = context_module::instance($cm->id);
-            $fs->delete_area_files($context->id);
-        }
-
-        if (! $DB->delete_records('assignment_submissions', array('assignment'=>$assignment->id))) {
-            $result = false;
-        }
-
-        if (! $DB->delete_records('event', array('modulename'=>'assignment', 'instance'=>$assignment->id))) {
-            $result = false;
-        }
-
-        if (! $DB->delete_records('assignment', array('id'=>$assignment->id))) {
-            $result = false;
-        }
-        $mod = $DB->get_field('modules','id',array('name'=>'assignment'));
-
-        assignment_grade_item_delete($assignment);
-
-        return $result;
-    }
-
-    /**
-     * Updates a new assignment activity
-     *
-     * Given an object containing all the necessary data,
-     * (defined by the form in mod_form.php) this function
-     * will update the assignment instance and return the id number
-     * The due date is updated in the calendar
-     * This is common to all assignment types.
-     *
-     * @global object
-     * @global object
-     * @param object $assignment The data from the form on mod_form.php
-     * @return bool success
-     */
-    function update_instance($assignment) {
-        global $COURSE, $DB;
-
-        $assignment->timemodified = time();
-
-        $assignment->id = $assignment->instance;
-        $assignment->courseid = $assignment->course;
-
-        $DB->update_record('assignment', $assignment);
-
-        if ($assignment->timedue) {
-            $event = new stdClass();
-
-            if ($event->id = $DB->get_field('event', 'id', array('modulename'=>'assignment', 'instance'=>$assignment->id))) {
-
-                $event->name        = $assignment->name;
-                $event->description = format_module_intro('assignment', $assignment, $assignment->coursemodule);
-                $event->timestart   = $assignment->timedue;
-
-                $calendarevent = calendar_event::load($event->id);
-                $calendarevent->update($event);
-            } else {
-                $event = new stdClass();
-                $event->name        = $assignment->name;
-                $event->description = format_module_intro('assignment', $assignment, $assignment->coursemodule);
-                $event->courseid    = $assignment->course;
-                $event->groupid     = 0;
-                $event->userid      = 0;
-                $event->modulename  = 'assignment';
-                $event->instance    = $assignment->id;
-                $event->eventtype   = 'due';
-                $event->timestart   = $assignment->timedue;
-                $event->timeduration = 0;
-
-                calendar_event::create($event);
-            }
-        } else {
-            $DB->delete_records('event', array('modulename'=>'assignment', 'instance'=>$assignment->id));
-        }
-
-        // get existing grade item
-        assignment_grade_item_update($assignment);
-
-        return true;
-    }
-
-    /**
-     * Update grade item for this submission.
-     *
-     * @param stdClass $submission The submission instance
-     */
-    function update_grade($submission) {
-        assignment_update_grades($this->assignment, $submission->userid);
-    }
-
-    /**
-     * Top-level function for handling of submissions called by submissions.php
-     *
-     * This is for handling the teacher interaction with the grading interface
-     * This should be suitable for most assignment types.
-     *
-     * @global object
-     * @param string $mode Specifies the kind of teacher interaction taking place
-     */
-    function submissions($mode) {
-        ///The main switch is changed to facilitate
-        ///1) Batch fast grading
-        ///2) Skip to the next one on the popup
-        ///3) Save and Skip to the next one on the popup
-
-        //make user global so we can use the id
-        global $USER, $OUTPUT, $DB, $PAGE;
-
-        $mailinfo = optional_param('mailinfo', null, PARAM_BOOL);
-
-        if (optional_param('next', null, PARAM_BOOL)) {
-            $mode='next';
-        }
-        if (optional_param('saveandnext', null, PARAM_BOOL)) {
-            $mode='saveandnext';
-        }
-
-        if (is_null($mailinfo)) {
-            if (optional_param('sesskey', null, PARAM_BOOL)) {
-                set_user_preference('assignment_mailinfo', 0);
-            } else {
-                $mailinfo = get_user_preferences('assignment_mailinfo', 0);
-            }
-        } else {
-            set_user_preference('assignment_mailinfo', $mailinfo);
-        }
-
-        if (!($this->validate_and_preprocess_feedback())) {
-            // form was submitted ('Save' or 'Save and next' was pressed, but validation failed)
-            $this->display_submission();
-            return;
-        }
-
-        switch ($mode) {
-            case 'grade':                         // We are in a main window grading
-                if ($submission = $this->process_feedback()) {
-                    $this->display_submissions(get_string('changessaved'));
-                } else {
-                    $this->display_submissions();
-                }
-                break;
-
-            case 'single':                        // We are in a main window displaying one submission
-                if ($submission = $this->process_feedback()) {
-                    $this->display_submissions(get_string('changessaved'));
-                } else {
-                    $this->display_submission();
-                }
-                break;
-
-            case 'all':                          // Main window, display everything
-                $this->display_submissions();
-                break;
-
-            case 'fastgrade':
-                ///do the fast grading stuff  - this process should work for all 3 subclasses
-                $grading    = false;
-                $commenting = false;
-                $col        = false;
-                if (isset($_POST['submissioncomment'])) {
-                    $col = 'submissioncomment';
-                    $commenting = true;
-                }
-                if (isset($_POST['menu'])) {
-                    $col = 'menu';
-                    $grading = true;
-                }
-                if (!$col) {
-                    //both submissioncomment and grade columns collapsed..
-                    $this->display_submissions();
-                    break;
-                }
-
-                foreach ($_POST[$col] as $id => $unusedvalue){
-
-                    $id = (int)$id; //clean parameter name
-
-                    $this->process_outcomes($id);
-
-                    if (!$submission = $this->get_submission($id)) {
-                        $submission = $this->prepare_new_submission($id);
-                        $newsubmission = true;
-                    } else {
-                        $newsubmission = false;
-                    }
-                    unset($submission->data1);  // Don't need to update this.
-                    unset($submission->data2);  // Don't need to update this.
-
-                    //for fast grade, we need to check if any changes take place
-                    $updatedb = false;
-
-                    if ($grading) {
-                        $grade = $_POST['menu'][$id];
-                        $updatedb = $updatedb || ($submission->grade != $grade);
-                        $submission->grade = $grade;
-                    } else {
-                        if (!$newsubmission) {
-                            unset($submission->grade);  // Don't need to update this.
-                        }
-                    }
-                    if ($commenting) {
-                        $commentvalue = trim($_POST['submissioncomment'][$id]);
-                        $updatedb = $updatedb || ($submission->submissioncomment != $commentvalue);
-                        $submission->submissioncomment = $commentvalue;
-                    } else {
-                        unset($submission->submissioncomment);  // Don't need to update this.
-                    }
-
-                    $submission->teacher    = $USER->id;
-                    if ($updatedb) {
-                        $submission->mailed = (int)(!$mailinfo);
-                    }
-
-                    $submission->timemarked = time();
-
-                    //if it is not an update, we don't change the last modified time etc.
-                    //this will also not write into database if no submissioncomment and grade is entered.
-
-                    if ($updatedb){
-                        if ($newsubmission) {
-                            if (!isset($submission->submissioncomment)) {
-                                $submission->submissioncomment = '';
-                            }
-                            $sid = $DB->insert_record('assignment_submissions', $submission);
-                            $submission->id = $sid;
-                        } else {
-                            $DB->update_record('assignment_submissions', $submission);
-                        }
-
-                        // trigger grade event
-                        $this->update_grade($submission);
-
-                        //add to log only if updating
-                        add_to_log($this->course->id, 'assignment', 'update grades',
-                                   'submissions.php?id='.$this->cm->id.'&user='.$submission->userid,
-                                   $submission->userid, $this->cm->id);
-                    }
-
-                }
-
-                $message = $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
-
-                $this->display_submissions($message);
-                break;
-
-
-            case 'saveandnext':
-                ///We are in pop up. save the current one and go to the next one.
-                //first we save the current changes
-                if ($submission = $this->process_feedback()) {
-                    //print_heading(get_string('changessaved'));
-                    //$extra_javascript = $this->update_main_listing($submission);
-                }
-
-            case 'next':
-                /// We are currently in pop up, but we want to skip to next one without saving.
-                ///    This turns out to be similar to a single case
-                /// The URL used is for the next submission.
-                $offset = required_param('offset', PARAM_INT);
-                $nextid = required_param('nextid', PARAM_INT);
-                $id = required_param('id', PARAM_INT);
-                $filter = optional_param('filter', self::FILTER_ALL, PARAM_INT);
-
-                if ($mode == 'next' || $filter !== self::FILTER_REQUIRE_GRADING) {
-                    $offset = (int)$offset+1;
-                }
-                $redirect = new moodle_url('submissions.php',
-                        array('id' => $id, 'offset' => $offset, 'userid' => $nextid,
-                        'mode' => 'single', 'filter' => $filter));
-
-                redirect($redirect);
-                break;
-
-            case 'singlenosave':
-                $this->display_submission();
-                break;
-
-            default:
-                echo "something seriously is wrong!!";
-                break;
-        }
-    }
-
-    /**
-     * Checks if grading method allows quickgrade mode. At the moment it is hardcoded
-     * that advanced grading methods do not allow quickgrade.
-     *
-     * Assignment type plugins are not allowed to override this method
-     *
-     * @return boolean
-     */
-    public final function quickgrade_mode_allowed() {
-        global $CFG;
-        require_once("$CFG->dirroot/grade/grading/lib.php");
-        if ($controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Helper method updating the listing on the main script from popup using javascript
-     *
-     * @global object
-     * @global object
-     * @param $submission object The submission whose data is to be updated on the main page
-     */
-    function update_main_listing($submission) {
-        global $SESSION, $CFG, $OUTPUT;
-
-        $output = '';
-
-        $perpage = get_user_preferences('assignment_perpage', 10);
-
-        $quickgrade = get_user_preferences('assignment_quickgrade', 0) && $this->quickgrade_mode_allowed();
-
-        /// Run some Javascript to try and update the parent page
-        $output .= '<script type="text/javascript">'."\n<!--\n";
-        if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['submissioncomment'])) {
-            if ($quickgrade){
-                $output.= 'opener.document.getElementById("submissioncomment'.$submission->userid.'").value="'
-                .trim($submission->submissioncomment).'";'."\n";
-             } else {
-                $output.= 'opener.document.getElementById("com'.$submission->userid.
-                '").innerHTML="'.shorten_text(trim(strip_tags($submission->submissioncomment)), 15)."\";\n";
-            }
-        }
-
-        if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['grade'])) {
-            //echo optional_param('menuindex');
-            if ($quickgrade){
-                $output.= 'opener.document.getElementById("menumenu'.$submission->userid.
-                '").selectedIndex="'.optional_param('menuindex', 0, PARAM_INT).'";'."\n";
-            } else {
-                $output.= 'opener.document.getElementById("g'.$submission->userid.'").innerHTML="'.
-                $this->display_grade($submission->grade)."\";\n";
-            }
-        }
-        //need to add student's assignments in there too.
-        if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemodified']) &&
-            $submission->timemodified) {
-            $output.= 'opener.document.getElementById("ts'.$submission->userid.
-                 '").innerHTML="'.addslashes_js($this->print_student_answer($submission->userid)).userdate($submission->timemodified)."\";\n";
-        }
-
-        if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemarked']) &&
-            $submission->timemarked) {
-            $output.= 'opener.document.getElementById("tt'.$submission->userid.
-                 '").innerHTML="'.userdate($submission->timemarked)."\";\n";
-        }
-
-        if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['status'])) {
-            $output.= 'opener.document.getElementById("up'.$submission->userid.'").className="s1";';
-            $buttontext = get_string('update');
-            $url = new moodle_url('/mod/assignment/submissions.php', array(
-                    'id' => $this->cm->id,
-                    'userid' => $submission->userid,
-                    'mode' => 'single',
-                    'offset' => (optional_param('offset', '', PARAM_INT)-1)));
-            $button = $OUTPUT->action_link($url, $buttontext, new popup_action('click', $url, 'grade'.$submission->userid, array('height' => 450, 'width' => 700)), array('ttile'=>$buttontext));
-
-            $output .= 'opener.document.getElementById("up'.$submission->userid.'").innerHTML="'.addslashes_js($button).'";';
-        }
-
-        $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $submission->userid);
-
-        if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['finalgrade'])) {
-            $output.= 'opener.document.getElementById("finalgrade_'.$submission->userid.
-            '").innerHTML="'.$grading_info->items[0]->grades[$submission->userid]->str_grade.'";'."\n";
-        }
-
-        if (!empty($CFG->enableoutcomes) and empty($SESSION->flextable['mod-assignment-submissions']->collapse['outcome'])) {
-
-            if (!empty($grading_info->outcomes)) {
-                foreach($grading_info->outcomes as $n=>$outcome) {
-                    if ($outcome->grades[$submission->userid]->locked) {
-                        continue;
-                    }
-
-                    if ($quickgrade){
-                        $output.= 'opener.document.getElementById("outcome_'.$n.'_'.$submission->userid.
-                        '").selectedIndex="'.$outcome->grades[$submission->userid]->grade.'";'."\n";
-
-                    } else {
-                        $options = make_grades_menu(-$outcome->scaleid);
-                        $options[0] = get_string('nooutcome', 'grades');
-                        $output.= 'opener.document.getElementById("outcome_'.$n.'_'.$submission->userid.'").innerHTML="'.$options[$outcome->grades[$submission->userid]->grade]."\";\n";
-                    }
-
-                }
-            }
-        }
-
-        $output .= "\n-->\n</script>";
-        return $output;
-    }
-
-    /**
-     *  Return a grade in user-friendly form, whether it's a scale or not
-     *
-     * @global object
-     * @param mixed $grade
-     * @return string User-friendly representation of grade
-     */
-    function display_grade($grade) {
-        global $DB;
-
-        static $scalegrades = array();   // Cache scales for each assignment - they might have different scales!!
-
-        if ($this->assignment->grade >= 0) {    // Normal number
-            if ($grade == -1) {
-                return '-';
-            } else {
-                return $grade.' / '.$this->assignment->grade;
-            }
-
-        } else {                                // Scale
-            if (empty($scalegrades[$this->assignment->id])) {
-                if ($scale = $DB->get_record('scale', array('id'=>-($this->assignment->grade)))) {
-                    $scalegrades[$this->assignment->id] = make_menu_from_list($scale->scale);
-                } else {
-                    return '-';
-                }
-            }
-            if (isset($scalegrades[$this->assignment->id][$grade])) {
-                return $scalegrades[$this->assignment->id][$grade];
-            }
-            return '-';
-        }
-    }
-
-    /**
-     *  Display a single submission, ready for grading on a popup window
-     *
-     * This default method prints the teacher info and submissioncomment box at the top and
-     * the student info and submission at the bottom.
-     * This method also fetches the necessary data in order to be able to
-     * provide a "Next submission" button.
-     * Calls preprocess_submission() to give assignment type plug-ins a chance
-     * to process submissions before they are graded
-     * This method gets its arguments from the page parameters userid and offset
-     *
-     * @global object
-     * @global object
-     * @param string $extra_javascript
-     */
-    function display_submission($offset=-1,$userid =-1, $display=true) {
-        global $CFG, $DB, $PAGE, $OUTPUT, $USER;
-        require_once($CFG->libdir.'/gradelib.php');
-        require_once($CFG->libdir.'/tablelib.php');
-        require_once("$CFG->dirroot/repository/lib.php");
-        require_once("$CFG->dirroot/grade/grading/lib.php");
-        if ($userid==-1) {
-            $userid = required_param('userid', PARAM_INT);
-        }
-        if ($offset==-1) {
-            $offset = required_param('offset', PARAM_INT);//offset for where to start looking for student.
-        }
-        $filter = optional_param('filter', 0, PARAM_INT);
-
-        if (!$user = $DB->get_record('user', array('id'=>$userid))) {
-            print_error('nousers');
-        }
-
-        if (!$submission = $this->get_submission($user->id)) {
-            $submission = $this->prepare_new_submission($userid);
-        }
-        if ($submission->timemodified > $submission->timemarked) {
-            $subtype = 'assignmentnew';
-        } else {
-            $subtype = 'assignmentold';
-        }
-
-        $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array($user->id));
-        $gradingdisabled = $grading_info->items[0]->grades[$userid]->locked || $grading_info->items[0]->grades[$userid]->overridden;
-
-    /// construct SQL, using current offset to find the data of the next student
-        $course     = $this->course;
-        $assignment = $this->assignment;
-        $cm         = $this->cm;
-        $context    = context_module::instance($cm->id);
-
-        //reset filter to all for offline assignment
-        if ($assignment->assignmenttype == 'offline' && $filter == self::FILTER_SUBMITTED) {
-            $filter = self::FILTER_ALL;
-        }
-        /// Get all ppl that can submit assignments
-
-        $currentgroup = groups_get_activity_group($cm);
-        $users = get_enrolled_users($context, 'mod/assignment:submit', $currentgroup, 'u.id');
-        if ($users) {
-            $users = array_keys($users);
-            // if groupmembersonly used, remove users who are not in any group
-            if (!empty($CFG->enablegroupmembersonly) and $cm->groupmembersonly) {
-                if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
-                    $users = array_intersect($users, array_keys($groupingusers));
-                }
-            }
-        }
-
-        $nextid = 0;
-        $where = '';
-        if($filter == self::FILTER_SUBMITTED) {
-            $where .= 's.timemodified > 0 AND ';
-        } else if($filter == self::FILTER_REQUIRE_GRADING) {
-            $where .= 's.timemarked < s.timemodified AND ';
-        }
-
-        if ($users) {
-            $userfields = user_picture::fields('u', array('lastaccess'));
-            $select = "SELECT $userfields,
-                              s.id AS submissionid, s.grade, s.submissioncomment,
-                              s.timemodified, s.timemarked,
-                              CASE WHEN s.timemarked > 0 AND s.timemarked >= s.timemodified THEN 1
-                                   ELSE 0 END AS status ";
-
-            $sql = 'FROM {user} u '.
-                   'LEFT JOIN {assignment_submissions} s ON u.id = s.userid
-                   AND s.assignment = '.$this->assignment->id.' '.
-                   'WHERE '.$where.'u.id IN ('.implode(',', $users).') ';
-
-            if ($sort = flexible_table::get_sort_for_table('mod-assignment-submissions')) {
-                $sort = 'ORDER BY '.$sort.' ';
-            }
-            $auser = $DB->get_records_sql($select.$sql.$sort, null, $offset, 2);
-
-            if (is_array($auser) && count($auser)>1) {
-                $nextuser = next($auser);
-                $nextid = $nextuser->id;
-            }
-        }
-
-        if ($submission->teacher) {
-            $teacher = $DB->get_record('user', array('id'=>$submission->teacher));
-        } else {
-            global $USER;
-            $teacher = $USER;
-        }
-
-        $this->preprocess_submission($submission);
-
-        $mformdata = new stdClass();
-        $mformdata->context = $this->context;
-        $mformdata->maxbytes = $this->course->maxbytes;
-        $mformdata->courseid = $this->course->id;
-        $mformdata->teacher = $teacher;
-        $mformdata->assignment = $assignment;
-        $mformdata->submission = $submission;
-        $mformdata->lateness = $this->display_lateness($submission->timemodified);
-        $mformdata->auser = $auser;
-        $mformdata->user = $user;
-        $mformdata->offset = $offset;
-        $mformdata->userid = $userid;
-        $mformdata->cm = $this->cm;
-        $mformdata->grading_info = $grading_info;
-        $mformdata->enableoutcomes = $CFG->enableoutcomes;
-        $mformdata->grade = $this->assignment->grade;
-        $mformdata->gradingdisabled = $gradingdisabled;
-        $mformdata->nextid = $nextid;
-        $mformdata->submissioncomment= $submission->submissioncomment;
-        $mformdata->submissioncommentformat= FORMAT_HTML;
-        $mformdata->submission_content= $this->print_user_files($user->id,true);
-        $mformdata->filter = $filter;
-        $mformdata->mailinfo = get_user_preferences('assignment_mailinfo', 0);
-         if ($assignment->assignmenttype == 'upload') {
-            $mformdata->fileui_options = array('subdirs'=>1, 'maxbytes'=>$assignment->maxbytes, 'maxfiles'=>$assignment->var1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL);
-        } elseif ($assignment->assignmenttype == 'uploadsingle') {
-            $mformdata->fileui_options = array('subdirs'=>0, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL);
-        }
-        $advancedgradingwarning = false;
-        $gradingmanager = get_grading_manager($this->context, 'mod_assignment', 'submission');
-        if ($gradingmethod = $gradingmanager->get_active_method()) {
-            $controller = $gradingmanager->get_controller($gradingmethod);
-            if ($controller->is_form_available()) {
-                $itemid = null;
-                if (!empty($submission->id)) {
-                    $itemid = $submission->id;
-                }
-                if ($gradingdisabled && $itemid) {
-                    $mformdata->advancedgradinginstance = $controller->get_current_instance($USER->id, $itemid);
-                } else if (!$gradingdisabled) {
-                    $instanceid = optional_param('advancedgradinginstanceid', 0, PARAM_INT);
-                    $mformdata->advancedgradinginstance = $controller->get_or_create_instance($instanceid, $USER->id, $itemid);
-                }
-            } else {
-                $advancedgradingwarning = $controller->form_unavailable_notification();
-            }
-        }
-
-        $submitform = new assignment_grading_form( null, $mformdata );
-
-         if (!$display) {
-            $ret_data = new stdClass();
-            $ret_data->mform = $submitform;
-            if (isset($mformdata->fileui_options)) {
-                $ret_data->fileui_options = $mformdata->fileui_options;
-            }
-            return $ret_data;
-        }
-
-        if ($submitform->is_cancelled()) {
-            redirect('submissions.php?id='.$this->cm->id);
-        }
-
-        $submitform->set_data($mformdata);
-
-        $PAGE->set_title($this->course->fullname . ': ' .get_string('feedback', 'assignment').' - '.fullname($user, true));
-        $PAGE->set_heading($this->course->fullname);
-        $PAGE->navbar->add(get_string('submissions', 'assignment'), new moodle_url('/mod/assignment/submissions.php', array('id'=>$cm->id)));
-        $PAGE->navbar->add(fullname($user, true));
-
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string('feedback', 'assignment').': '.fullname($user, true));
-
-        // display mform here...
-        if ($advancedgradingwarning) {
-            echo $OUTPUT->notification($advancedgradingwarning, 'error');
-        }
-        $submitform->display();
-
-        $customfeedback = $this->custom_feedbackform($submission, true);
-        if (!empty($customfeedback)) {
-            echo $customfeedback;
-        }
-
-        echo $OUTPUT->footer();
-    }
-
-    /**
-     *  Preprocess submission before grading
-     *
-     * Called by display_submission()
-     * The default type does nothing here.
-     *
-     * @param object $submission The submission object
-     */
-    function preprocess_submission(&$submission) {
-    }
-
-    /**
-     *  Display all the submissions ready for grading
-     *
-     * @global object
-     * @global object
-     * @global object
-     * @global object
-     * @param string $message
-     * @return bool|void
-     */
-    function display_submissions($message='') {
-        global $CFG, $DB, $USER, $DB, $OUTPUT, $PAGE;
-        require_once($CFG->libdir.'/gradelib.php');
-
-        /* first we check to see if the form has just been submitted
-         * to request user_preference updates
-         */
-
-       $filters = array(self::FILTER_ALL             => get_string('all'),
-                        self::FILTER_REQUIRE_GRADING => get_string('requiregrading', 'assignment'));
-
-        $updatepref = optional_param('updatepref', 0, PARAM_BOOL);
-        if ($updatepref) {
-            $perpage = optional_param('perpage', 10, PARAM_INT);
-            $perpage = ($perpage <= 0) ? 10 : $perpage ;
-            $filter = optional_param('filter', 0, PARAM_INT);
-            set_user_preference('assignment_perpage', $perpage);
-            set_user_preference('assignment_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL));
-            set_user_preference('assignment_filter', $filter);
-        }
-
-        /* next we get perpage and quickgrade (allow quick grade) params
-         * from database
-         */
-        $perpage    = get_user_preferences('assignment_perpage', 10);
-        $quickgrade = get_user_preferences('assignment_quickgrade', 0) && $this->quickgrade_mode_allowed();
-        $filter = get_user_preferences('assignment_filter', 0);
-        $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id);
-
-        if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) {
-            $uses_outcomes = true;
-        } else {
-            $uses_outcomes = false;
-        }
-
-        $page    = optional_param('page', 0, PARAM_INT);
-        $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
-
-    /// Some shortcuts to make the code read better
-
-        $course     = $this->course;
-        $assignment = $this->assignment;
-        $cm         = $this->cm;
-        $hassubmission = false;
-
-        // reset filter to all for offline assignment only.
-        if ($assignment->assignmenttype == 'offline') {
-            if ($filter == self::FILTER_SUBMITTED) {
-                $filter = self::FILTER_ALL;
-            }
-        } else {
-            $filters[self::FILTER_SUBMITTED] = get_string('submitted', 'assignment');
-        }
-
-        $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
-        add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->cm->id, $this->assignment->id, $this->cm->id);
-
-        $PAGE->set_title(format_string($this->assignment->name,true));
-        $PAGE->set_heading($this->course->fullname);
-        echo $OUTPUT->header();
-
-        echo '<div class="usersubmissions">';
-
-        //hook to allow plagiarism plugins to update status/print links.
-        echo plagiarism_update_status($this->course, $this->cm);
-
-        $course_context = context_course::instance($course->id);
-        if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {
-            echo '<div class="allcoursegrades"><a href="' . $CFG->wwwroot . '/grade/report/grader/index.php?id=' . $course->id . '">'
-                . get_string('seeallcoursegrades', 'grades') . '</a></div>';
-        }
-
-        if (!empty($message)) {
-            echo $message;   // display messages here if any
-        }
-
-        $context = context_module::instance($cm->id);
-
-    /// Check to see if groups are being used in this assignment
-
-        /// find out current groups mode
-        $groupmode = groups_get_activity_groupmode($cm);
-        $currentgroup = groups_get_activity_group($cm, true);
-        groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/assignment/submissions.php?id=' . $this->cm->id);
-
-        /// Print quickgrade form around the table
-        if ($quickgrade) {
-            $formattrs = array();
-            $formattrs['action'] = new moodle_url('/mod/assignment/submissions.php');
-            $formattrs['id'] = 'fastg';
-            $formattrs['method'] = 'post';
-
-            echo html_writer::start_tag('form', $formattrs);
-            echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id',      'value'=> $this->cm->id));
-            echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode',    'value'=> 'fastgrade'));
-            echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'page',    'value'=> $page));
-            echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey()));
-        }
-
-        /// Get all ppl that are allowed to submit assignments
-        list($esql, $params) = get_enrolled_sql($context, 'mod/assignment:submit', $currentgroup);
-
-        if ($filter == self::FILTER_ALL) {
-            $sql = "SELECT u.id FROM {user} u ".
-                   "LEFT JOIN ($esql) eu ON eu.id=u.id ".
-                   "WHERE u.deleted = 0 AND eu.id=u.id ";
-        } else {
-            $wherefilter = ' AND s.assignment = '. $this->assignment->id;
-            $assignmentsubmission = "LEFT JOIN {assignment_submissions} s ON (u.id = s.userid) ";
-            if($filter == self::FILTER_SUBMITTED) {
-                $wherefilter .= ' AND s.timemodified > 0 ';
-            } else if($filter == self::FILTER_REQUIRE_GRADING && $assignment->assignmenttype != 'offline') {
-                $wherefilter .= ' AND s.timemarked < s.timemodified ';
-            } else { // require grading for offline assignment
-                $assignmentsubmission = "";
-                $wherefilter = "";
-            }
-
-            $sql = "SELECT u.id FROM {user} u ".
-                   "LEFT JOIN ($esql) eu ON eu.id=u.id ".
-                   $assignmentsubmission.
-                   "WHERE u.deleted = 0 AND eu.id=u.id ".
-                   $wherefilter;
-        }
-
-        $users = $DB->get_records_sql($sql, $params);
-        if (!empty($users)) {
-            if($assignment->assignmenttype == 'offline' && $filter == self::FILTER_REQUIRE_GRADING) {
-                //remove users who has submitted their assignment
-                foreach ($this->get_submissions() as $submission) {
-                    if (array_key_exists($submission->userid, $users)) {
-                        unset($users[$submission->userid]);
-                    }
-                }
-            }
-            $users = array_keys($users);
-        }
-
-        // if groupmembersonly used, remove users who are not in any group
-        if ($users and !empty($CFG->enablegroupmembersonly) and $cm->groupmembersonly) {
-            if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
-                $users = array_intersect($users, array_keys($groupingusers));
-            }
-        }
-
-        $extrafields = get_extra_user_fields($context);
-        $tablecolumns = array_merge(array('picture', 'fullname'), $extrafields,
-                array('grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade'));
-        if ($uses_outcomes) {
-            $tablecolumns[] = 'outcome'; // no sorting based on outcomes column
-        }
-
-        $extrafieldnames = array();
-        foreach ($extrafields as $field) {
-            $extrafieldnames[] = get_user_field_name($field);
-        }
-        $tableheaders = array_merge(
-                array('', get_string('fullnameuser')),
-                $extrafieldnames,
-                array(
-                    get_string('grade'),
-                    get_string('comment', 'assignment'),
-                    get_string('lastmodified').' ('.get_string('submission', 'assignment').')',
-                    get_string('lastmodified').' ('.get_string('grade').')',
-                    get_string('status'),
-                    get_string('finalgrade', 'grades'),
-                ));
-        if ($uses_outcomes) {
-            $tableheaders[] = get_string('outcome', 'grades');
-        }
-
-        require_once($CFG->libdir.'/tablelib.php');
-        $table = new flexible_table('mod-assignment-submissions');
-
-        $table->define_columns($tablecolumns);
-        $table->define_headers($tableheaders);
-        $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;currentgroup='.$currentgroup);
-
-        $table->sortable(true, 'lastname');//sorted by lastname by default
-        $table->collapsible(true);
-        $table->initialbars(true);
-
-        $table->column_suppress('picture');
-        $table->column_suppress('fullname');
-
-        $table->column_class('picture', 'picture');
-        $table->column_class('fullname', 'fullname');
-        foreach ($extrafields as $field) {
-            $table->column_class($field, $field);
-        }
-        $table->column_class('grade', 'grade');
-        $table->column_class('submissioncomment', 'comment');
-        $table->column_class('timemodified', 'timemodified');
-        $table->column_class('timemarked', 'timemarked');
-        $table->column_class('status', 'status');
-        $table->column_class('finalgrade', 'finalgrade');
-        if ($uses_outcomes) {
-            $table->column_class('outcome', 'outcome');
-        }
-
-        $table->set_attribute('cellspacing', '0');
-        $table->set_attribute('id', 'attempts');
-        $table->set_attribute('class', 'submissions');
-        $table->set_attribute('width', '100%');
-
-        $table->no_sorting('finalgrade');
-        $table->no_sorting('outcome');
-        $table->text_sorting('submissioncomment');
-
-        // Start working -- this is necessary as soon as the niceties are over
-        $table->setup();
-
-        /// Construct the SQL
-        list($where, $params) = $table->get_sql_where();
-        if ($where) {
-            $where .= ' AND ';
-        }
-
-        if ($filter == self::FILTER_SUBMITTED) {
-           $where .= 's.timemodified > 0 AND ';
-        } else if($filter == self::FILTER_REQUIRE_GRADING) {
-            $where = '';
-            if ($assignment->assignmenttype != 'offline') {
-               $where .= 's.timemarked < s.timemodified AND ';
-            }
-        }
-
-        if ($sort = $table->get_sql_sort()) {
-            $sort = ' ORDER BY '.$sort;
-        }
-
-        $ufields = user_picture::fields('u', $extrafields);
-        if (!empty($users)) {
-            $select = "SELECT $ufields,
-                              s.id AS submissionid, s.grade, s.submissioncomment,
-                              s.timemodified, s.timemarked,
-                              CASE WHEN s.timemarked > 0 AND s.timemarked >= s.timemodified THEN 1
-                                   ELSE 0 END AS status ";
-
-            $sql = 'FROM {user} u '.
-                   'LEFT JOIN {assignment_submissions} s ON u.id = s.userid
-                    AND s.assignment = '.$this->assignment->id.' '.
-                   'WHERE '.$where.'u.id IN ('.implode(',',$users).') ';
-
-            $ausers = $DB->get_records_sql($select.$sql.$sort, $params, $table->get_page_start(), $table->get_page_size());
-
-            $table->pagesize($perpage, count($users));
-
-            ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
-            $offset = $page * $perpage;
-            $strupdate = get_string('update');
-            $strgrade  = get_string('grade');
-            $strview  = get_string('view');
-            $grademenu = make_grades_menu($this->assignment->grade);
-
-            if ($ausers !== false) {
-                $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array_keys($ausers));
-                $endposition = $offset + $perpage;
-                $currentposition = 0;
-                foreach ($ausers as $auser) {
-                    if ($currentposition == $offset && $offset < $endposition) {
-                        $rowclass = null;
-                        $final_grade = $grading_info->items[0]->grades[$auser->id];
-                        $grademax = $grading_info->items[0]->grademax;
-                        $final_grade->formatted_grade = round($final_grade->grade,2) .' / ' . round($grademax,2);
-                        $locked_overridden = 'locked';
-                        if ($final_grade->overridden) {
-                            $locked_overridden = 'overridden';
-                        }
-
-                        // TODO add here code if advanced grading grade must be reviewed => $auser->status=0
-
-                        $picture = $OUTPUT->user_picture($auser);
-
-                        if (empty($auser->submissionid)) {
-                            $auser->grade = -1; //no submission yet
-                        }
-
-                        if (!empty($auser->submissionid)) {
-                            $hassubmission = true;
-                        ///Prints student answer and student modified date
-                        ///attach file or print link to student answer, depending on the type of the assignment.
-                        ///Refer to print_student_answer in inherited classes.
-                            if ($auser->timemodified > 0) {
-                                $studentmodifiedcontent = $this->print_student_answer($auser->id)
-                                        . userdate($auser->timemodified);
-                                if ($assignment->timedue && $auser->timemodified > $assignment->timedue && $this->supports_lateness()) {
-                                    $studentmodifiedcontent .= $this->display_lateness($auser->timemodified);
-                                    $rowclass = 'late';
-                                }
-                            } else {
-                                $studentmodifiedcontent = '&nbsp;';
-                            }
-                            $studentmodified = html_writer::tag('div', $studentmodifiedcontent, array('id' => 'ts' . $auser->id));
-                        ///Print grade, dropdown or text
-                            if ($auser->timemarked > 0) {
-                                $teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
-
-                                if ($final_grade->locked or $final_grade->overridden) {
-                                    $grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
-                                } else if ($quickgrade) {
-                                    $attributes = array();
-                                    $attributes['tabindex'] = $tabindex++;
-                                    $menu = html_writer::label(get_string('assignment:grade', 'assignment'), 'menumenu'. $auser->id, false, array('class' => 'accesshide'));
-                                    $menu .= html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
-                                    $grade = '<div id="g'.$auser->id.'">'. $menu .'</div>';
-                                } else {
-                                    $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
-                                }
-
-                            } else {
-                                $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
-                                if ($final_grade->locked or $final_grade->overridden) {
-                                    $grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
-                                } else if ($quickgrade) {
-                                    $attributes = array();
-                                    $attributes['tabindex'] = $tabindex++;
-                                    $menu = html_writer::label(get_string('assignment:grade', 'assignment'), 'menumenu'. $auser->id, false, array('class' => 'accesshide'));
-                                    $menu .= html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
-                                    $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
-                                } else {
-                                    $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
-                                }
-                            }
-                        ///Print Comment
-                            if ($final_grade->locked or $final_grade->overridden) {
-                                $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($final_grade->str_feedback),15).'</div>';
-
-                            } else if ($quickgrade) {
-                                $comment = '<div id="com'.$auser->id.'">'
-                                         . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
-                                         . $auser->id.'" rows="2" cols="20" spellcheck="true">'.($auser->submissioncomment).'</textarea></div>';
-                            } else {
-                                $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->submissioncomment),15).'</div>';
-                            }
-                        } else {
-                            $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
-                            $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
-                            $status          = '<div id="st'.$auser->id.'">&nbsp;</div>';
-
-                            if ($final_grade->locked or $final_grade->overridden) {
-                                $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';
-                                $hassubmission = true;
-                            } else if ($quickgrade) {   // allow editing
-                                $attributes = array();
-                                $attributes['tabindex'] = $tabindex++;
-                                $menu = html_writer::label(get_string('assignment:grade', 'assignment'), 'menumenu'. $auser->id, false, array('class' => 'accesshide'));
-                                $menu .= html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
-                                $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
-                                $hassubmission = true;
-                            } else {
-                                $grade = '<div id="g'.$auser->id.'">-</div>';
-                            }
-
-                            if ($final_grade->locked or $final_grade->overridden) {
-                                $comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';
-                            } else if ($quickgrade) {
-                                $comment = '<div id="com'.$auser->id.'">'
-                                         . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
-                                         . $auser->id.'" rows="2" cols="20" spellcheck="true">'.($auser->submissioncomment).'</textarea></div>';
-                            } else {
-                                $comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
-                            }
-                        }
-
-                        if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
-                            $auser->status = 0;
-                        } else {
-                            $auser->status = 1;
-                        }
-
-                        $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
-                        if ($final_grade->locked or $final_grade->overridden) {
-                            $buttontext = $strview;
-                        }
-
-                        ///No more buttons, we use popups ;-).
-                        $popup_url = '/mod/assignment/submissions.php?id='.$this->cm->id
-                                   . '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;filter='.$filter.'&amp;offset='.$offset++;
-
-                        $button = $OUTPUT->action_link($popup_url, $buttontext);
-
-                        $status  = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
-
-                        $finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';
-
-                        $outcomes = '';
-
-                        if ($uses_outcomes) {
-
-                            foreach($grading_info->outcomes as $n=>$outcome) {
-                                $outcomes .= '<div class="outcome"><label for="'. 'outcome_'.$n.'_'.$auser->id .'">'.$outcome->name.'</label>';
-                                $options = make_grades_menu(-$outcome->scaleid);
-
-                                if ($outcome->grades[$auser->id]->locked or !$quickgrade) {
-                                    $options[0] = get_string('nooutcome', 'grades');
-                                    $outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';
-                                } else {
-                                    $attributes = array();
-                                    $attributes['tabindex'] = $tabindex++;
-                                    $attributes['id'] = 'outcome_'.$n.'_'.$auser->id;
-                                    $outcomes .= ' '.html_writer::select($options, 'outcome_'.$n.'['.$auser->id.']', $outcome->grades[$auser->id]->grade, array(0=>get_string('nooutcome', 'grades')), $attributes);
-                                }
-                                $outcomes .= '</div>';
-                            }
-                        }
-
-                        $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser, has_capability('moodle/site:viewfullnames', $this->context)) . '</a>';
-                        $extradata = array();
-                        foreach ($extrafields as $field) {
-                            $extradata[] = $auser->{$field};
-                        }
-                        $row = array_merge(array($picture, $userlink), $extradata,
-                                array($grade, $comment, $studentmodified, $teachermodified,
-                                $status, $finalgrade));
-                        if ($uses_outcomes) {
-                            $row[] = $outcomes;
-                        }
-                        $table->add_data($row, $rowclass);
-                    }
-                    $currentposition++;
-                }
-                if ($hassubmission && method_exists($this, 'download_submissions')) {
-                    echo html_writer::start_tag('div', array('class' => 'mod-assignment-download-link'));
-                    echo html_writer::link(new moodle_url('/mod/assignment/submissions.php', array('id' => $this->cm->id, 'download' => 'zip')), get_string('downloadall', 'assignment'));
-                    echo html_writer::end_tag('div');
-                }
-                $table->print_html();  /// Print the whole table
-            } else {
-                if ($filter == self::FILTER_SUBMITTED) {
-                    echo html_writer::tag('div', get_string('nosubmisson', 'assignment'), array('class'=>'nosubmisson'));
-                } else if ($filter == self::FILTER_REQUIRE_GRADING) {
-                    echo html_writer::tag('div', get_string('norequiregrading', 'assignment'), array('class'=>'norequiregrading'));
-                }
-            }
-        }
-
-        /// Print quickgrade form around the table
-        if ($quickgrade && $table->started_output && !empty($users)){
-            $mailinfopref = false;
-            if (get_user_preferences('assignment_mailinfo', 1)) {
-                $mailinfopref = true;
-            }
-            $emailnotification =  html_writer::checkbox('mailinfo', 1, $mailinfopref, get_string('enablenotification','assignment'));
-
-            $emailnotification .= $OUTPUT->help_icon('enablenotification', 'assignment');
-            echo html_writer::tag('div', $emailnotification, array('class'=>'emailnotification'));
-
-            $savefeedback = html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'fastg', 'value'=>get_string('saveallfeedback', 'assignment')));
-            echo html_writer::tag('div', $savefeedback, array('class'=>'fastgbutton'));
-
-            echo html_writer::end_tag('form');
-        } else if ($quickgrade) {
-            echo html_writer::end_tag('form');
-        }
-
-        echo '</div>';
-        /// End of fast grading form
-
-        /// Mini form for setting user preference
-
-        $formaction = new moodle_url('/mod/assignment/submissions.php', array('id'=>$this->cm->id));
-        $mform = new MoodleQuickForm('optionspref', 'post', $formaction, '', array('class'=>'optionspref'));
-
-        $mform->addElement('hidden', 'updatepref');
-        $mform->setDefault('updatepref', 1);
-        $mform->addElement('header', 'qgprefs', get_string('optionalsettings', 'assignment'));
-        $mform->addElement('select', 'filter', get_string('show'),  $filters);
-
-        $mform->setDefault('filter', $filter);
-
-        $mform->addElement('text', 'perpage', get_string('pagesize', 'assignment'), array('size'=>1));
-        $mform->setDefault('perpage', $perpage);
-
-        if ($this->quickgrade_mode_allowed()) {
-            $mform->addElement('checkbox', 'quickgrade', get_string('quickgrade','assignment'));
-            $mform->setDefault('quickgrade', $quickgrade);
-            $mform->addHelpButton('quickgrade', 'quickgrade', 'assignment');
-        }
-
-        $mform->addElement('submit', 'savepreferences', get_string('savepreferences'));
-
-        $mform->display();
-
-        echo $OUTPUT->footer();
-    }
-
-    /**
-     * If the form was cancelled ('Cancel' or 'Next' was pressed), call cancel method
-     * from advanced grading (if applicable) and returns true
-     * If the form was submitted, validates it and returns false if validation did not pass.
-     * If validation passes, preprocess advanced grading (if applicable) and returns true.
-     *
-     * Note to the developers: This is NOT the correct way to implement advanced grading
-     * in grading form. The assignment grading was written long time ago and unfortunately
-     * does not fully use the mforms. Usually function is_validated() is called to
-     * validate the form and get_data() is called to get the data from the form.
-     *
-     * Here we have to push the calculated grade to $_POST['xgrade'] because further processing
-     * of the form gets the data not from form->get_data(), but from $_POST (using statement
-     * like  $feedback = data_submitted() )
-     */
-    protected function validate_and_preprocess_feedback() {
-        global $USER, $CFG;
-        require_once($CFG->libdir.'/gradelib.php');
-        if (!($feedback = data_submitted()) || !isset($feedback->userid) || !isset($feedback->offset)) {
-            return true;      // No incoming data, nothing to validate
-        }
-        $userid = required_param('userid', PARAM_INT);
-        $offset = required_param('offset', PARAM_INT);
-        $gradinginfo = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array($userid));
-        $gradingdisabled = $gradinginfo->items[0]->grades[$userid]->locked || $gradinginfo->items[0]->grades[$userid]->overridden;
-        if ($gradingdisabled) {
-            return true;
-        }
-        $submissiondata = $this->display_submission($offset, $userid, false);
-        $mform = $submissiondata->mform;
-        $gradinginstance = $mform->use_advanced_grading();
-        if (optional_param('cancel', false, PARAM_BOOL) || optional_param('next', false, PARAM_BOOL)) {
-            // form was cancelled
-            if ($gradinginstance) {
-                $gradinginstance->cancel();
-            }
-        } else if ($mform->is_submitted()) {
-            // form was submitted (= a submit button other than 'cancel' or 'next' has been clicked)
-            if (!$mform->is_validated()) {
-                return false;
-            }