Merge branch 'MDL-42796-master' of git://github.com/andrewnicols/moodle
authorSam Hemelryk <sam@moodle.com>
Tue, 10 Dec 2013 22:13:32 +0000 (11:13 +1300)
committerSam Hemelryk <sam@moodle.com>
Tue, 10 Dec 2013 22:13:32 +0000 (11:13 +1300)
143 files changed:
.jshintrc
admin/index.php
admin/renderer.php
admin/tests/behat/upload_users.feature
admin/tool/replace/classes/form.php [new file with mode: 0644]
admin/tool/replace/index.php
admin/tool/replace/lang/en/tool_replace.php
admin/tool/replace/version.php
admin/tool/uploadcourse/tests/behat/create.feature
admin/tool/uploadcourse/tests/behat/update.feature
admin/webservice/forms.php
backup/util/ui/base_moodleform.class.php
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js [new file with mode: 0644]
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js [new file with mode: 0644]
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js [new file with mode: 0644]
backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-debug.js [new file with mode: 0644]
backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js [new file with mode: 0644]
backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel.js [new file with mode: 0644]
backup/util/ui/yui/confirmcancel/confirmcancel.js [deleted file]
backup/util/ui/yui/src/backupselectall/build.json [new file with mode: 0644]
backup/util/ui/yui/src/backupselectall/js/backupselectall.js [moved from backup/util/ui/yui/backupselectall/backupselectall.js with 88% similarity]
backup/util/ui/yui/src/backupselectall/js/backupselectall.json [new file with mode: 0644]
backup/util/ui/yui/src/backupselectall/meta/backupselectall.json [new file with mode: 0644]
backup/util/ui/yui/src/confirmcancel/build.json [new file with mode: 0644]
backup/util/ui/yui/src/confirmcancel/js/confirmcancel.js [new file with mode: 0644]
backup/util/ui/yui/src/confirmcancel/meta/confirmcancel.json [new file with mode: 0644]
badges/tests/behat/add_badge.feature
badges/tests/behat/award_badge.feature
blocks/blog_recent/block_blog_recent.php
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js
blocks/navigation/yui/src/navigation/js/navigation.js
cohort/tests/behat/upload_cohort_users.feature
config-dist.php
course/lib.php
enrol/guest/lang/en/enrol_guest.php
enrol/guest/lib.php
enrol/yui/notification/notification.js [deleted file]
group/tests/behat/groups_import.feature
lang/en/moodle.php
lib/adminlib.php
lib/behat/behat_base.php
lib/behat/behat_files.php
lib/behat/classes/behat_config_manager.php
lib/classes/component.php
lib/classes/event/base.php
lib/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
lib/classes/event/course_module_instances_list_viewed.php
lib/classes/update/checker.php
lib/classes/update/deployer.php
lib/classes/useragent.php
lib/deprecatedlib.php
lib/dml/moodle_database.php
lib/dml/mssql_native_moodle_database.php
lib/dml/mysqli_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/editor/tinymce/plugins/managefiles/manage_form.php
lib/grouplib.php
lib/navigationlib.php
lib/outputrequirementslib.php
lib/testing/generator/block_generator.php
lib/testing/generator/data_generator.php
lib/testing/generator/module_generator.php
lib/tests/behat/behat_deprecated.php
lib/tests/event_course_module_instance_list_viewed.php [new file with mode: 0644]
lib/tests/event_deprecated_test.php [new file with mode: 0644]
lib/tests/event_test.php
lib/tests/fixtures/event_mod_badfixtures.php [moved from lib/phpunit/generatorlib.php with 59% similarity]
lib/tests/fixtures/event_mod_fixtures.php [new file with mode: 0644]
lib/tests/grouplib_test.php
lib/tests/theme_config_test.php
lib/tests/useragent_test.php
lib/upgrade.txt
lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js [new file with mode: 0644]
lib/yui/dragdrop/dragdrop.js [deleted file]
lib/yui/src/blocks/js/blocks.js
lib/yui/src/dragdrop/build.json [new file with mode: 0644]
lib/yui/src/dragdrop/js/dragdrop.js [new file with mode: 0644]
lib/yui/src/dragdrop/meta/dragdrop.json [new file with mode: 0644]
lib/yuilib/3.13.0/io-upload-iframe/io-upload-iframe-coverage.js
lib/yuilib/3.13.0/io-upload-iframe/io-upload-iframe-debug.js
lib/yuilib/3.13.0/io-upload-iframe/io-upload-iframe-min.js
lib/yuilib/3.13.0/io-upload-iframe/io-upload-iframe.js
mdeploy.php
mod/assign/backup/moodle2/restore_assign_activity_task.class.php
mod/assign/module.js
mod/assign/tests/behat/file_submission.feature
mod/book/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/book/classes/event/instances_list_viewed.php [deleted file]
mod/book/index.php
mod/book/lang/en/book.php
mod/book/tests/events_test.php
mod/chat/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/chat/classes/event/instances_list_viewed.php [deleted file]
mod/chat/index.php
mod/chat/lang/en/chat.php
mod/chat/tests/events_test.php
mod/choice/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/choice/classes/event/instances_list_viewed.php [deleted file]
mod/choice/index.php
mod/choice/lang/en/choice.php
mod/choice/tests/events_test.php
mod/data/data.js
mod/feedback/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/feedback/classes/event/instances_list_viewed.php [deleted file]
mod/feedback/index.php
mod/feedback/lang/en/feedback.php
mod/page/classes/event/course_module_instance_list_viewed.php [new file with mode: 0644]
mod/page/classes/event/instances_list_viewed.php [deleted file]
mod/page/index.php
mod/page/lang/en/page.php
mod/scorm/tests/behat/add_scorm.feature
question/editlib.php
repository/filesystem/lib.php
repository/recent/tests/behat/add_recent.feature
repository/recent/tests/behat/behat_repository_recent.php [deleted file]
repository/tests/behat/behat_filepicker.php
repository/tests/behat/cancel_add_file.feature
repository/tests/behat/create_folders.feature
repository/tests/behat/create_shortcut.feature [new file with mode: 0644]
repository/tests/behat/delete_files.feature
repository/tests/behat/overwrite_file.feature [new file with mode: 0644]
repository/tests/behat/zip_and_unzip.feature
repository/upload/tests/behat/behat_repository_upload.php
repository/upload/tests/behat/upload_file.feature
theme/afterburner/style/afterburner_styles.css
theme/bootstrapbase/readme_moodle.txt
theme/bootstrapbase/yui/build/moodle-theme_bootstrapbase-bootstrap/moodle-theme_bootstrapbase-bootstrap-debug.js
theme/bootstrapbase/yui/build/moodle-theme_bootstrapbase-bootstrap/moodle-theme_bootstrapbase-bootstrap-min.js
theme/bootstrapbase/yui/build/moodle-theme_bootstrapbase-bootstrap/moodle-theme_bootstrapbase-bootstrap.js
theme/bootstrapbase/yui/src/bootstrap/js/bootstrapcollapse.js
theme/bootstrapbase/yui/src/bootstrap/js/bootstrapdropdown.js
theme/bootstrapbase/yui/src/bootstrap/js/bootstrapengine.js
theme/canvas/style/core.css
theme/clean/layout/secure.php

index 06de646..89f05f1 100644 (file)
--- a/.jshintrc
+++ b/.jshintrc
@@ -42,7 +42,7 @@
     "sub":          false,
     "supernew":     false,
     "maxerr":       500,
-    "maxlen":       150,
+    "maxlen":       180,
     "passfail":     false,
     "latedef":      true
 }
index ea9f37d..a07104c 100644 (file)
@@ -47,7 +47,9 @@ if (!function_exists('iconv')) {
 
 define('NO_OUTPUT_BUFFERING', true);
 
-if (empty($_GET['cache']) and empty($_POST['cache']) and empty($_GET['sesskey']) and empty($_POST['sesskey'])) {
+if ((isset($_GET['cache']) and $_GET['cache'] === '0')
+        or (isset($_POST['cache']) and $_POST['cache'] === '0')
+        or (!isset($_POST['cache']) and !isset($_GET['cache']) and empty($_GET['sesskey']) and empty($_POST['sesskey']))) {
     // Prevent caching at all cost when visiting this page directly,
     // we redirect to self once we known no upgrades are necessary.
     // Note: $_GET and $_POST are used here intentionally because our param cleaning is not loaded yet.
@@ -90,9 +92,7 @@ $newaddonreq    = optional_param('installaddonrequest', null, PARAM_RAW);
 
 // Set up PAGE.
 $url = new moodle_url('/admin/index.php');
-if ($cache) {
-    $url->param('cache', 1);
-}
+$url->param('cache', $cache);
 $PAGE->set_url($url);
 unset($url);
 
@@ -267,12 +267,13 @@ if (!$cache and $version > $CFG->version) {  // upgrade
     $PAGE->set_pagelayout('maintenance');
     $PAGE->set_popup_notification_allowed(false);
 
+    /** @var core_admin_renderer $output */
+    $output = $PAGE->get_renderer('core', 'admin');
+
     if (upgrade_stale_php_files_present()) {
         $PAGE->set_title($stradministration);
         $PAGE->set_cacheable(false);
 
-        /** @var core_admin_renderer $output */
-        $output = $PAGE->get_renderer('core', 'admin');
         echo $output->upgrade_stale_php_files_page();
         die();
     }
@@ -287,8 +288,6 @@ if (!$cache and $version > $CFG->version) {  // upgrade
         $PAGE->set_heading($strdatabasechecking);
         $PAGE->set_cacheable(false);
 
-        /** @var core_admin_renderer $output */
-        $output = $PAGE->get_renderer('core', 'admin');
         echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
         die();
 
@@ -302,8 +301,6 @@ if (!$cache and $version > $CFG->version) {  // upgrade
         $PAGE->set_heading($strcurrentrelease);
         $PAGE->set_cacheable(false);
 
-        /** @var core_admin_renderer $output */
-        $output = $PAGE->get_renderer('core', 'admin');
         echo $output->upgrade_environment_page($release, $envstatus, $environment_results);
         die();
 
@@ -315,23 +312,13 @@ if (!$cache and $version > $CFG->version) {  // upgrade
         $PAGE->set_heading($strplugincheck);
         $PAGE->set_cacheable(false);
 
-        $reloadurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'confirmrelease' => 1));
-
-        /** @var core_admin_renderer $output */
-        $output = $PAGE->get_renderer('core', 'admin');
-
-        // check plugin dependencies first
-        $failed = array();
-        if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
-            echo $output->unsatisfied_dependencies_page($version, $failed, $reloadurl);
-            die();
-        }
-        unset($failed);
+        $reloadurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'confirmrelease' => 1, 'cache' => 0));
 
         if ($fetchupdates) {
-            // no sesskey support guaranteed here
-            if (empty($CFG->disableupdatenotifications)) {
-                \core\update\checker::instance()->fetch();
+            // No sesskey support guaranteed here, because sessions might not work yet.
+            $updateschecker = \core\update\checker::instance();
+            if ($updateschecker->enabled()) {
+                $updateschecker->fetch();
             }
             redirect($reloadurl);
         }
@@ -342,6 +329,7 @@ if (!$cache and $version > $CFG->version) {  // upgrade
 
             $deploydata = $deployer->submitted_data();
             if (!empty($deploydata)) {
+                // No sesskey support guaranteed here, because sessions might not work yet.
                 echo $output->upgrade_plugin_confirm_deploy_page($deployer, $deploydata);
                 die();
             }
@@ -349,11 +337,22 @@ if (!$cache and $version > $CFG->version) {  // upgrade
 
         echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
                 $version, $showallplugins, $reloadurl,
-                new moodle_url('/admin/index.php', array('confirmupgrade'=>1, 'confirmrelease'=>1, 'confirmplugincheck'=>1)));
+                new moodle_url('/admin/index.php', array('confirmupgrade'=>1, 'confirmrelease'=>1, 'confirmplugincheck'=>1, 'cache'=>0)));
         die();
 
     } else {
-        // Launch main upgrade
+        // Always verify plugin dependencies!
+        $failed = array();
+        if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+            $PAGE->set_pagelayout('maintenance');
+            $PAGE->set_popup_notification_allowed(false);
+            $reloadurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'confirmrelease' => 1, 'cache' => 0));
+            echo $output->unsatisfied_dependencies_page($version, $failed, $reloadurl);
+            die();
+        }
+        unset($failed);
+
+        // Launch main upgrade.
         upgrade_core($version, true);
     }
 } else if ($version < $CFG->version) {
@@ -373,6 +372,10 @@ if (!$cache and $branch <> $CFG->branch) {  // Update the branch
 if (!$cache and moodle_needs_upgrading()) {
     if (!$PAGE->headerprinted) {
         // means core upgrade or installation was not already done
+
+        /** @var core_admin_renderer $output */
+        $output = $PAGE->get_renderer('core', 'admin');
+
         if (!$confirmplugins) {
             $strplugincheck = get_string('plugincheck');
 
@@ -384,40 +387,46 @@ if (!$cache and moodle_needs_upgrading()) {
             $PAGE->set_cacheable(false);
 
             if ($fetchupdates) {
-                // no sesskey support guaranteed here
-                \core\update\checker::instance()->fetch();
+                require_sesskey();
+                $updateschecker = \core\update\checker::instance();
+                if ($updateschecker->enabled()) {
+                    $updateschecker->fetch();
+                }
                 redirect($PAGE->url);
             }
 
-            $output = $PAGE->get_renderer('core', 'admin');
-
             $deployer = \core\update\deployer::instance();
             if ($deployer->enabled()) {
                 $deployer->initialize($PAGE->url, $PAGE->url);
 
                 $deploydata = $deployer->submitted_data();
                 if (!empty($deploydata)) {
+                    require_sesskey();
                     echo $output->upgrade_plugin_confirm_deploy_page($deployer, $deploydata);
                     die();
                 }
             }
 
-            // check plugin dependencies first
-            $failed = array();
-            if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
-                echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
-                die();
-            }
-            unset($failed);
-
-            // dependencies check passed, let's rock!
+            // Show plugins info.
             echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
                     $version, $showallplugins,
                     new moodle_url($PAGE->url),
-                    new moodle_url('/admin/index.php', array('confirmplugincheck'=>1)));
+                    new moodle_url('/admin/index.php', array('confirmplugincheck'=>1, 'cache'=>0)));
+            die();
+        }
+
+        // Make sure plugin dependencies are always checked.
+        $failed = array();
+        if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
+            $PAGE->set_pagelayout('maintenance');
+            $PAGE->set_popup_notification_allowed(false);
+            $reloadurl = new moodle_url('/admin/index.php', array('cache' => 0));
+            echo $output->unsatisfied_dependencies_page($version, $failed, $reloadurl);
             die();
         }
+        unset($failed);
     }
+
     // install/upgrade all plugins and other parts
     upgrade_noncore(true);
 }
@@ -477,6 +486,17 @@ if (during_initial_install()) {
     upgrade_finished('upgradesettings.php');
 }
 
+if (has_capability('moodle/site:config', context_system::instance())) {
+    if ($fetchupdates) {
+        require_sesskey();
+        $updateschecker = \core\update\checker::instance();
+        if ($updateschecker->enabled()) {
+            $updateschecker->fetch();
+        }
+        redirect(new moodle_url('/admin/index.php', array('cache' => 0)));
+    }
+}
+
 // Now we can be sure everything was upgraded and caches work fine,
 // redirect if necessary to make sure caching is enabled.
 if (!$cache) {
@@ -564,12 +584,6 @@ $registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOOD
 
 admin_externalpage_setup('adminnotifications');
 
-if ($fetchupdates) {
-    require_sesskey();
-    $updateschecker->fetch();
-    redirect(new moodle_url('/admin/index.php'));
-}
-
 $output = $PAGE->get_renderer('core', 'admin');
 echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
         $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
index f86097b..3ba44bb 100644 (file)
@@ -140,7 +140,7 @@ class core_admin_renderer extends plugin_renderer_base {
     public function upgrade_confirm_page($strnewversion, $maturity, $testsite) {
         $output = '';
 
-        $continueurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1));
+        $continueurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'cache' => 0));
         $continue = new single_button($continueurl, get_string('continue'), 'get');
         $cancelurl = new moodle_url('/admin/index.php');
 
@@ -170,7 +170,7 @@ class core_admin_renderer extends plugin_renderer_base {
         $output .= $this->environment_check_table($envstatus, $environment_results);
 
         if (!$envstatus) {
-            $output .= $this->upgrade_reload(new moodle_url('/admin/index.php'), array('confirmupgrade' => 1));
+            $output .= $this->upgrade_reload(new moodle_url('/admin/index.php'), array('confirmupgrade' => 1, 'cache' => 0));
 
         } else {
             $output .= $this->notification(get_string('environmentok', 'admin'), 'notifysuccess');
@@ -179,7 +179,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 $output .= $this->box(get_string('langpackwillbeupdated', 'admin'), 'generalbox', 'notice');
             }
 
-            $output .= $this->continue_button(new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'confirmrelease' => 1)));
+            $output .= $this->continue_button(new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'confirmrelease' => 1, 'cache' => 0)));
         }
 
         $output .= $this->footer();
@@ -711,7 +711,7 @@ class core_admin_renderer extends plugin_renderer_base {
         }
 
         $updateinfo .= $this->container_start('checkforupdates');
-        $fetchurl = new moodle_url('/admin/index.php', array('fetchupdates' => 1, 'sesskey' => sesskey(), 'cache' => 1));
+        $fetchurl = new moodle_url('/admin/index.php', array('fetchupdates' => 1, 'sesskey' => sesskey(), 'cache' => 0));
         $updateinfo .= $this->single_button($fetchurl, get_string('checkforupdates', 'core_plugin'));
         if ($fetch) {
             $updateinfo .= $this->container(get_string('checkforupdateslast', 'core_plugin',
@@ -962,7 +962,7 @@ class core_admin_renderer extends plugin_renderer_base {
             $out .= $this->output->heading(get_string('nonehighlighted', 'core_plugin'));
             if (empty($options['full'])) {
                 $out .= html_writer::link(new moodle_url('/admin/index.php',
-                    array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 1)),
+                    array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 1, 'cache' => 0)),
                     get_string('nonehighlightedinfo', 'core_plugin'));
             }
             $out .= $this->output->container_end();
@@ -972,11 +972,11 @@ class core_admin_renderer extends plugin_renderer_base {
             $out .= $this->output->heading(get_string('somehighlighted', 'core_plugin', $sumofhighlighted));
             if (empty($options['full'])) {
                 $out .= html_writer::link(new moodle_url('/admin/index.php',
-                    array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 1)),
+                    array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 1, 'cache' => 0)),
                     get_string('somehighlightedinfo', 'core_plugin'));
             } else {
                 $out .= html_writer::link(new moodle_url('/admin/index.php',
-                    array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 0)),
+                    array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 0, 'cache' => 0)),
                     get_string('somehighlightedonly', 'core_plugin'));
             }
             $out .= $this->output->container_end();
index ae9d83b..16aef6d 100644 (file)
@@ -19,7 +19,7 @@ Feature: Upload users
     And I expand "Users" node
     And I expand "Accounts" node
     And I follow "Upload users"
-    When I upload "lib/tests/fixtures/upload_users.csv" file to "File" filepicker
+    When I upload "lib/tests/fixtures/upload_users.csv" file to "File" filemanager
     And I press "Upload users"
     Then I should see "Upload users preview"
     And I should see "Tom"
diff --git a/admin/tool/replace/classes/form.php b/admin/tool/replace/classes/form.php
new file mode 100644 (file)
index 0000000..5c60510
--- /dev/null
@@ -0,0 +1,69 @@
+<?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/>.
+
+/**
+ * Site wide search-replace form.
+ *
+ * @package    tool_replace
+ * @copyright  2013 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once("$CFG->libdir/formslib.php");
+
+/**
+ * Site wide search-replace form.
+ */
+class tool_replace_form extends moodleform {
+    function definition() {
+        global $CFG, $DB;
+
+        $mform = $this->_form;
+
+        $mform->addElement('header', 'searchhdr', get_string('pluginname', 'tool_replace'));
+        $mform->setExpanded('searchhdr', true);
+
+        $mform->addElement('text', 'search', get_string('searchwholedb', 'tool_replace'), 'size="50"');
+        $mform->setType('search', PARAM_RAW);
+        $mform->addElement('static', 'searchst', '', get_string('searchwholedbhelp', 'tool_replace'));
+        $mform->addRule('search', get_string('required'), 'required', null, 'client');
+
+        $mform->addElement('text', 'replace', get_string('replacewith', 'tool_replace'), 'size="50"', PARAM_RAW);
+        $mform->addElement('static', 'replacest', '', get_string('replacewithhelp', 'tool_replace'));
+        $mform->setType('replace', PARAM_RAW);
+        $mform->addElement('checkbox', 'shorten', get_string('shortenoversized', 'tool_replace'));
+        $mform->addRule('replace', get_string('required'), 'required', null, 'client');
+
+        $mform->addElement('header', 'confirmhdr', get_string('confirm'));
+        $mform->setExpanded('confirmhdr', true);
+        $mform->addElement('checkbox', 'sure', get_string('disclaimer', 'tool_replace'));
+        $mform->addRule('sure', get_string('required'), 'required', null, 'client');
+
+        $this->add_action_buttons(false, get_string('doit', 'tool_replace'));
+    }
+
+    function validation($data, $files) {
+        $errors = parent::validation($data, $files);
+
+        if (empty($data['shorten']) and core_text::strlen($data['search']) < core_text::strlen($data['replace'])) {
+            $errors['shorten'] = get_string('required');
+        }
+
+        return $errors;
+    }
+}
index 67d945e..b3013d2 100644 (file)
@@ -17,8 +17,7 @@
 /**
  * Search and replace strings throughout all texts in the whole database
  *
- * @package    tool
- * @subpackage replace
+ * @package    tool_replace
  * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
@@ -31,56 +30,38 @@ require_once($CFG->libdir.'/adminlib.php');
 
 admin_externalpage_setup('toolreplace');
 
-$search  = optional_param('search', '', PARAM_RAW);
-$replace = optional_param('replace', '', PARAM_RAW);
-$sure    = optional_param('sure', 0, PARAM_BOOL);
-
-###################################################################
 echo $OUTPUT->header();
 
 echo $OUTPUT->heading(get_string('pageheader', 'tool_replace'));
 
-if ($DB->get_dbfamily() !== 'mysql' and $DB->get_dbfamily() !== 'postgres') {
-    //TODO: add $DB->text_replace() to DML drivers
+if (!$DB->replace_all_text_supported()) {
     echo $OUTPUT->notification(get_string('notimplemented', 'tool_replace'));
     echo $OUTPUT->footer();
     die;
 }
 
-if (!data_submitted() or !$search or !$replace or !confirm_sesskey() or !$sure) {   /// Print a form
-    echo $OUTPUT->notification(get_string('notsupported', 'tool_replace'));
-    echo $OUTPUT->notification(get_string('excludedtables', 'tool_replace'));
+echo $OUTPUT->box_start();
+echo $OUTPUT->notification(get_string('notsupported', 'tool_replace'));
+echo $OUTPUT->notification(get_string('excludedtables', 'tool_replace'));
+echo $OUTPUT->box_end();
+
+$form = new tool_replace_form();
 
-    echo $OUTPUT->box_start();
-    echo '<div class="mdl-align">';
-    echo '<form action="index.php" method="post"><div>';
-    echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-    echo '<div><label for="search">'.get_string('searchwholedb', 'tool_replace').
-            ' </label><input id="search" type="text" name="search" size="40" /> ('.
-            get_string('searchwholedbhelp', 'tool_replace').')</div>';
-    echo '<div><label for="replace">'.get_string('replacewith', 'tool_replace').
-            ' </label><input type="text" id="replace" name="replace" size="40" /> ('.
-            get_string('replacewithhelp', 'tool_replace').')</div>';
-    echo '<div><label for="sure">'.get_string('disclaimer', 'tool_replace').' </label><input type="checkbox" id="sure" name="sure" value="1" /></div>';
-    echo '<div class="buttons"><input type="submit" class="singlebutton" value="Yes, do it now" /></div>';
-    echo '</div></form>';
-    echo '</div>';
-    echo $OUTPUT->box_end();
+if (!$data = $form->get_data()) {
+    $form->display();
     echo $OUTPUT->footer();
-    die;
+    die();
 }
 
+// Scroll to the end when finished.
+$PAGE->requires->js_init_code("window.scrollTo(0, 5000000);");
+
 echo $OUTPUT->box_start();
-db_replace($search, $replace);
+db_replace($data->search, $data->replace);
 echo $OUTPUT->box_end();
 
-/// Rebuild course cache which might be incorrect now
-echo $OUTPUT->notification(get_string('notifyrebuilding', 'tool_replace'), 'notifysuccess');
-rebuild_course_cache();
-echo $OUTPUT->notification(get_string('notifyfinished', 'tool_replace'), 'notifysuccess');
+// Course caches are now rebuilt on the fly.
 
 echo $OUTPUT->continue_button(new moodle_url('/admin/index.php'));
 
 echo $OUTPUT->footer();
-
-
index 9103e89..919ed67 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['disclaimer'] = 'I understand the risks of this operation:';
+$string['cannotfit'] = 'The replacement is longer than original and shortening is not allow, cannot continue.';
+$string['disclaimer'] = 'I understand the risks of this operation';
+$string['doit'] = 'Yes, do it!';
 $string['excludedtables'] = 'Several tables are not updated as part of the text replacement. This include configuration, log, events, and session tables.';
 $string['pageheader'] = 'Search and replace text throughout the whole database';
 $string['notifyfinished'] = '...finished';
 $string['notifyrebuilding'] = 'Rebuilding course cache...';
-$string['notimplemented'] = 'Sorry, this feature is implemented only for MySQL and PostgreSQL databases.';
+$string['notimplemented'] = 'Sorry, this feature is not implemented in your database driver.';
 $string['notsupported'] ='This script is not supported, always make complete backup before proceeding!<br />This operation can not be reverted!';
 $string['pluginname'] = 'DB search and replace';
-$string['replacewith'] = 'Replace with this string:';
+$string['replacewith'] = 'Replace with this string';
 $string['replacewithhelp'] = 'usually new server URL';
-$string['searchwholedb'] = 'Search whole database for:';
+$string['searchwholedb'] = 'Search whole database for';
 $string['searchwholedbhelp'] = 'usually previous server URL';
+$string['shortenoversized'] = 'Shorten result if necessary';
index 4496dcd..307be8f 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013110500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013110501; // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013110500; // Requires this Moodle version
 $plugin->component = 'tool_replace'; // Full name of the plugin (used for diagnostics)
 
index ee95ca1..ce2c98b 100644 (file)
@@ -15,7 +15,7 @@ Feature: An admin can create courses using a CSV file
 
   @javascript
   Scenario: Creation of unexisting courses
-    Given I upload "admin/tool/uploadcourse/tests/fixtures/courses.csv" file to "File" filepicker
+    Given I upload "admin/tool/uploadcourse/tests/fixtures/courses.csv" file to "File" filemanager
     And I click on "Preview" "button"
     When I click on "Upload courses" "button"
     Then I should see "The course exists and update is not allowed"
@@ -29,7 +29,7 @@ Feature: An admin can create courses using a CSV file
 
   @javascript
   Scenario: Creation of existing courses
-    Given I upload "admin/tool/uploadcourse/tests/fixtures/courses.csv" file to "File" filepicker
+    Given I upload "admin/tool/uploadcourse/tests/fixtures/courses.csv" file to "File" filemanager
     And I select "Create all, increment shortname if needed" from "Upload mode"
     And I click on "Preview" "button"
     When I click on "Upload courses" "button"
index 3a06d16..457f07d 100644 (file)
@@ -15,7 +15,7 @@ Feature: An admin can update courses using a CSV file
 
   @javascript
   Scenario: Updating a course fullname
-    Given I upload "admin/tool/uploadcourse/tests/fixtures/courses.csv" file to "File" filepicker
+    Given I upload "admin/tool/uploadcourse/tests/fixtures/courses.csv" file to "File" filemanager
     And I select "Only update existing courses" from "Upload mode"
     And I select "Update with CSV data only" from "Update mode"
     And I click on "Preview" "button"
index 3aef57c..dea693b 100644 (file)
@@ -207,12 +207,14 @@ class web_service_token_form extends moodleform {
 
             if ($usertotal < 500) {
                 list($sort, $params) = users_order_by_sql('u');
-                //user searchable selector - get all users (admin and guest included)
-                //user must be confirmed, not deleted, not suspended, not guest
-                $sql = "SELECT u.id, u.firstname, u.lastname
-                            FROM {user} u
-                            WHERE u.deleted = 0 AND u.confirmed = 1 AND u.suspended = 0 AND u.id != :siteguestid
-                            ORDER BY $sort";
+                // User searchable selector - return users who are confirmed, not deleted, not suspended and not a guest.
+                $sql = 'SELECT u.id, ' . get_all_user_name_fields(true, 'u') . '
+                        FROM {user} u
+                        WHERE u.deleted = 0
+                        AND u.confirmed = 1
+                        AND u.suspended = 0
+                        AND u.id != :siteguestid
+                        ORDER BY ' . $sort;
                 $params['siteguestid'] = $CFG->siteguest;
                 $users = $DB->get_records_sql($sql, $params);
                 $options = array();
index 762ea70..262142e 100644 (file)
@@ -348,12 +348,12 @@ abstract class base_moodleform extends moodleform {
         $config->yesLabel = get_string('confirmcancelyes', 'backup');
         $config->noLabel = get_string('confirmcancelno', 'backup');
         $config->closeButtonTitle = get_string('close', 'editor');
-        $PAGE->requires->yui_module('moodle-backup-confirmcancel', 'M.core_backup.watch_cancel_buttons', array($config));
+        $PAGE->requires->yui_module('moodle-backup-confirmcancel', 'M.core_backup.confirmcancel.watch_cancel_buttons', array($config));
 
         // Get list of module types on course.
         $modinfo = get_fast_modinfo($COURSE);
         $modnames = $modinfo->get_used_module_names(true);
-        $PAGE->requires->yui_module('moodle-backup-backupselectall', 'M.core_backup.select_all_init',
+        $PAGE->requires->yui_module('moodle-backup-backupselectall', 'M.core_backup.backupselectall',
                 array($modnames));
         $PAGE->requires->strings_for_js(array('select', 'all', 'none'), 'moodle');
         $PAGE->requires->strings_for_js(array('showtypes', 'hidetypes'), 'backup');
diff --git a/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js
new file mode 100644 (file)
index 0000000..3de94d5
Binary files /dev/null and b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js differ
diff --git a/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js
new file mode 100644 (file)
index 0000000..b001213
Binary files /dev/null and b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js differ
diff --git a/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js
new file mode 100644 (file)
index 0000000..3de94d5
Binary files /dev/null and b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js differ
diff --git a/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-debug.js b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-debug.js
new file mode 100644 (file)
index 0000000..173f290
Binary files /dev/null and b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-debug.js differ
diff --git a/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js
new file mode 100644 (file)
index 0000000..f19f1a9
Binary files /dev/null and b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js differ
diff --git a/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel.js b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel.js
new file mode 100644 (file)
index 0000000..173f290
Binary files /dev/null and b/backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel.js differ
diff --git a/backup/util/ui/yui/confirmcancel/confirmcancel.js b/backup/util/ui/yui/confirmcancel/confirmcancel.js
deleted file mode 100644 (file)
index 77deaf1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-YUI.add('moodle-backup-confirmcancel', function(Y) {
-
-// Namespace for the backup
-M.core_backup = M.core_backup || {};
-/**
- * Adds confirmation dialogues to the cancel buttons on the page.
- *
- * @param {object} config
- */
-M.core_backup.watch_cancel_buttons = function(config) {
-    Y.all('.confirmcancel').each(function(){
-        this._confirmationListener = this._confirmationListener || this.on('click', function(e){
-            // Prevent the default event (sumbit) from firing
-            e.preventDefault();
-            // Create the confirm box
-            var confirm = new M.core.confirm(config);
-            // If the user clicks yes
-            confirm.on('complete-yes', function(e){
-                // Detach the listener for the confirm box so it doesn't fire again.
-                this._confirmationListener.detach();
-                // Simulate the original cancel button click
-                this.simulate('click');
-            }, this);
-            // Show the confirm box
-            confirm.show();
-        }, this);
-    });
-}
-
-}, '@VERSION@', {'requires':['base','node','node-event-simulate','moodle-core-notification']});
diff --git a/backup/util/ui/yui/src/backupselectall/build.json b/backup/util/ui/yui/src/backupselectall/build.json
new file mode 100644 (file)
index 0000000..85b6072
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "name": "moodle-backup-backupselectall",
+  "builds": {
+    "moodle-backup-backupselectall": {
+      "jsfiles": [
+        "backupselectall.js"
+      ]
+    }
+  }
+}
@@ -1,12 +1,18 @@
-YUI.add('moodle-backup-backupselectall', function(Y) {
+/**
+ * Adds select all/none links to the top of the backup/restore/import schema page.
+ *
+ * @module moodle-backup-backupselectall
+ */
 
 // Namespace for the backup
 M.core_backup = M.core_backup || {};
 
 /**
  * Adds select all/none links to the top of the backup/restore/import schema page.
+ *
+ * @class M.core_backup.backupselectall
  */
-M.core_backup.select_all_init = function(modnames) {
+M.core_backup.backupselectall = function(modnames) {
     var formid = null;
 
     var helper = function(e, check, type, mod) {
@@ -23,7 +29,7 @@ M.core_backup.select_all_init = function(modnames) {
             if (prefix && name.substring(0, prefix.length) !== prefix) {
                 return;
             }
-            if (name.substring(name.length - len) == type) {
+            if (name.substring(name.length - len) === type) {
                 checkbox.set('checked', check);
             }
         });
@@ -67,9 +73,9 @@ M.core_backup.select_all_init = function(modnames) {
     var withuserdata = false;
     Y.all('input[type="checkbox"]').each(function(checkbox) {
         var name = checkbox.get('name');
-        if (name.substring(name.length - 9) == '_userdata') {
+        if (name.substring(name.length - 9) === '_userdata') {
             withuserdata = '_userdata';
-        } else if (name.substring(name.length - 9) == '_userinfo') {
+        } else if (name.substring(name.length - 9) === '_userinfo') {
             withuserdata = '_userinfo';
         }
     });
@@ -103,7 +109,7 @@ M.core_backup.select_all_init = function(modnames) {
         if (!modnames.hasOwnProperty(mod)) {
             continue;
         }
-        var html = html_generator('include_setting section_level', 'mod_' + mod, modnames[mod]);
+        html = html_generator('include_setting section_level', 'mod_' + mod, modnames[mod]);
         if (withuserdata) {
             html += html_generator('normal_setting', 'userdata-mod_' + mod, modnames[mod]);
         }
@@ -127,26 +133,27 @@ M.core_backup.select_all_init = function(modnames) {
         modlist.currentlyshown = !modlist.currentlyshown;
 
         // Either hide or show the links.
-        var animcfg = { node: modlist, duration: 0.2 };
+        var animcfg = { node: modlist, duration: 0.2 },
+            anim;
         if (modlist.currentlyshown) {
             // Animate reveal of the module links.
             modlist.show();
             animcfg.to = { maxHeight: modlist.get('clientHeight') + 'px' };
             modlist.setStyle('maxHeight', '0px');
-            var anim = new Y.Anim(animcfg);
+            anim = new Y.Anim(animcfg);
             anim.on('end', function() { modlist.setStyle('maxHeight', 'none'); });
             anim.run();
         } else {
             // Animate hide of the module links.
             animcfg.to = { maxHeight: '0px' };
             modlist.setStyle('maxHeight', modlist.get('clientHeight') + 'px');
-            var anim = new Y.Anim(animcfg);
+            anim = new Y.Anim(animcfg);
             anim.on('end', function() { modlist.hide(); modlist.setStyle('maxHeight', 'none'); });
             anim.run();
         }
 
     };
-    Y.one('#backup-bytype').on('click', function(e) { toggletypes(); });
+    Y.one('#backup-bytype').on('click', function() { toggletypes(); });
 
     Y.one('#backup-all-included').on('click',  function(e) { helper(e, true,  '_included'); });
     Y.one('#backup-none-included').on('click', function(e) { helper(e, false, '_included'); });
@@ -154,6 +161,4 @@ M.core_backup.select_all_init = function(modnames) {
         Y.one('#backup-all-userdata').on('click',  function(e) { helper(e, true,  withuserdata); });
         Y.one('#backup-none-userdata').on('click', function(e) { helper(e, false, withuserdata); });
     }
-}
-
-}, '@VERSION@', {'requires':['base', 'node', 'event', 'node-event-simulate', 'anim']});
+};
diff --git a/backup/util/ui/yui/src/backupselectall/js/backupselectall.json b/backup/util/ui/yui/src/backupselectall/js/backupselectall.json
new file mode 100644 (file)
index 0000000..81f6ce7
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "moodle-backup-backupselectall": {
+    "requires": [
+        "node",
+        "event",
+        "node-event-simulate",
+        "anim"
+    ]
+  }
+}
diff --git a/backup/util/ui/yui/src/backupselectall/meta/backupselectall.json b/backup/util/ui/yui/src/backupselectall/meta/backupselectall.json
new file mode 100644 (file)
index 0000000..81f6ce7
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "moodle-backup-backupselectall": {
+    "requires": [
+        "node",
+        "event",
+        "node-event-simulate",
+        "anim"
+    ]
+  }
+}
diff --git a/backup/util/ui/yui/src/confirmcancel/build.json b/backup/util/ui/yui/src/confirmcancel/build.json
new file mode 100644 (file)
index 0000000..603210c
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "name": "moodle-backup-confirmcancel",
+    "builds": {
+        "moodle-backup-confirmcancel": {
+            "jsfiles": [
+                "confirmcancel.js"
+            ]
+        }
+    }
+}
diff --git a/backup/util/ui/yui/src/confirmcancel/js/confirmcancel.js b/backup/util/ui/yui/src/confirmcancel/js/confirmcancel.js
new file mode 100644 (file)
index 0000000..ddaeb52
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * Add a confirmation dialogue when cancelling a backup.
+ *
+ * @module moodle-backup-confirmcancel
+ */
+
+/**
+ * Add a confirmation dialogue when cancelling a backup.
+ *
+ * @class M.core_backup.confirmcancel
+ */
+
+
+// Namespace for the backup.
+M.core_backup = M.core_backup || {};
+
+M.core_backup.confirmcancel = {
+    /**
+     * An array of EventHandlers which call the confirm_cancel dialogue.
+     *
+     * @property listeners
+     * @protected
+     * @type Array
+     */
+    listeners: [],
+
+    /**
+     * The configuration supplied to this instance.
+     *
+     * @property config
+     * @protected
+     * @type Object
+     */
+    config: {},
+
+    /**
+     * Initializer to watch all cancel buttons.
+     *
+     * @method watch_cancel_buttons
+     * @param {Object} config The configuration for the confirmation dialogue.
+     */
+    watch_cancel_buttons: function(config) {
+        this.config = config;
+
+        this.listeners.push(
+            Y.one(Y.config.doc.body).delegate('click', this.confirm_cancel, '.confirmcancel', this)
+        );
+    },
+
+    /**
+     * Display the confirmation dialogue.
+     *
+     * @method confirm_cancel
+     * @protected
+     * @param {EventFacade} e
+     */
+    confirm_cancel: function(e) {
+        // Prevent the default event (submit) from firing.
+        e.preventDefault();
+
+        // Create the confirmation dialogue.
+        var confirm = new M.core.confirm(this.config);
+
+        // If the user clicks yes.
+        confirm.on('complete-yes', function(){
+            // Detach the listeners for the confirm box so they don't fire again.
+            new Y.EventHandle(M.core_backup.confirmcancel.listeners).detach();
+
+            // Simulate the original cancel button click.
+            c.currentTarget.simulate('click');
+        }, this);
+
+
+        // Show the confirm box.
+        confirm.show();
+    }
+};
diff --git a/backup/util/ui/yui/src/confirmcancel/meta/confirmcancel.json b/backup/util/ui/yui/src/confirmcancel/meta/confirmcancel.json
new file mode 100644 (file)
index 0000000..e352bdf
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "moodle-backup-confirmcancel": {
+        "requires": [
+            "node",
+            "node-event-simulate",
+            "moodle-core-notification-confirm"
+        ]
+    }
+}
index 9d4b5fa..64bf704 100644 (file)
@@ -36,7 +36,7 @@ Feature: Add badges to the system
       | Description | Test badge description |
       | issuername | Test Badge Site |
       | issuercontact | testuser@test-badge-site.com |
-    And I upload "badges/tests/behat/badge.png" file to "Image" filepicker
+    And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
     When I press "Create badge"
     Then I should see "Edit details"
     And I should see "Test Badge"
index d34d36e..c738acf 100644 (file)
@@ -18,7 +18,7 @@ Feature: Award badges
       | Description | Test badge description |
       | issuername | Test Badge Site |
       | issuercontact | testuser@test-badge-site.com |
-    And I upload "badges/tests/behat/badge.png" file to "Image" filepicker
+    And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
     And I press "Create badge"
     And I select "Profile completion" from "type"
     And I check "First name"
@@ -53,7 +53,7 @@ Feature: Award badges
       | Name | Site Badge |
       | Description | Site badge description |
       | issuername | Tester of site badge |
-    And I upload "badges/tests/behat/badge.png" file to "Image" filepicker
+    And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
     And I press "Create badge"
     And I select "Manual issue by role" from "type"
     And I check "Teacher"
@@ -98,7 +98,7 @@ Feature: Award badges
       | Name | Course Badge |
       | Description | Course badge description |
       | issuername | Tester of course badge |
-    And I upload "badges/tests/behat/badge.png" file to "Image" filepicker
+    And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
     And I press "Create badge"
     And I select "Manual issue by role" from "type"
     And I check "Teacher"
@@ -156,7 +156,7 @@ Feature: Award badges
       | Name | Course Badge |
       | Description | Course badge description |
       | issuername | Tester of course badge |
-    And I upload "badges/tests/behat/badge.png" file to "Image" filepicker
+    And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
     And I press "Create badge"
     And I select "Activity completion" from "type"
     And I check "Test assignment name"
@@ -219,7 +219,7 @@ Feature: Award badges
       | Name | Course Badge |
       | Description | Course badge description |
       | issuername | Tester of course badge |
-    And I upload "badges/tests/behat/badge.png" file to "Image" filepicker
+    And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
     And I press "Create badge"
     And I select "Course completion" from "type"
     And I fill the moodle form with:
index 1bee81e..e002c94 100644 (file)
@@ -83,6 +83,7 @@ class block_blog_recent extends block_base {
 
         $this->content = new stdClass();
         $this->content->footer = '';
+        $this->content->text = '';
 
         $context = $this->page->context;
 
index b6e6822..7a116ee 100644 (file)
Binary files a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js and b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js differ
index e474ba8..c48a7c3 100644 (file)
Binary files a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js and b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js differ
index 368a23d..0ecd3b9 100644 (file)
Binary files a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js and b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js differ
index 0748b98..7db6ca9 100644 (file)
@@ -409,7 +409,7 @@ Y.extend(TREE, Y.Base, TREE.prototype, {
         instance : {
             value : false,
             setter : function(val) {
-                return parseInt(val);
+                return parseInt(val, 10);
             }
         }
     }
index 5e6a5ad..eb0ea17 100644 (file)
@@ -27,7 +27,7 @@ Feature: Upload users to a cohort
     And I expand "Users" node
     And I expand "Accounts" node
     When I follow "Upload users"
-    And I upload "lib/tests/fixtures/upload_users_cohorts.csv" file to "File" filepicker
+    And I upload "lib/tests/fixtures/upload_users_cohorts.csv" file to "File" filemanager
     And I press "Upload users"
     And I press "Upload users"
     And I press "Continue"
index cafa530..e7f1631 100644 (file)
@@ -672,6 +672,11 @@ $CFG->admin = 'admin';
 // Example:
 //   $CFG->behat_usedeprecated = true;
 //
+// Including feature files from directories outside the dirroot is possible if required. The setting
+// requires that the running user has executable permissions on all parent directories in the paths.
+// Example:
+//   $CFG->behat_additionalfeatures = array('/home/developer/code/wipfeatures');
+//
 //=========================================================================
 // 12. DEVELOPER DATA GENERATOR
 //=========================================================================
index ce72a9c..2f3ef23 100644 (file)
@@ -2183,7 +2183,7 @@ function course_get_cm_move(cm_info $mod, $sr = null) {
     if ($hasmanageactivities) {
         $pixicon = 'i/dragdrop';
 
-        if ($mod->course == SITEID) {
+        if (!course_ajax_enabled($mod->get_course())) {
             // Override for course frontpage until we get drag/drop working there.
             $pixicon = 't/move';
         }
index 606def8..f536bb2 100644 (file)
@@ -24,6 +24,8 @@
 
 $string['allowguests'] = 'This course allows guest users to enter';
 $string['guest:config'] = 'Configure guest access instances';
+$string['guestaccess_withpassword'] = 'Guest access requires password';
+$string['guestaccess_withoutpassword'] = 'Guest access';
 $string['password'] = 'Password';
 $string['password_help'] = 'A password allows guest access to the course to be restricted to only those who know the password. Guests will be required to supply the password each time they access the course.';
 $string['passwordinvalid'] = 'Incorrect access password, please try again';
index 65444bd..2f0d444 100644 (file)
@@ -44,9 +44,9 @@ class enrol_guest_plugin extends enrol_plugin {
     public function get_info_icons(array $instances) {
         foreach ($instances as $instance) {
             if ($instance->password !== '') {
-                return array(new pix_icon('withpassword', get_string('pluginname', 'enrol_guest'), 'enrol_guest'));
+                return array(new pix_icon('withpassword', get_string('guestaccess_withpassword', 'enrol_guest'), 'enrol_guest'));
             } else {
-                return array(new pix_icon('withoutpassword', get_string('pluginname', 'enrol_guest'), 'enrol_guest'));
+                return array(new pix_icon('withoutpassword', get_string('guestaccess_withoutpassword', 'enrol_guest'), 'enrol_guest'));
             }
         }
     }
diff --git a/enrol/yui/notification/notification.js b/enrol/yui/notification/notification.js
deleted file mode 100644 (file)
index f2bf542..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * This module provides backwards compatability and should be removed
- * entirely in Moodle 2.5
- */
-YUI.add('moodle-enrol-notification', function(Y) {
-    console.log("You are using a deprecated name. Please update your YUI module to use moodle-core-notification instead of moodle-enrol-notification");
-}, '@VERSION@', {requires:['base','node','overlay','event-key', 'moodle-core-notification']});
index 57aca33..83322aa 100644 (file)
@@ -22,7 +22,7 @@ Feature: Importing of groups and groupings
     And I expand "Users" node
     And I follow "Groups"
     And I press "Import groups"
-    When I upload "group/tests/fixtures/groups_import.csv" file to "Import" filepicker
+    When I upload "group/tests/fixtures/groups_import.csv" file to "Import" filemanager
     And I press "Import groups"
     And I press "Continue"
     Then I should see "group-id-1"
@@ -47,7 +47,7 @@ Feature: Importing of groups and groupings
     And I expand "Users" node
     And I follow "Groups"
     And I press "Import groups"
-    When I upload "group/tests/fixtures/groups_import.csv" file to "Import" filepicker
+    When I upload "group/tests/fixtures/groups_import.csv" file to "Import" filemanager
     And I press "Import groups"
     Then I should see "Group group-id-1 added successfully"
     And I should see "Group group-id-2 added successfully"
@@ -91,7 +91,7 @@ Feature: Importing of groups and groupings
     And I expand "Users" node
     And I follow "Groups"
     And I press "Import groups"
-    When I upload "group/tests/fixtures/groups_import.csv" file to "Import" filepicker
+    When I upload "group/tests/fixtures/groups_import.csv" file to "Import" filemanager
     And I press "Import groups"
     And I press "Continue"
     Then I select "group-id-1" from "groups"
index 387d439..d20f174 100644 (file)
@@ -723,6 +723,7 @@ $string['eventcourseresetstarted'] = 'Course reset started';
 $string['eventcourserestored'] = 'Course restored';
 $string['eventcourseupdated'] = 'Course updated';
 $string['eventcoursesectionupdated'] = ' Course section updated';
+$string['eventcoursemoduleinstancelistviewed'] = 'Course module instance list viewed';
 $string['eventusercreated'] = 'User created';
 $string['eventuserdeleted'] = 'User deleted';
 $string['eventuserlistviewed'] = 'User list viewed';
@@ -1333,7 +1334,6 @@ $string['numyears'] = '{$a} years';
 $string['ok'] = 'OK';
 $string['oldpassword'] = 'Current password';
 $string['olduserdirectory'] = 'This is the OLD users directory, and is no longer needed. You may safely delete it. The files it contains have been copied to the NEW user directory.';
-$string['opentoguests'] = 'Guest access';
 $string['optional'] = 'optional';
 $string['options'] = 'options';
 $string['order'] = 'Order';
index 449a88e..a190faa 100644 (file)
@@ -6741,11 +6741,8 @@ function db_replace($search, $replace) {
 
         if ($columns = $DB->get_columns($table)) {
             $DB->set_debug(true);
-            foreach ($columns as $column => $data) {
-                if (in_array($data->meta_type, array('C', 'X'))) {  // Text stuff only
-                    //TODO: this should be definitively moved to DML driver to do the actual replace, this is not going to work for MSSQL and Oracle...
-                    $DB->execute("UPDATE {".$table."} SET $column = REPLACE($column, ?, ?)", array($search, $replace));
-                }
+            foreach ($columns as $column) {
+                $DB->replace_all_text($table, $column, $search, $replace);
             }
             $DB->set_debug(false);
         }
@@ -6776,6 +6773,8 @@ function db_replace($search, $replace) {
         echo $OUTPUT->notification("...finished", 'notifysuccess');
     }
 
+    purge_all_caches();
+
     return true;
 }
 
index 6278ff7..241a773 100644 (file)
@@ -29,7 +29,8 @@
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
 use Behat\Mink\Exception\ExpectationException as ExpectationException,
-    Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
+    Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
+    Behat\Mink\Element\NodeElement as NodeElement;
 
 /**
  * Steps definitions base class.
@@ -39,6 +40,11 @@ use Behat\Mink\Exception\ExpectationException as ExpectationException,
  * It can not contain steps definitions to avoid duplicates, only utility
  * methods shared between steps.
  *
+ * @method NodeElement find_field(string $locator) Finds a form element
+ * @method NodeElement find_button(string $locator) Finds a form input submit element or a button
+ * @method NodeElement find_link(string $locator) Finds a link on a page
+ * @method NodeElement find_file(string $locator) Finds a forum input file element
+ *
  * @package   core
  * @category  test
  * @copyright 2012 David Monllaó
index 3ee17b6..06358f3 100644 (file)
@@ -32,7 +32,7 @@
 require_once(__DIR__ . '/behat_base.php');
 
 use Behat\Mink\Exception\ExpectationException as ExpectationException,
-    Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
+    Behat\Mink\Element\NodeElement as NodeElement;
 
 /**
  * Files-related actions.
@@ -49,9 +49,9 @@ use Behat\Mink\Exception\ExpectationException as ExpectationException,
 class behat_files extends behat_base {
 
     /**
-     * Gets the filepicker NodeElement.
+     * Gets the NodeElement for filepicker of filemanager moodleform element.
      *
-     * The filepicker field label is pointing to a hidden input which is
+     * The filepicker/filemanager element label is pointing to a hidden input which is
      * not recognized as a named selector, as it is hidden...
      *
      * @throws ExpectationException Thrown by behat_base::find
@@ -77,7 +77,7 @@ class behat_files extends behat_base {
     }
 
     /**
-     * Performs $action on a filepicker container element (file or folder).
+     * Performs $action on a filemanager container element (file or folder).
      *
      * It works together with open_element_contextual_menu
      * as this method needs the contextual menu to be opened.
@@ -99,22 +99,25 @@ class behat_files extends behat_base {
     /**
      * Opens the contextual menu of a folder or a file.
      *
-     * Works both in filepicker elements and when dealing with repository
-     * elements inside modal windows.
+     * Works both in filemanager elements and when dealing with repository
+     * elements inside filepicker modal window.
      *
      * @throws ExpectationException Thrown by behat_base::find
      * @param string $name The name of the folder/file
-     * @param string $filepickerelement The filepicker locator, the whole DOM if false
+     * @param string $filemanagerelement The filemanager form element locator, the repository items are in filepicker modal window if false
      * @return void
      */
-    protected function open_element_contextual_menu($name, $filepickerelement = false) {
+    protected function open_element_contextual_menu($name, $filemanagerelement = false) {
 
-        // If a filepicker is specified we restrict the search to the filepicker descendants.
+        // If a filemanager is specified we restrict the search to the descendants of this particular filemanager form element.
         $containernode = false;
         $exceptionmsg = '"'.$name.'" element can not be found';
-        if ($filepickerelement) {
-            $containernode = $this->get_filepicker_node($filepickerelement);
-            $exceptionmsg = 'The "'.$filepickerelement.'" filepicker ' . $exceptionmsg;
+        if ($filemanagerelement) {
+            $containernode = $this->get_filepicker_node($filemanagerelement);
+            $exceptionmsg = 'The "'.$filemanagerelement.'" filemanager ' . $exceptionmsg;
+            $locatorprefix = "//div[@class='fp-content']";
+        } else {
+            $locatorprefix = "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-items ')]//descendant::div[@class='fp-content']";
         }
 
         $exception = new ExpectationException($exceptionmsg, $this->getSession());
@@ -122,13 +125,13 @@ class behat_files extends behat_base {
         // Avoid quote-related problems.
         $name = $this->getSession()->getSelectorsHandler()->xpathLiteral($name);
 
-        // Get a filepicker element (folder or file).
+        // Get a filepicker/filemanager element (folder or file).
         try {
 
             // First we look at the folder as we need to click on the contextual menu otherwise it would be opened.
             $node = $this->find(
                 'xpath',
-                "//div[@class='fp-content']" .
+                $locatorprefix .
                     "//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]" .
                     "[contains(concat(' ', normalize-space(@class), ' '), ' fp-folder ')]" .
                     "[normalize-space(.)=$name]" .
@@ -142,7 +145,7 @@ class behat_files extends behat_base {
             // Here the contextual menu is hidden, we click on the thumbnail.
             $node = $this->find(
                 'xpath',
-                "//div[@class='fp-content']" .
+                $locatorprefix .
                 "//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]" .
                 "[normalize-space(.)=$name]" .
                 "//descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-thumbnail ')]",
@@ -156,25 +159,25 @@ class behat_files extends behat_base {
     }
 
     /**
-     * Opens the 'add file' modal window and selects the repository.
+     * Opens the filepicker modal window and selects the repository.
      *
      * @throws ExpectationException Thrown by behat_base::find
-     * @param NodeElement $filepickernode The filepicker DOM node.
+     * @param NodeElement $filemanagernode The filemanager or filepicker form element DOM node.
      * @param mixed $repositoryname The repo name.
      * @return void
      */
-    protected function open_add_file_window($filepickernode, $repositoryname) {
+    protected function open_add_file_window($filemanagernode, $repositoryname) {
 
-        $exception = new ExpectationException('No files can be added to the specified filepicker', $this->getSession());
+        $exception = new ExpectationException('No files can be added to the specified filemanager', $this->getSession());
 
-        // We should deal with single-file and multiple-file filepickers,
+        // We should deal with single-file and multiple-file filemanagers,
         // catching the exception thrown by behat_base::find() in case is not multiple
         try {
-            // Looking for the add button inside the specified filepicker.
-            $add = $this->find('css', 'div.fp-btn-add a', $exception, $filepickernode);
+            // Looking for the add button inside the specified filemanager.
+            $add = $this->find('css', 'div.fp-btn-add a', $exception, $filemanagernode);
         } catch (Exception $e) {
-            // Otherwise should be a single-file filepicker.
-            $add = $this->find('css', 'input.fp-btn-choose', $exception, $filepickernode);
+            // Otherwise should be a single-file filepicker form element.
+            $add = $this->find('css', 'input.fp-btn-choose', $exception, $filemanagernode);
         }
         $add->click();
 
@@ -184,7 +187,7 @@ class behat_files extends behat_base {
         // Avoid problems with both double and single quotes in the same string.
         $repositoryname = $this->getSession()->getSelectorsHandler()->xpathLiteral($repositoryname);
 
-        // Here we don't need to look inside the selected filepicker because there can only be one modal window.
+        // Here we don't need to look inside the selected element because there can only be one modal window.
         $repositorylink = $this->find(
             'xpath',
             "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')]" .
index c4f8a4b..d559ff4 100644 (file)
@@ -82,6 +82,11 @@ class behat_config_manager {
             $features = array_values($featurespaths);
         }
 
+        // Optionally include features from additional directories.
+        if (!empty($CFG->behat_additionalfeatures)) {
+            $features = array_merge($features, array_map("realpath", $CFG->behat_additionalfeatures));
+        }
+
         // Gets all the components with steps definitions.
         $stepsdefinitions = array();
         $steps = self::get_components_steps_definitions();
index 53c0241..e6ea562 100644 (file)
@@ -566,6 +566,9 @@ $cache = '.var_export($cache, true).';
         self::load_classes('core', "$CFG->dirroot/lib/classes");
 
         foreach (self::$subsystems as $subsystem => $fulldir) {
+            if (!$fulldir) {
+                continue;
+            }
             self::load_classes('core_'.$subsystem, "$fulldir/classes");
         }
 
index 6a303f2..6cbcbe2 100644 (file)
@@ -113,6 +113,24 @@ abstract class base implements \IteratorAggregate {
      */
     private final function __construct() {
         $this->data = array_fill_keys(self::$fields, null);
+
+        // Define some basic details.
+        $classname = get_called_class();
+        $parts = explode('\\', $classname);
+        if (count($parts) !== 3 or $parts[1] !== 'event') {
+            throw new \coding_exception("Invalid event class name '$classname', it must be defined in component\\event\\
+                    namespace");
+        }
+        $this->data['eventname'] = '\\'.$classname;
+        $this->data['component'] = $parts[0];
+
+        $pos = strrpos($parts[2], '_');
+        if ($pos === false) {
+            throw new \coding_exception("Invalid event class name '$classname', there must be at least one underscore separating
+                    object and action words");
+        }
+        $this->data['target'] = substr($parts[2], 0, $pos);
+        $this->data['action'] = substr($parts[2], $pos + 1);
     }
 
     /**
@@ -146,21 +164,6 @@ abstract class base implements \IteratorAggregate {
         // Set automatic data.
         $event->data['timecreated'] = time();
 
-        $classname = get_class($event);
-        $parts = explode('\\', $classname);
-        if (count($parts) !== 3 or $parts[1] !== 'event') {
-            throw new \coding_exception("Invalid event class name '$classname', it must be defined in component\\event\\ namespace");
-        }
-        $event->data['eventname'] = '\\'.$classname;
-        $event->data['component'] = $parts[0];
-
-        $pos = strrpos($parts[2], '_');
-        if ($pos === false) {
-            throw new \coding_exception("Invalid event class name '$classname', there must be at least one underscore separating object and action words");
-        }
-        $event->data['target'] = substr($parts[2], 0, $pos);
-        $event->data['action'] = substr($parts[2], $pos+1);
-
         // Set optional data or use defaults.
         $event->data['objectid'] = isset($data['objectid']) ? $data['objectid'] : null;
         $event->data['courseid'] = isset($data['courseid']) ? $data['courseid'] : null;
@@ -444,7 +447,9 @@ abstract class base implements \IteratorAggregate {
                 debugging('Number of event data fields must not be changed in event classes', DEBUG_DEVELOPER);
             }
             $encoded = json_encode($this->data['other']);
-            if ($encoded === false or $this->data['other'] !== json_decode($encoded, true)) {
+            // The comparison here is not set to strict as whole float numbers will be converted to integers through JSON encoding /
+            // decoding and send an unwanted debugging message.
+            if ($encoded === false or $this->data['other'] != json_decode($encoded, true)) {
                 debugging('other event data must be compatible with json encoding', DEBUG_DEVELOPER);
             }
             if ($this->data['userid'] and !is_number($this->data['userid'])) {
diff --git a/lib/classes/event/course_module_instance_list_viewed.php b/lib/classes/event/course_module_instance_list_viewed.php
new file mode 100644 (file)
index 0000000..de0e553
--- /dev/null
@@ -0,0 +1,113 @@
+<?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/>.
+
+/**
+ * Course module instance list viewed event.
+ *
+ * @package    core
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\event;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Course module instance list viewed event class.
+ *
+ * This is an abstract to guide the developers in using this event name for their events.
+ * It is intended to be used when the user viewes the list of all the instances of a module
+ * in a course. This replaces the historical 'view all' log entry generated in mod/somemod/index.php.
+ *
+ * Example:
+ *
+ *     \mod_chat\event\course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed
+ *
+ * @package    core
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class course_module_instance_list_viewed extends base{
+
+    /** @var string private var to store mod name */
+    private $modname;
+
+    /**
+     * Init method.
+     *
+     * @return void
+     */
+    protected function init() {
+        $this->data['crud'] = 'r';
+        $this->data['level'] = self::LEVEL_OTHER;
+        if (strstr($this->component, 'mod_') === false) {
+            throw new \coding_exception('The event name or namespace is invalid.');
+        } else {
+            $this->modname = str_replace('mod_', '', $this->component);
+        }
+    }
+
+    /**
+     * Returns description of what happened.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return "User with id '$this->userid' viewed instance list for module '$this->modname' in course with id
+                '$this->courseid'";
+    }
+
+    /**
+     * Return localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventcoursemoduleinstancelistviewed', 'core');
+    }
+
+    /**
+     * Get URL related to the action.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url("/mod/$this->modname/index.php", array('id' => $this->courseid));
+    }
+
+    /**
+     * Return the legacy event log data.
+     *
+     * @return array|null
+     */
+    protected function get_legacy_logdata() {
+        return array($this->courseid, $this->modname, 'view all', 'index.php?id=' . $this->courseid, '');
+    }
+
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception
+     * @return void
+     */
+    protected function validate_data() {
+        if ($this->context->contextlevel !== CONTEXT_COURSE) {
+            throw new \coding_exception('The context must be a course level context.');
+        }
+    }
+
+}
index b1b6db3..a7c2df1 100644 (file)
@@ -17,6 +17,8 @@
 /**
  * Course module instances list_viewed event.
  *
+ * This class has been deprecated, please use \core\event\course_module_instance_list_viewed.
+ *
  * @package    core
  * @copyright  2013 Frédéric Massart
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -26,56 +28,15 @@ namespace core\event;
 defined('MOODLE_INTERNAL') || die();
 
 /**
- * Course module instances list viewed event class.
- *
- * This is an abstract to guide the developers in using this event name for their events.
- * It is intended to be used when the user viewes the list of all the instances of a module
- * in a course. This replaces the historical 'view all' log entry generated in mod/somemod/index.php.
- *
- * Example:
- *
- *     \mod_chat\event\instances_list_viewed extends \core\event\course_module_instances_list_viewed
+ * This class has been deprecated, please use \core\event\course_module_instance_list_viewed.
  *
+ * @deprecated Since Moodle 2.7
  * @package    core
  * @copyright  2013 Frédéric Massart
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-abstract class course_module_instances_list_viewed extends \core\event\content_viewed {
-
-    /**
-     * Init method.
-     *
-     * @return void
-     */
-    protected function init() {
-        $this->data['crud'] = 'r';
-        $this->data['level'] = self::LEVEL_OTHER;
-    }
-
-    /**
-     * Set page detail.
-     *
-     * Override to prevent its use.
-     */
-    public function set_page_detail() {
-    }
-
-    /**
-     * Custom validation.
-     *
-     * The parent validation is ignored on purpose.
-     *
-     * @throws \coding_exception
-     * @return void
-     */
-    protected function validate_data() {
-        if ($this->context->contextlevel !== CONTEXT_COURSE) {
-           throw new \coding_exception('The context must be a course level context.');
-        }
-        // Hack to by pass the requirement of the parent class. 'view_all' was the old fashioned-way
-        // to describe the page listing all the instances of a module in a course.
-        $this->data['other']['content'] = 'view_all';
-        parent::validate_data();
-    }
-
+abstract class course_module_instances_list_viewed extends course_module_instance_list_viewed {
 }
+
+debugging('core\\event\\course_module_instances_list_viewed has been deperecated. Please use
+        core\\event\\course_module_instance_list_viewed instead', DEBUG_DEVELOPER);
index f3d3582..2277627 100644 (file)
@@ -81,6 +81,18 @@ class checker {
         }
     }
 
+    /**
+     * Is automatic deployment enabled?
+     *
+     * @return bool
+     */
+    public function enabled() {
+        global $CFG;
+
+        // The feature can be prohibited via config.php.
+        return empty($CFG->disableupdateautodeploy);
+    }
+
     /**
      * Returns the timestamp of the last execution of {@link fetch()}
      *
index 89c47d6..0eccb8e 100644 (file)
@@ -32,9 +32,6 @@ defined('MOODLE_INTERNAL') || die();
  */
 class deployer {
 
-    const HTTP_PARAM_PREFIX     = 'updteautodpldata_';  // Hey, even Google has not heard of such a prefix! So it MUST be safe :-p.
-    const HTTP_PARAM_CHECKER    = 'datapackagesize';    // Name of the parameter that holds the number of items in the received data items.
-
     /** @var \core\update\deployer holds the singleton instance */
     protected static $singletoninstance;
     /** @var moodle_url URL of a page that includes the deployer UI */
@@ -207,9 +204,19 @@ class deployer {
             throw new coding_exception('Illegal method call - deployer not initialized.');
         }
 
-        $params = $this->data_to_params(array(
-            'updateinfo' => (array)$info,   // See http://www.php.net/manual/en/language.types.array.php#language.types.array.casting .
-        ));
+        $params = array(
+            'updateaddon' => $info->component,
+            'version' =>$info->version,
+            'sesskey' => sesskey(),
+        );
+
+        // Append some our own data.
+        if (!empty($this->callerurl)) {
+            $params['callerurl'] = $this->callerurl->out(false);
+        }
+        if (!empty($this->returnurl)) {
+            $params['returnurl'] = $this->returnurl->out(false);
+        }
 
         $widget = new \single_button(
             new moodle_url($this->callerurl, $params),
@@ -301,25 +308,46 @@ class deployer {
      * @return array
      */
     public function submitted_data() {
+        $component = optional_param('updateaddon', '', PARAM_COMPONENT);
+        $version = optional_param('version', '', PARAM_RAW);
+        if (!$component or !$version) {
+            return false;
+        }
+
+        $plugininfo = \core_plugin_manager::instance()->get_plugin_info($component);
+        if (!$plugininfo) {
+            return false;
+        }
 
-        $data = $this->params_to_data($_POST);
+        if ($plugininfo->is_standard()) {
+            return false;
+        }
 
-        if (empty($data) or empty($data[self::HTTP_PARAM_CHECKER])) {
+        if (!$updates = $plugininfo->available_updates()) {
             return false;
         }
 
-        if (!empty($data['updateinfo']) and is_object($data['updateinfo'])) {
-            $updateinfo = $data['updateinfo'];
-            if (!empty($updateinfo->component) and !empty($updateinfo->version)) {
-                $data['updateinfo'] = new info($updateinfo->component, (array)$updateinfo);
+        $info = null;
+        foreach ($updates as $update) {
+            if ($update->version == $version) {
+                $info = $update;
+                break;
             }
         }
+        if (!$info) {
+            return false;
+        }
 
-        if (!empty($data['callerurl'])) {
+        $data = array(
+            'updateaddon' => $component,
+            'updateinfo'  => $info,
+            'callerurl'   => optional_param('callerurl', null, PARAM_URL),
+            'returnurl'   => optional_param('returnurl', null, PARAM_URL),
+        );
+        if ($data['callerurl']) {
             $data['callerurl'] = new moodle_url($data['callerurl']);
         }
-
-        if (!empty($data['returnurl'])) {
+        if ($data['callerurl']) {
             $data['returnurl'] = new moodle_url($data['returnurl']);
         }
 
@@ -421,60 +449,6 @@ class deployer {
 
     /* === End of external API === */
 
-    /**
-     * Prepares an array of HTTP parameters that can be passed to another page.
-     *
-     * @param array|object $data associative array or an object holding the data, data JSON-able
-     * @return array suitable as a param for moodle_url
-     */
-    protected function data_to_params($data) {
-
-        // Append some our own data.
-        if (!empty($this->callerurl)) {
-            $data['callerurl'] = $this->callerurl->out(false);
-        }
-        if (!empty($this->returnurl)) {
-            $data['returnurl'] = $this->returnurl->out(false);
-        }
-
-        // Finally append the count of items in the package.
-        $data[self::HTTP_PARAM_CHECKER] = count($data);
-
-        // Generate params.
-        $params = array();
-        foreach ($data as $name => $value) {
-            $transname = self::HTTP_PARAM_PREFIX.$name;
-            $transvalue = json_encode($value);
-            $params[$transname] = $transvalue;
-        }
-
-        return $params;
-    }
-
-    /**
-     * Converts HTTP parameters passed to the script into native PHP data
-     *
-     * @param array $params such as $_REQUEST or $_POST
-     * @return array data passed for this class
-     */
-    protected function params_to_data(array $params) {
-
-        if (empty($params)) {
-            return array();
-        }
-
-        $data = array();
-        foreach ($params as $name => $value) {
-            if (strpos($name, self::HTTP_PARAM_PREFIX) === 0) {
-                $realname = substr($name, strlen(self::HTTP_PARAM_PREFIX));
-                $realvalue = json_decode($value);
-                $data[$realname] = $realvalue;
-            }
-        }
-
-        return $data;
-    }
-
     /**
      * Returns a random string to be used as a filename of the password storage.
      *
@@ -511,7 +485,13 @@ class deployer {
         $directory = core_component::get_plugin_directory($plugintype, $pluginname);
 
         if (is_null($directory)) {
-            throw new coding_exception('Unknown component location', $component);
+            // Plugin unknown, most probably deleted or missing during upgrade,
+            // look at the parent directory instead because they might want to install it.
+            $plugintypes = core_component::get_plugin_types();
+            if (!isset($plugintypes[$plugintype])) {
+                throw new coding_exception('Unknown component location', $component);
+            }
+            $directory = $plugintypes[$plugintype];
         }
 
         return $this->directory_writable($directory);
index 3782b5c..7e0d40d 100644 (file)
@@ -500,17 +500,17 @@ class core_useragent {
         } else {
             return false;
         }
-        $compat_view = false;
+        $compatview = false;
         // IE8 and later versions may pretend to be IE7 for intranet sites, use Trident version instead,
         // the Trident should always describe the capabilities of IE in any emulation mode.
         if ($browser === '7.0' and preg_match("/Trident\/([0-9\.]+)/", $useragent, $match)) {
-            $compat_view = true;
+            $compatview = true;
             $browser = $match[1] + 4; // NOTE: Hopefully this will work also for future IE versions.
         }
         $browser = round($browser, 1);
         return array(
             'version'    => $browser,
-            'compatview' => $compat_view
+            'compatview' => $compatview
         );
     }
 
@@ -863,6 +863,9 @@ class core_useragent {
             } else if (self::is_ie() and !self::check_ie_version('9')) {
                 // IE < 9 doesn't support SVG. Say no.
                 $instance->supportssvg = false;
+            } else if (self::is_ie() and !self::check_ie_version('10') and self::check_ie_compatibility_view()) {
+                // IE 9 Compatibility View doesn't support SVG. Say no.
+                $instance->supportssvg = false;
             } else if (preg_match('#Android +[0-2]\.#', $instance->useragent)) {
                 // Android < 3 doesn't support SVG. Say no.
                 $instance->supportssvg = false;
index b58d1ee..394a12e 100644 (file)
@@ -558,46 +558,6 @@ function get_file_url($path, $options=null, $type='coursefile') {
     return $ffurl;
 }
 
-/**
- * @deprecated use get_string("pluginname", "auth_[PLUINNAME]") instead.
- * @todo remove completely in MDL-40517
- */
-function auth_get_plugin_title($authtype) {
-    throw new coding_exception('Function auth_get_plugin_title() is deprecated, please use standard get_string("pluginname", "auth_'.$authtype.'")!');
-}
-
-/**
- * @deprecated use indivividual enrol plugin settings instead
- * @todo remove completely in MDL-40517
- */
-function get_default_course_role($course) {
-    throw new coding_exception('get_default_course_role() can not be used any more, please use enrol plugin settings instead!');
-}
-
-/**
- * @deprecated use get_string_manager()->get_list_of_translations() instead.
- * @todo remove completely in MDL-40517
- */
-function get_list_of_languages($refreshcache=false, $returnall=false) {
-    throw new coding_exception('get_list_of_languages() can not be used any more, please use get_string_manager()->get_list_of_translations() instead.');
-}
-
-/**
- * @deprecated use get_string_manager()->get_list_of_currencies() instead.
- * @todo remove completely in MDL-40517
- */
-function get_list_of_currencies() {
-    throw new coding_exception('get_list_of_currencies() can not be used any more, please use get_string_manager()->get_list_of_currencies() instead.');
-}
-
-/**
- * @deprecated use get_string_manager()->get_list_of_countries() instead.
- * @todo remove completely in MDL-40517
- */
-function get_list_of_countries() {
-    throw new coding_exception('get_list_of_countries() can not be used any more, please use get_string_manager()->get_list_of_countries() instead.');
-}
-
 /**
  * Return all course participant for a given course
  *
@@ -655,56 +615,6 @@ function get_recent_enrolments($courseid, $timestart) {
     return $DB->get_records_sql($sql, $params);
 }
 
-########### FROM weblib.php ##########################################################################
-
-/**
- * @deprecated use $OUTPUT->box() instead.
- * @todo remove completely in MDL-40517
- */
-function print_simple_box($message, $align='', $width='', $color='', $padding=5, $class='generalbox', $id='', $return=false) {
-    throw new coding_exception('print_simple_box can not be used any more. Please use $OUTPUT->box() instead');
-}
-
-/**
- * @deprecated use $OUTPUT->box_start instead.
- * @todo remove completely in MDL-40517
- */
-function print_simple_box_start($align='', $width='', $color='', $padding=5, $class='generalbox', $id='', $return=false) {
-    throw new coding_exception('print_simple_box_start can not be used any more. Please use $OUTPUT->box_start instead');
-}
-
-/**
- * @deprecated use $OUTPUT->box_end instead.
- * @todo remove completely in MDL-40517
- */
-function print_simple_box_end($return=false) {
-    throw new coding_exception('print_simple_box_end can not be used any more. Please use $OUTPUT->box_end instead');
-}
-
-/**
- * @deprecated the urltolink filter now does this job.
- * @todo remove completely in MDL-40517
- */
-function convert_urls_into_links($text) {
-    throw new coding_exception('convert_urls_into_links() can not be used any more and replaced by the urltolink filter');
-}
-
-/**
- * @deprecated use the emoticon_manager class instead.
- * @todo remove completely in MDL-40517
- */
-function get_emoticons_list_for_help_file() {
-    throw new coding_exception('get_emoticons_list_for_help_file() can not be used any more, use the new emoticon_manager API instead');
-}
-
-/**
- * @deprecated use emoticon filter now does this job.
- * @todo remove completely in MDL-40517
- */
-function replace_smilies(&$text) {
-    throw new coding_exception('replace_smilies() can not be used any more and replaced with the emoticon filter.');
-}
-
 /**
  * @deprecated use clean_param($string, PARAM_FILE) instead.
  * @todo final deprecation of this function in MDL-40607
@@ -984,13 +894,6 @@ function error($message, $link='') {
 }
 
 
-/**
- * @deprecated use $PAGE->requires->js_module() instead.
- */
-function require_js($lib) {
-    throw new coding_exception('require_js() was removed, use new JS api');
-}
-
 /**
  * @deprecated use $PAGE->theme->name instead.
  * @todo final deprecation of this function in MDL-40607
@@ -1032,54 +935,6 @@ function skip_main_destination() {
     return $OUTPUT->skip_link_target();
 }
 
-/**
- * @deprecated use $OUTPUT->heading() instead.
- * @todo remove completely in MDL-40517
- */
-function print_headline($text, $size=2, $return=false) {
-    throw new coding_exception('print_headline() can not be used any more. Please use $OUTPUT->heading() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->heading() instead.
- * @todo remove completely in MDL-40517
- */
-function print_heading($text, $deprecated = '', $size = 2, $class = 'main', $return = false, $id = '') {
-    throw new coding_exception('print_heading() can not be used any more. Please use $OUTPUT->heading() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->heading() instead.
- * @todo remove completely in MDL-40517
- */
-function print_heading_block($heading, $class='', $return=false) {
-    throw new coding_exception('print_heading_with_block() can not be used any more. Please use $OUTPUT->heading() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->box() instead.
- * @todo remove completely in MDL-40517
- */
-function print_box($message, $classes='generalbox', $ids='', $return=false) {
-    throw new coding_exception('print_box() can not be used any more. Please use $OUTPUT->box() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->box_start() instead.
- * @todo remove completely in MDL-40517
- */
-function print_box_start($classes='generalbox', $ids='', $return=false) {
-    throw new coding_exception('print_box_start() can not be used any more. Please use $OUTPUT->box_start() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->box_end() instead.
- * @todo remove completely in MDL-40517
- */
-function print_box_end($return=false) {
-    throw new coding_exception('print_box_end() can not be used any more. Please use $OUTPUT->box_end() instead.');
-}
-
 /**
  * Print a message in a standard themed container.
  *
@@ -1134,14 +989,6 @@ function print_container_start($clearfix=false, $classes='', $idbase='', $return
     }
 }
 
-/**
- * @deprecated do not use any more, is not automatic
- * @todo remove completely in MDL-40517
- */
-function check_theme_arrows() {
-    throw new coding_exception('check_theme_arrows() has been deprecated, do not use it anymore, it is now automatic.');
-}
-
 /**
  * Simple function to end a container (see above)
  *
@@ -1327,22 +1174,6 @@ function print_header_simple($title='', $heading='', $navigation='', $focus='',
     }
 }
 
-/**
- * @deprecated use $OUTPUT->footer() instead.
- * @todo remove completely in MDL-40517
- */
-function print_footer($course = NULL, $usercourse = NULL, $return = false) {
-    throw new coding_exception('print_footer() cant be used anymore. Please use $OUTPUT->footer() instead.');
-}
-
-/**
- * @deprecated use theme layouts instead.
- * @todo remove completely in MDL-40517
- */
-function user_login_string($course='ignored', $user='ignored') {
-    throw new coding_exception('user_login_info() cant be used anymore. User login info is now handled via themes layouts.');
-}
-
 /**
  * Prints a nice side block with an optional header.  The content can either
  * be a block of HTML or a list of text with optional icons.
@@ -1391,90 +1222,6 @@ function print_side_block($heading='', $content='', $list=NULL, $icons=NULL, $fo
     echo $OUTPUT->block($bc, BLOCK_POS_LEFT); // POS LEFT may be wrong, but no way to get a better guess here.
 }
 
-/**
- * @deprecated blocks are now printed by theme.
- * @todo remove completely in MDL-40517
- */
-function blocks_have_content(&$blockmanager, $region) {
-    throw new coding_exception('blocks_have_content() can no longer be used. Blocks are now printed by the theme.');
-}
-
-/**
- * @deprecated blocks are now printed by the theme.
- * @todo remove completely in MDL-40517
- */
-function blocks_print_group($page, $blockmanager, $region) {
-    throw new coding_exception('function blocks_print_group() can no longer be used. Blocks are now printed by the theme.');
-}
-
-/**
- * @deprecated blocks are now printed by the theme.
- * @todo remove completely in MDL-40517
- */
-function blocks_setup(&$page, $pinned = BLOCKS_PINNED_FALSE) {
-    throw new coding_exception('blocks_print_group() can no longer be used. Blocks are now printed by the theme.');
-}
-
-/**
- * @deprecated Layout is now controlled by the theme.
- * @todo remove completely in MDL-40517
- */
-function blocks_preferred_width($instances) {
-    throw new coding_exception('blocks_print_group() can no longer be used. Blocks are now printed by the theme.');
-}
-
-/**
- * @deprecated use html_writer::table() instead.
- * @todo remove completely in MDL-40517
- */
-function print_table($table, $return=false) {
-    throw new coding_exception('print_table() can no longer be used. Use html_writer::table() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->action_link() instead (note: popups are discouraged for accesibility reasons)
- * @todo remove completely in MDL-40517
- */
-function link_to_popup_window ($url, $name=null, $linkname=null, $height=400, $width=500, $title=null, $options=null, $return=false) {
-    throw new coding_exception('link_to_popup_window() can no longer be used. Please to use $OUTPUT->action_link() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->single_button() instead.
- * @todo remove completely in MDL-40517
- */
-function button_to_popup_window ($url, $name=null, $linkname=null,
-                                 $height=400, $width=500, $title=null, $options=null, $return=false,
-                                 $id=null, $class=null) {
-    throw new coding_exception('button_to_popup_window() can no longer be used. Please use $OUTPUT->single_button() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->single_button() instead.
- * @todo remove completely in MDL-40517
- */
-function print_single_button($link, $options, $label='OK', $method='get', $notusedanymore='',
-        $return=false, $tooltip='', $disabled = false, $jsconfirmmessage='', $formid = '') {
-
-    throw new coding_exception('print_single_button() can no longer be used. Please use $OUTPUT->single_button() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->spacer() instead.
- * @todo remove completely in MDL-40517
- */
-function print_spacer($height=1, $width=1, $br=true, $return=false) {
-    throw new coding_exception('print_spacer() can no longer be used. Please use $OUTPUT->spacer() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->user_picture() instead.
- * @todo remove completely in MDL-40517
- */
-function print_user_picture($user, $courseid, $picture=NULL, $size=0, $return=false, $link=true, $target='', $alttext=true) {
-    throw new coding_exception('print_user_picture() can no longer be used. Please use $OUTPUT->user_picture($user, array(\'courseid\'=>$courseid) instead.');
-}
-
 /**
  * Prints a basic textarea field.
  *
@@ -1533,24 +1280,6 @@ function print_textarea($unused, $rows, $cols, $width, $height, $name, $value=''
     echo $str;
 }
 
-
-/**
- * Print a help button.
- *
- * @deprecated since Moodle 2.0
- */
-function helpbutton($page, $title, $module='moodle', $image=true, $linktext=false, $text='', $return=false, $imagetext='') {
-    throw new coding_exception('helpbutton() can not be used any more, please see $OUTPUT->help_icon().');
-}
-
-/**
- * @deprecated this is now handled by text editors
- * @todo remove completely in MDL-40517
- */
-function emoticonhelpbutton($form, $field, $return = false) {
-    throw new coding_exception('emoticonhelpbutton() was removed, new text editors will implement this feature');
-}
-
 /**
  * Returns a string of html with an image of a help icon linked to a help page on a number of help topics.
  * Should be used only with htmleditor or textarea.
@@ -1642,32 +1371,6 @@ function print_arrow($direction='up', $strsort=null, $return=false) {
     }
 }
 
-/**
- * Returns a string containing a link to the user documentation.
- * Also contains an icon by default. Shown to teachers and admin only.
- *
- * @deprecated since Moodle 2.0
- */
-function doc_link($path='', $text='', $iconpath='ignored') {
-    throw new coding_exception('doc_link() can not be used any more, please see $OUTPUT->doc_link().');
-}
-
-/**
- * @deprecated use $OUTPUT->render($pagingbar) instead.
- * @todo remove completely in MDL-40517
- */
-function print_paging_bar($totalcount, $page, $perpage, $baseurl, $pagevar='page',$nocurr=false, $return=false) {
-    throw new coding_exception('print_paging_bar() can not be used any more. Please use $OUTPUT->render($pagingbar) instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->confirm($message, $buttoncontinue, $buttoncancel) instead.
- * @todo remove completely in MDL-40517
- */
-function notice_yesno($message, $linkyes, $linkno, $optionsyes=NULL, $optionsno=NULL, $methodyes='post', $methodno='post') {
-    throw new coding_exception('notice_yesno() can not be used any more. Please use $OUTPUT->confirm($message, $buttoncontinue, $buttoncancel) instead.');
-}
-
 /**
  * Given an array of values, output the HTML for a select element with those options.
  *
@@ -1724,24 +1427,6 @@ function choose_from_menu ($options, $name, $selected='', $nothing='choose', $sc
     }
 }
 
-/**
- * @deprecated use html_writer::select_yes_no() instead.
- * @todo remove completely in MDL-40517
- */
-function choose_from_menu_yesno($name, $selected, $script = '', $return = false, $disabled = false, $tabindex = 0) {
-    throw new coding_exception('choose_from_menu_yesno() can not be used anymore. Please use html_writerselect_yes_no() instead.');
-}
-
-/**
- * @deprecated use html_writer::select() instead.
- * @todo remove completely in MDL-40517
- */
-function choose_from_menu_nested($options,$name,$selected='',$nothing='choose',$script = '',
-                                 $nothingvalue=0,$return=false,$disabled=false,$tabindex=0) {
-
-    throw new coding_exception('choose_from_menu_nested() can not be used any more. Please use html_writer::select() instead.');
-}
-
 /**
  * Prints a help button about a scale
  *
@@ -1768,48 +1453,6 @@ function print_scale_menu_helpbutton($courseid, $scale, $return=false) {
     }
 }
 
-/**
- * @deprecated use html_writer::select_time() instead
- * @todo remove completely in MDL-40517
- */
-function print_time_selector($hour, $minute, $currenttime=0, $step=5, $return=false) {
-    throw new moodle_exception('print_time_selector() can not be used any more . Please use html_writer::select_time() instead.');
-}
-
-/**
- * @deprecated please use html_writer::select_time instead
- * @todo remove completely in MDL-40517
- */
-function print_date_selector($day, $month, $year, $currenttime=0, $return=false) {
-    throw new coding_exception('print_date_selector() can not be used any more. Please use html_writer::select_time() instead.');
-}
-
-/**
- * Implements a complete little form with a dropdown menu.
- *
- * @deprecated since Moodle 2.0
- */
-function popup_form($baseurl, $options, $formid, $selected='', $nothing='choose', $help='', $helptext='', $return=false,
-    $targetwindow='self', $selectlabel='', $optionsextra=NULL, $submitvalue='', $disabled=false, $showbutton=false) {
-        throw new coding_exception('popup_form() can not be used any more, please see $OUTPUT->single_select or $OUTPUT->url_select().');
-}
-
-/**
- * @deprecated use $OUTPUT->close_window_button() instead.
- * @todo remove completely in MDL-40517
- */
-function close_window_button($name='closewindow', $return=false, $reloadopener = false) {
-    throw new coding_exception('close_window_button() can not be used any more. Use $OUTPUT->close_window_button() instead.');
-}
-
-/**
- * @deprecated use html_writer instead.
- * @todo remove completely in MDL-40517
- */
-function choose_from_radio ($options, $name, $checked='', $return=false) {
-    throw new coding_exception('choose_from_radio() can not be used any more. Please use html_writer instead.');
-}
-
 /**
  * Display an standard html checkbox with an optional label
  *
@@ -1847,32 +1490,6 @@ function print_checkbox($name, $value, $checked = true, $label = '', $alt = '',
 
 }
 
-/**
- * @deprecated use mforms or html_writer instead.
- * @todo remove completely in MDL-40517
- */
-function print_textfield($name, $value, $alt = '', $size=50, $maxlength=0, $return=false) {
-    throw new coding_exception('print_textfield() can not be used anymore. Please use mforms or html_writer instead.');
-}
-
-
-/**
- * @deprecated use $OUTPUT->heading_with_help() instead
- * @todo remove completely in MDL-40517
- */
-function print_heading_with_help($text, $helppage, $module='moodle', $icon=false, $return=false) {
-    throw new coding_exception('print_heading_with_help() can not be used anymore. Please use $OUTPUT->heading_with_help() instead.');
-}
-
-/**
- * @deprecated use $OUTPUT->edit_button() instead.
- * @todo remove completely in MDL-40517
- */
-function update_tag_button($tagid) {
-    throw new coding_exception('update_tag_button() can not be used any more. Please $OUTPUT->edit_button(moodle_url) instead.');
-}
-
-
 /**
  * Prints the 'update this xxx' button that appears on module pages.
  *
@@ -1900,14 +1517,6 @@ function update_module_button($cmid, $ignored, $string) {
     }
 }
 
-/**
- * @deprecated use $OUTPUT->edit_button() instead.
- * @todo remove completely in MDL-40517
- */
-function update_course_icon($courseid) {
-    throw new coding_exception('update_course_button() can not be used anymore. Please use $OUTPUT->edit_button(moodle_url) instead.');
-}
-
 /**
  * Prints breadcrumb trail of links, called in theme/-/header.html
  *
@@ -2004,7 +1613,7 @@ function build_navigation($extranavlinks, $cm = null) {
 
 /**
  * @deprecated not relevant with global navigation in Moodle 2.x+
- * @todo remove completely in MDL-40517
+ * @todo remove completely in MDL-40607
  */
 function navmenu($course, $cm=NULL, $targetwindow='self') {
     // This function has been deprecated with the creation of the global nav in
@@ -2014,30 +1623,6 @@ function navmenu($course, $cm=NULL, $targetwindow='self') {
     return '';
 }
 
-/**
- * @deprecated use the settings block instead.
- * @todo remove completely in MDL-40517
- */
-function switchroles_form($courseid) {
-    throw new coding_exception('switchroles_form() can not be used any more. The global settings block does this job.');
-}
-
-/**
- * @deprecated Please use normal $OUTPUT->header() instead
- * @todo remove completely in MDL-40517
- */
-function admin_externalpage_print_header($focus='') {
-    throw new coding_exception('admin_externalpage_print_header can not be used any more. Please $OUTPUT->header() instead.');
-}
-
-/**
- * @deprecated Please use normal $OUTPUT->footer() instead
- * @todo remove completely in MDL-40517
- */
-function admin_externalpage_print_footer() {
-    throw new coding_exception('admin_externalpage_print_footer can not be used anymore Please $OUTPUT->footer() instead.');
-}
-
 /// CALENDAR MANAGEMENT  ////////////////////////////////////////////////////////////////
 
 
@@ -2151,13 +1736,6 @@ function show_event($event) {
     return $event->toggle_visibility(true);
 }
 
-/**
- * @deprecated Use core_text::strtolower($text) instead.
- */
-function moodle_strtolower($string, $encoding='') {
-    throw new coding_exception('moodle_strtolower() cannot be used any more. Please use core_text::strtolower() instead.');
-}
-
 /**
  * Original singleton helper function, please use static methods instead,
  * ex: core_text::convert()
@@ -3985,12 +3563,6 @@ function convert_tabrows_to_tree($tabrows, $selected, $inactive, $activated) {
     return $subtree;
 }
 
-/**
- * @deprecated since Moodle 2.3
- */
-function move_section($course, $section, $move) {
-    throw new coding_exception('move_section() can not be used any more, please see move_section_to().');
-}
 /**
  * Can handle rotated text. Whether it is safe to use the trickery in textrotate.js.
  *
@@ -4052,22 +3624,6 @@ function get_context_instance_by_id($id, $strictness = IGNORE_MISSING) {
     return context::instance_by_id($id, $strictness);
 }
 
-/**
- * @deprecated since Moodle 2.2
- * @see load_temp_course_role()
- */
-function load_temp_role($context, $roleid, array $accessdata) {
-    throw new coding_exception('load_temp_role() can not be used any more, please use load_temp_course_role()');
-}
-
-/**
- * @deprecated since Moodle 2.2
- * @see remove_temp_course_roles()
- */
-function remove_temp_roles($context, array $accessdata) {
-    throw new coding_exception('remove_temp_roles() can not be used any more, please use remove_temp_course_roles()');
-}
-
 /**
  * Returns system context or null if can not be created yet.
  *
@@ -4526,14 +4082,6 @@ function get_related_contexts_string(context $context) {
     }
 }
 
-/**
- * @deprecated since Moodle 2.0 - use $PAGE->user_is_editing() instead.
- * @see moodle_page->user_is_editing()
- */
-function isediting() {
-    throw new coding_exception('isediting() can not be used any more, please use $PAGE->user_is_editing() instead.');
-}
-
 /**
  * Get a list of all the plugins of a given type that contain a particular file.
  *
index 156d39c..de17fc8 100644 (file)
@@ -2126,6 +2126,52 @@ abstract class moodle_database {
         return '';
     }
 
+    /**
+     * Does this driver support tool_replace?
+     *
+     * @since 2.6.1
+     * @return bool
+     */
+    public function replace_all_text_supported() {
+        return false;
+    }
+
+    /**
+     * Replace given text in all rows of column.
+     *
+     * @since 2.6.1
+     * @param string $table name of the table
+     * @param database_column_info $column
+     * @param string $search
+     * @param string $replace
+     */
+    public function replace_all_text($table, database_column_info $column, $search, $replace) {
+        if (!$this->replace_all_text_supported()) {
+            return;
+        }
+
+        // NOTE: override this methods if following standard compliant SQL
+        //       does not work for your driver.
+
+        $columnname = $column->name;
+        $sql = "UPDATE {".$table."}
+                       SET $columnname = REPLACE($columnname, ?, ?)
+                     WHERE $columnname IS NOT NULL";
+
+        if ($column->meta_type === 'X') {
+            $this->execute($sql, array($search, $replace));
+
+        } else if ($column->meta_type === 'C') {
+            if (core_text::strlen($search) < core_text::strlen($replace)) {
+                $colsize = $column->max_length;
+                $sql = "UPDATE {".$table."}
+                       SET $columnname = SUBSTRING(REPLACE($columnname, ?, ?), 1, $colsize)
+                     WHERE $columnname IS NOT NULL";
+            }
+            $this->execute($sql, array($search, $replace));
+        }
+    }
+
     /**
      * Checks and returns true if transactions are supported.
      *
index ec4e983..cc682e5 100644 (file)
@@ -1252,6 +1252,16 @@ s only returning name of SQL substring function, it now requires all parameters.
         }
     }
 
+    /**
+     * Does this driver support tool_replace?
+     *
+     * @since 2.6.1
+     * @return bool
+     */
+    public function replace_all_text_supported() {
+        return true;
+    }
+
     public function session_lock_supported() {
         return true;
     }
index 5196484..33d07b9 100644 (file)
@@ -1392,6 +1392,16 @@ class mysqli_native_moodle_database extends moodle_database {
         return ' CAST(' . $fieldname . ' AS SIGNED) ';
     }
 
+    /**
+     * Does this driver support tool_replace?
+     *
+     * @since 2.6.1
+     * @return bool
+     */
+    public function replace_all_text_supported() {
+        return true;
+    }
+
     public function session_lock_supported() {
         return true;
     }
index 3754d9b..f4cf21d 100644 (file)
@@ -1216,6 +1216,16 @@ class pgsql_native_moodle_database extends moodle_database {
         return $positivematch ? '~*' : '!~*';
     }
 
+    /**
+     * Does this driver support tool_replace?
+     *
+     * @since 2.6.1
+     * @return bool
+     */
+    public function replace_all_text_supported() {
+        return true;
+    }
+
     public function session_lock_supported() {
         return true;
     }
index 6b9bce2..093cda6 100644 (file)
@@ -1314,6 +1314,16 @@ class sqlsrv_native_moodle_database extends moodle_database {
         }
     }
 
+    /**
+     * Does this driver support tool_replace?
+     *
+     * @since 2.6.1
+     * @return bool
+     */
+    public function replace_all_text_supported() {
+        return true;
+    }
+
     public function session_lock_supported() {
         return true;
     }
index 146f615..d44714e 100644 (file)
@@ -4234,6 +4234,64 @@ class core_dml_testcase extends database_driver_testcase {
         $this->assertCount($currentcount, $results);
     }
 
+    public function test_replace_all_text() {
+        $DB = $this->tdb;
+        $dbman = $DB->get_manager();
+
+        if (!$DB->replace_all_text_supported()) {
+            $this->markTestSkipped($DB->get_name().' does not support replacing of texts');
+        }
+
+        $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('name', XMLDB_TYPE_CHAR, '20', null, null);
+        $table->add_field('intro', XMLDB_TYPE_TEXT, 'big', null, null);
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+        $dbman->create_table($table);
+
+        $id1 = (string)$DB->insert_record($tablename, array('name' => null, 'intro' => null));
+        $id2 = (string)$DB->insert_record($tablename, array('name' => '', 'intro' => ''));
+        $id3 = (string)$DB->insert_record($tablename, array('name' => 'xxyy', 'intro' => 'vvzz'));
+        $id4 = (string)$DB->insert_record($tablename, array('name' => 'aa bb aa bb', 'intro' => 'cc dd cc aa'));
+        $id5 = (string)$DB->insert_record($tablename, array('name' => 'kkllll', 'intro' => 'kkllll'));
+
+        $expected = $DB->get_records($tablename, array(), 'id ASC');
+
+        $columns = $DB->get_columns($tablename);
+
+        $DB->replace_all_text($tablename, $columns['name'], 'aa', 'o');
+        $result = $DB->get_records($tablename, array(), 'id ASC');
+        $expected[$id4]->name = 'o bb o bb';
+        $this->assertEquals($expected, $result);
+
+        $DB->replace_all_text($tablename, $columns['intro'], 'aa', 'o');
+        $result = $DB->get_records($tablename, array(), 'id ASC');
+        $expected[$id4]->intro = 'cc dd cc o';
+        $this->assertEquals($expected, $result);
+
+        $DB->replace_all_text($tablename, $columns['name'], '_', '*');
+        $DB->replace_all_text($tablename, $columns['name'], '?', '*');
+        $DB->replace_all_text($tablename, $columns['name'], '%', '*');
+        $DB->replace_all_text($tablename, $columns['intro'], '_', '*');
+        $DB->replace_all_text($tablename, $columns['intro'], '?', '*');
+        $DB->replace_all_text($tablename, $columns['intro'], '%', '*');
+        $result = $DB->get_records($tablename, array(), 'id ASC');
+        $this->assertEquals($expected, $result);
+
+        $long = '1234567890123456789';
+        $DB->replace_all_text($tablename, $columns['name'], 'kk', $long);
+        $result = $DB->get_records($tablename, array(), 'id ASC');
+        $expected[$id5]->name = core_text::substr($long.'llll', 0, 20);
+        $this->assertEquals($expected, $result);
+
+        $DB->replace_all_text($tablename, $columns['intro'], 'kk', $long);
+        $result = $DB->get_records($tablename, array(), 'id ASC');
+        $expected[$id5]->intro = $long.'llll';
+        $this->assertEquals($expected, $result);
+    }
+
     public function test_onelevel_commit() {
         $DB = $this->tdb;
         $dbman = $DB->get_manager();
index f6c223d..bea6fc1 100644 (file)
@@ -65,7 +65,7 @@ class tinymce_managefiles_manage_form extends moodleform {
         $mform->registerNoSubmitButton('refresh');
 
         $mform->addElement('static', '', '',
-                html_writer::tag('span', '', array('class' => 'managefilesstatus')));
+                html_writer::tag('div', '', array('class' => 'managefilesstatus')));
 
         $mform->addElement('header', 'deletefiles', get_string('unusedfilesheader', 'tinymce_managefiles'));
         $mform->addElement('static', '', '',
index 13e852d..c698bf0 100644 (file)
@@ -993,7 +993,13 @@ function groups_cache_groupdata($courseid, cache $cache = null) {
 
     if (!empty($groupings)) {
         // Finally get the mappings between the two.
-        $mappings = $DB->get_records_list('groupings_groups', 'groupingid', array_keys($groupings), '', 'id,groupingid,groupid');
+        list($insql, $params) = $DB->get_in_or_equal(array_keys($groupings));
+        $mappings = $DB->get_records_sql("
+                SELECT gg.id, gg.groupingid, gg.groupid
+                  FROM {groupings_groups} gg
+                  JOIN {groups} g ON g.id = gg.groupid
+                 WHERE gg.groupingid $insql
+              ORDER BY g.name ASC", $params);
     } else {
         $mappings = array();
     }
index 7e61808..748bddf 100644 (file)
@@ -4492,6 +4492,10 @@ class settings_navigation_ajax extends settings_navigation {
             return false;
         }
         $this->load_administration_settings();
+
+        // Check if local plugins is adding node to site admin.
+        $this->load_local_plugin_settings();
+
         $this->initialised = true;
     }
 }
index d530d79..e0648ff 100644 (file)
@@ -1261,13 +1261,8 @@ class page_requirements_manager {
         }
 
         $baserollups = array(
-            'rollup/' . $CFG->yui3version . '/yui-moodlesimple' . $yuiformat . '.js',
-        );
-        // The reason for separate rollups is that the Y = YUI().use('*') call is run async and
-        // it gets it's knickers in a twist. Putting it in a separate <script>
-        // to the moodle rollup means that it's completed before the moodle one starts.
-        $moodlerollups = array(
-            'rollup/' . $jsrev . '/mcore' . $format . '.js',
+            'rollup/' . $CFG->yui3version . "/yui-moodlesimple{$yuiformat}.js",
+            'rollup/' . $jsrev . "/mcore{$format}.js",
         );
 
         if ($this->yui3loader->combine) {
@@ -1278,11 +1273,9 @@ class page_requirements_manager {
                 }
                 $code .= '<link rel="stylesheet" type="text/css" href="'.$this->yui3loader->comboBase.implode('&amp;', $modules).'" />';
             }
-            $code .= '<link rel="stylesheet" type="text/css" href="'.$this->yui3loader->local_comboBase.'rollup/'.$CFG->yui3version.'/yui-moodlesimple-min.css" />';
+            $code .= '<link rel="stylesheet" type="text/css" href="'.$this->yui3loader->local_comboBase.'rollup/'.$CFG->yui3version.'/yui-moodlesimple' . $yuiformat . '.css" />';
             $code .= '<script type="text/javascript" src="'.$this->yui3loader->local_comboBase
                     . implode('&amp;', $baserollups) . '"></script>';
-            $code .= '<script type="text/javascript" src="'.$this->yui3loader->local_comboBase
-                    . implode('&amp;', $moodlerollups) . '"></script>';
 
         } else {
             if (!empty($page->theme->yuicssmodules)) {
@@ -1290,13 +1283,10 @@ class page_requirements_manager {
                     $code .= '<link rel="stylesheet" type="text/css" href="'.$this->yui3loader->base.$module.'/'.$module.'-min.css" />';
                 }
             }
-            $code .= '<link rel="stylesheet" type="text/css" href="'.$this->yui3loader->local_comboBase.'rollup/'.$CFG->yui3version.'/yui-moodlesimple-min.css" />';
+            $code .= '<link rel="stylesheet" type="text/css" href="'.$this->yui3loader->local_comboBase.'rollup/'.$CFG->yui3version.'/yui-moodlesimple' . $yuiformat . '.css" />';
             foreach ($baserollups as $rollup) {
                 $code .= '<script type="text/javascript" src="'.$this->yui3loader->local_comboBase.$rollup.'"></script>';
             }
-            foreach ($moodlerollups as $rollup) {
-                $code .= '<script type="text/javascript" src="'.$this->yui3loader->local_comboBase.$rollup.'"></script>';
-            }
         }
 
         if ($this->yui3loader->filter === 'RAW') {
index 57a4644..c5ed29a 100644 (file)
@@ -104,26 +104,3 @@ abstract class testing_block_generator extends component_generator_base {
      */
     abstract public function create_instance($record = null, array $options = null);
 }
-
-/**
- * Deprecated in favour of testing_block_generator
- *
- * @deprecated since Moodle 2.5 MDL-37457 - please do not use this function any more.
- * @todo       MDL-37517 This will be deleted in Moodle 2.7
- * @see        testing_block_generator
- * @package    core
- * @category   test
- * @copyright  2012 David Monllaó
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-abstract class phpunit_block_generator extends testing_block_generator {
-
-    /**
-     * Dumb constructor to throw the deprecated notification
-     * @param testing_data_generator $datagenerator
-     */
-    public function __construct(testing_data_generator $datagenerator) {
-        debugging('Class phpunit_block_generator is deprecated, please use class testing_block_generator instead', DEBUG_DEVELOPER);
-        parent::__construct($datagenerator);
-    }
-}
index 1171bda..20dcf5a 100644 (file)
@@ -741,24 +741,3 @@ EOD;
     }
 
 }
-
-/**
- * Deprecated in favour of testing_data_generator
- *
- * @deprecated since Moodle 2.5 MDL-37457 - please do not use this function any more.
- * @todo       MDL-37517 This will be deleted in Moodle 2.7
- * @see        testing_data_generator
- * @package    core
- * @category   test
- * @copyright  2012 David Monllaó
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class phpunit_data_generator extends testing_data_generator {
-
-    /**
-     * Dumb constructor to throw the deprecated notification
-     */
-    public function __construct() {
-        debugging('Class phpunit_data_generator is deprecated, please use class testing_module_generator instead', DEBUG_DEVELOPER);
-    }
-}
index 82657f7..7a93b3a 100644 (file)
@@ -282,26 +282,3 @@ abstract class testing_module_generator extends component_generator_base {
         throw new coding_exception('Module generator for '.$this->get_modulename().' does not implement method create_content()');
     }
 }
-
-/**
- * Deprecated in favour of testing_module_generator
- *
- * @deprecated since Moodle 2.5 MDL-37457 - please do not use this function any more.
- * @todo       MDL-37517 This will be deleted in Moodle 2.7
- * @see        testing_module_generator
- * @package    core
- * @category   test
- * @copyright  2012 David Monllaó
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-abstract class phpunit_module_generator extends testing_module_generator {
-
-    /**
-     * Dumb constructor to throw the deprecated notification
-     * @param testing_data_generator $datagenerator
-     */
-    public function __construct(testing_data_generator $datagenerator) {
-        debugging('Class phpunit_module_generator is deprecated, please use class testing_module_generator instead', DEBUG_DEVELOPER);
-        parent::__construct($datagenerator);
-    }
-}
index 25c8bb4..5532c81 100644 (file)
@@ -27,7 +27,8 @@
 
 require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
 
-use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
+use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
+    Behat\Behat\Context\Step\Given as Given;
 
 /**
  * Deprecated behat step definitions.
@@ -94,6 +95,143 @@ class behat_deprecated extends behat_base {
         );
     }
 
+    /**
+     * Adds the specified file from the 'Recent files' repository to the specified filepicker of the current page.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_filepicker::i_add_file_from_repository_to_filemanager()
+     *
+     * @When /^I add "(?P<filename_string>(?:[^"]|\\")*)" file from recent files to "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @param string $filename
+     * @param string $filepickerelement
+     */
+    public function i_add_file_from_recent_files_to_filepicker($filename, $filepickerelement) {
+        $reponame = get_string('pluginname', 'repository_recent');
+        $alternative = 'I add "' . $this->escape($filename) . '" file from "' .
+                $reponame . '" to "' . $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(
+            new Given($alternative)
+        );
+    }
+
+    /**
+     * Uploads a file to the specified filemanager leaving other fields in upload form default. The paths should be relative to moodle codebase.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_repository_upload::i_upload_file_to_filemanager()
+     *
+     * @When /^I upload "(?P<filepath_string>(?:[^"]|\\")*)" file to "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @throws ExpectationException Thrown by behat_base::find
+     * @param string $filepath
+     * @param string $filepickerelement
+     */
+    public function i_upload_file_to_filepicker($filepath, $filepickerelement) {
+        $alternative = 'I upload "' . $this->escape($filepath) . '" file to "' .
+                $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(
+            new Given($alternative)
+        );
+    }
+
+    /**
+     * Creates a folder with specified name in the current folder and in the specified filepicker field.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_filepicker::i_create_folder_in_filemanager()
+     *
+     * @Given /^I create "(?P<foldername_string>(?:[^"]|\\")*)" folder in "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @throws ExpectationException Thrown by behat_base::find
+     * @param string $foldername
+     * @param string $filepickerelement
+     */
+    public function i_create_folder_in_filepicker($foldername, $filepickerelement) {
+        $alternative = 'I create "' . $this->escape($foldername) .
+                '" folder in "' . $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(new Given($alternative));
+    }
+
+    /**
+     * Opens the contents of a filepicker folder. It looks for the folder in the current folder and in the path bar.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_filepicker::i_open_folder_from_filemanager()
+     *
+     * @Given /^I open "(?P<foldername_string>(?:[^"]|\\")*)" folder from "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @throws ExpectationException Thrown by behat_base::find
+     * @param string $foldername
+     * @param string $filepickerelement
+     */
+    public function i_open_folder_from_filepicker($foldername, $filepickerelement) {
+        $alternative = 'I open "' . $this->escape($foldername) . '" folder from "' .
+                $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(new Given($alternative));
+    }
+
+    /**
+     * Unzips the specified file from the specified filepicker field. The zip file has to be visible in the current folder.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_filepicker::i_unzip_file_from_filemanager()
+     *
+     * @Given /^I unzip "(?P<filename_string>(?:[^"]|\\")*)" file from "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @throws ExpectationException Thrown by behat_base::find
+     * @param string $filename
+     * @param string $filepickerelement
+     */
+    public function i_unzip_file_from_filepicker($filename, $filepickerelement) {
+        $alternative = 'I unzip "' . $this->escape($filename) . '" file from "' .
+                $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(new Given($alternative));
+    }
+
+    /**
+     * Zips the specified folder from the specified filepicker field. The folder has to be in the current folder.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_filepicker::i_zip_folder_from_filemanager()
+     *
+     * @Given /^I zip "(?P<filename_string>(?:[^"]|\\")*)" folder from "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @throws ExpectationException Thrown by behat_base::find
+     * @param string $foldername
+     * @param string $filepickerelement
+     */
+    public function i_zip_folder_from_filepicker($foldername, $filepickerelement) {
+        $alternative = 'I zip "' . $this->escape($foldername) . '" folder from "' .
+                $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(new Given($alternative));
+    }
+
+    /**
+     * Deletes the specified file or folder from the specified filepicker field.
+     *
+     * @deprecated since 2.7
+     * @todo MDL-42862 This will be deleted in Moodle 2.9
+     * @see behat_filepicker::i_delete_file_from_filemanager()
+     *
+     * @Given /^I delete "(?P<file_or_folder_name_string>(?:[^"]|\\")*)" from "(?P<filepicker_field_string>(?:[^"]|\\")*)" filepicker$/
+     * @throws ExpectationException Thrown by behat_base::find
+     * @param string $name
+     * @param string $filepickerelement
+     */
+    public function i_delete_file_from_filepicker($name, $filepickerelement) {
+        $alternative = 'I delete "' . $this->escape($name) . '" from "' .
+                $this->escape($filepickerelement) . '" filemanager';
+        $this->deprecated_message($alternative);
+        return array(new Given($alternative));
+    }
+
     /**
      * Throws an exception if $CFG->behat_usedeprecated is not allowed.
      *
diff --git a/lib/tests/event_course_module_instance_list_viewed.php b/lib/tests/event_course_module_instance_list_viewed.php
new file mode 100644 (file)
index 0000000..b129c78
--- /dev/null
@@ -0,0 +1,75 @@
+<?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/>.
+
+/**
+ * Tests for base course module instance list viewed event.
+ *
+ * @package    core
+ * @category   phpunit
+ * @copyright  2013 Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+require_once(__DIR__.'/fixtures/event_mod_fixtures.php');
+
+/**
+ * Class core_event_course_module_instance_list_viewed_testcase
+ *
+ * Tests for event \core\event\course_module_instance_list_viewed_testcase
+ */
+class core_event_course_module_instance_list_viewed_testcase extends advanced_testcase {
+
+    /**
+     * Test event properties and methods.
+     */
+    public function test_event_attributes() {
+
+        $this->resetAfterTest();
+        $course = $this->getDataGenerator()->create_course();
+        $context = context_course::instance($course->id);
+
+        // Trigger the page view event.
+        $sink = $this->redirectEvents();
+        $event = \mod_unittests\event\course_module_instance_list_viewed::create(array(
+             'context' => $context,
+        ));
+        $event->trigger();
+        $result = $sink->get_events();
+        $event = reset($result);
+        $sink->close();
+
+        // Test event data.
+        $legacydata = array($course->id, 'unittests', 'view all', 'index.php?id=' . $course->id, '');
+        $this->assertEventLegacyLogData($legacydata, $event);
+        $url = new moodle_url('/mod/unittests/index.php', array('id' => $course->id));
+        $this->assertEquals($url, $event->get_url());
+
+    }
+
+    /**
+     * Test custom validations of the event.
+     */
+    public function test_event_validations() {
+        try {
+            \mod_unittests\event\course_module_instance_list_viewed::create(array('context' => context_system::instance()));
+            $this->fail('Event validation should not allow course_module_instance_list_viewed event to be triggered without outside
+                    course context');
+        } catch (Exception $e) {
+            $this->assertInstanceOf('coding_exception', $e);
+        }
+    }
+}
diff --git a/lib/tests/event_deprecated_test.php b/lib/tests/event_deprecated_test.php
new file mode 100644 (file)
index 0000000..aa20e91
--- /dev/null
@@ -0,0 +1,45 @@
+<?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/>.
+
+/**
+ * Tests for deprecated events. Please add tests for deprecated events in this file.
+ *
+ * @package    core
+ * @category   phpunit
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class core_event_instances_list_viewed_testcase
+ *
+ * Tests for deprecated events.
+ */
+class core_event_deprecated_testcase extends advanced_testcase {
+
+    /**
+     * Test event properties and methods.
+     */
+    public function test_deprecated_course_module_instances_list_viewed_events() {
+
+        // Make sure the abstract class course_module_instances_list_viewed generates a debugging notice.
+        require_once(__DIR__.'/fixtures/event_mod_badfixtures.php');
+        $this->assertDebuggingCalled(null, DEBUG_DEVELOPER);
+
+    }
+}
index 6e1093c..84b2bcd 100644 (file)
@@ -666,6 +666,12 @@ class core_event_testcase extends advanced_testcase {
         $event6->trigger();
         $this->assertDebuggingCalled();
 
+        // Check that whole float numbers do not trigger debugging messages.
+        $event7 = \core_tests\event\unittest_executed::create(array('courseid'=>1, 'context'=>\context_system::instance(),
+            'other' => array('wholenumber' => 90.0000, 'numberwithdecimals' => 54.7656, 'sample' => 1)));
+        $event7->trigger();
+        $this->assertDebuggingNotCalled();
+
         $event = \core_tests\event\problematic_event2::create(array());
         $this->assertDebuggingNotCalled();
         $event = \core_tests\event\problematic_event2::create(array('context'=>\context_system::instance()));
similarity index 59%
rename from lib/phpunit/generatorlib.php
rename to lib/tests/fixtures/event_mod_badfixtures.php
index 6dfbdd4..4b08455 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Adds data generator support
+ * Fixtures for new event testing under namespace mod_tests.
  *
- * Deprecated file in favour of lib/testing/generator/lib.php, keeping
- * file for backwards reference just in case 3rd party applications are
- * using them.
- *
- * @deprecated
- * @todo       MDL-37517 This will be deleted in Moodle 2.7
- * @see        lib/testing/generator/lib.php
  * @package    core
  * @category   phpunit
- * @copyright  2012 Petr Skoda {@link http://skodak.org}
+ * @copyright  2013 onwards Ankit Agarwal
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+namespace mod_unittests\event;
+defined('MOODLE_INTERNAL') || die();
 
-debugging('File lib/phpunit/generatorlib.php is deprecated, please use lib/testing/generator/lib.php instead', DEBUG_DEVELOPER);
-
-require_once(__DIR__ . '/../testing/generator/lib.php');
+/**
+ * Class course_module_instances_list_viewed
+ */
+class course_module_instances_list_viewed extends \core\event\course_module_instances_list_viewed {
+}
diff --git a/lib/tests/fixtures/event_mod_fixtures.php b/lib/tests/fixtures/event_mod_fixtures.php
new file mode 100644 (file)
index 0000000..5af9fa7
--- /dev/null
@@ -0,0 +1,33 @@
+<?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/>.
+
+/**
+ * Fixtures for new event testing under namespace mod_tests.
+ *
+ * @package    core
+ * @category   phpunit
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_unittests\event;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class course_module_instance_list_viewed
+ */
+class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
+}
index 8f5fb54..ede1736 100644 (file)
@@ -735,4 +735,36 @@ class core_grouplib_testcase extends advanced_testcase {
         groups_allgroups_course_menu($course, 'someurl.php', true, 256);
         $this->assertEquals($group1->id, $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid]);
     }
+
+    /**
+     * This unit test checks that groups_get_all_groups returns groups in
+     * alphabetical order even if they are in a grouping.
+     */
+    public function test_groups_ordering() {
+        $generator = $this->getDataGenerator();
+        $this->resetAfterTest();
+
+        // Create a course category and course.
+        $cat = $generator->create_category(array('parent' => 0));
+        $course = $generator->create_course(array('category' => $cat->id));
+        $grouping = $generator->create_grouping(array('courseid' => $course->id, 'name' => 'Grouping'));
+
+        // Create groups in reverse order.
+        $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 2'));
+        $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 1'));
+
+        // Assign the groups to the grouping in reverse order.
+        $this->assertTrue(groups_assign_grouping($grouping->id, $group2->id));
+        $this->assertTrue(groups_assign_grouping($grouping->id, $group1->id));
+
+        // Get all groups and check they are alphabetical.
+        $groups = array_values(groups_get_all_groups($course->id, 0));
+        $this->assertEquals('Group 1', $groups[0]->name);
+        $this->assertEquals('Group 2', $groups[1]->name);
+
+        // Now check the same is true when accessed by grouping.
+        $groups = array_values(groups_get_all_groups($course->id, 0, $grouping->id));
+        $this->assertEquals('Group 1', $groups[0]->name);
+        $this->assertEquals('Group 2', $groups[1]->name);
+    }
 }
index 64be4cc..3f88d22 100644 (file)
@@ -82,7 +82,15 @@ class core_theme_config_testcase extends advanced_testcase {
             // IE9 on Windows 7.
             'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' => true,
             // IE9 on Windows 7 in intranet mode.
-            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)' => true,
+            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)' => false,
+            // IE10 on Windows 8.
+            'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Touch)' => true,
+            // IE10 on Windows 8 in compatibility mode.
+            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Trident/6.0; Touch; .NET4.0E; .NET4.0C; Tablet PC 2.0)' => true,
+            // IE11 on Windows 8.
+            'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0)' => true,
+            // IE11 on Windows 8 in compatibility mode.
+            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)' => true,
             // Chrome 11 on Windows.
             'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.652.0 Safari/534.17' => true,
             // Chrome 22 on Windows.
@@ -102,7 +110,9 @@ class core_theme_config_testcase extends advanced_testcase {
             // Android browser 2.3 (HTC).
             'Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => false,
             // Android browser 3.0 (Motorola).
-            'Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13' => true
+            'Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13' => true,
+            // Android browser 4.3 (Samsung GT-9505).
+            'Mozilla/5.0 (Linux; Android 4.3; it-it; SAMSUNG GT-I9505/I9505XXUEMJ7 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36' => true
         );
         foreach ($useragents as $agent => $expected) {
             core_useragent::instance(true, $agent);
index ddfadb8..6ed05b0 100644 (file)
@@ -138,6 +138,9 @@ class core_useragent_testcase extends basic_testcase {
             '530' => array(
                 'Nexus' => 'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17 –Nexus'
             ),
+            '537' => array(
+                'Samsung GT-9505' => 'Mozilla/5.0 (Linux; Android 4.3; it-it; SAMSUNG GT-I9505/I9505XXUEMJ7 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36'
+            )
         ),
         'Chrome' => array(
             '8' => array(
@@ -413,6 +416,66 @@ class core_useragent_testcase extends basic_testcase {
 
     }
 
+    /**
+     * Modifies $_SERVER['HTTP_USER_AGENT'] manually to check if supports_svg
+     * works as expected.
+     */
+    public function test_supports_svg() {
+        $this->assertTrue(core_useragent::supports_svg());
+
+        // MSIE 5.0 is not considered a browser at all: known false positive.
+        core_useragent::instance(true, $this->user_agents['MSIE']['5.0']['Windows 98']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['5.5']['Windows 2000']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['6.0']['Windows XP SP2']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['7.0']['Windows XP SP2']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['8.0']['Windows Vista']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['9.0']['Windows 7']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['9.0i']['Windows 7']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['10.0']['Windows 8']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['10.0i']['Windows 8']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['11.0']['Windows 8.1']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['MSIE']['11.0i']['Windows 8.1']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['WebKit Android']['525']['G1 Phone']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['WebKit Android']['530']['Nexus']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['WebKit Android']['537']['Samsung GT-9505']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['Opera']['9.0']['Windows XP']);
+        $this->assertFalse(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['Chrome']['8']['Mac OS X']);
+        $this->assertTrue(core_useragent::supports_svg());
+
+        core_useragent::instance(true, $this->user_agents['Firefox']['18.0']['Mac OS X']);
+        $this->assertTrue(core_useragent::supports_svg());
+    }
+
     /**
      * Test browser version classes functionality.
      */
index 5b93690..b720a86 100644 (file)
@@ -1,6 +1,15 @@
 This files describes API changes in core libraries and APIs,
 information provided here is intended especially for developers.
 
+=== 2.7 ===
+
+* 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.
+* mod_chat\event\instances_list_viewed has been deprecated. Please use mod_chat\event\course_module_instance_list_viewed instead.
+* mod_choice\event\instances_list_viewed has been deprecated. Please use mod_choice\event\course_module_instance_list_viewed instead.
+* mod_feedback\event\instances_list_viewed has been deprecated. Please use mod_feedback\event\course_module_instance_list_viewed instead.
+* mod_page\event\instances_list_viewed has been deprecated. Please use mod_page\event\course_module_instance_list_viewed instead.
+
 === 2.6 ===
 
 * Use new methods from core_component class instead of get_core_subsystems(), get_plugin_types(),
index e2a1763..a765037 100644 (file)
Binary files a/lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js and b/lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js differ
index e4d3fd5..4da7627 100644 (file)
Binary files a/lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js and b/lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js differ
index 550debb..2b3315f 100644 (file)
Binary files a/lib/yui/build/moodle-core-blocks/moodle-core-blocks.js and b/lib/yui/build/moodle-core-blocks/moodle-core-blocks.js differ
diff --git a/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js
new file mode 100644 (file)
index 0000000..5014285
Binary files /dev/null and b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js differ
diff --git a/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js
new file mode 100644 (file)
index 0000000..7cd70d5
Binary files /dev/null and b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js differ
diff --git a/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js
new file mode 100644 (file)
index 0000000..5014285
Binary files /dev/null and b/lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js differ
diff --git a/lib/yui/dragdrop/dragdrop.js b/lib/yui/dragdrop/dragdrop.js
deleted file mode 100644 (file)
index 773373c..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-YUI.add('moodle-core-dragdrop', function(Y) {
-    var MOVEICON = {
-        pix: "i/move_2d",
-        largepix: "i/dragdrop",
-        component: 'moodle',
-        cssclass: 'moodle-core-dragdrop-draghandle'
-    };
-
-   /*
-    * General DRAGDROP class, this should not be used directly,
-    * it is supposed to be extended by your class
-    */
-    var DRAGDROP = function() {
-        DRAGDROP.superclass.constructor.apply(this, arguments);
-    };
-
-    Y.extend(DRAGDROP, Y.Base, {
-        goingup : null,
-        absgoingup : null,
-        samenodeclass : null,
-        parentnodeclass : null,
-        groups : [],
-        lastdroptarget : null,
-        initializer : function() {
-            // Listen for all drag:start events
-            Y.DD.DDM.on('drag:start', this.global_drag_start, this);
-            // Listen for all drag:end events
-            Y.DD.DDM.on('drag:end', this.global_drag_end, this);
-            // Listen for all drag:drag events
-            Y.DD.DDM.on('drag:drag', this.global_drag_drag, this);
-            // Listen for all drop:over events
-            Y.DD.DDM.on('drop:over', this.global_drop_over, this);
-            // Listen for all drop:hit events
-            Y.DD.DDM.on('drop:hit', this.global_drop_hit, this);
-            // Listen for all drop:miss events
-            Y.DD.DDM.on('drag:dropmiss', this.global_drag_dropmiss, this);
-
-            Y.one(Y.config.doc.body).delegate('key', this.global_keydown, 'down:32, enter, esc', '.' + MOVEICON.cssclass, this);
-            Y.one(Y.config.doc.body).delegate('click', this.global_keydown, '.' + MOVEICON.cssclass , this);
-        },
-
-        get_drag_handle: function(title, classname, iconclass, large) {
-            var iconname = MOVEICON.pix;
-            if (large) {
-                iconname = MOVEICON.largepix;
-            }
-            var dragicon = Y.Node.create('<img />')
-                .setStyle('cursor', 'move')
-                .setAttrs({
-                    'src' : M.util.image_url(iconname, MOVEICON.component),
-                    'alt' : title
-                });
-            if (iconclass) {
-                dragicon.addClass(iconclass);
-            }
-
-            var dragelement = Y.Node.create('<span></span>')
-                .addClass(classname)
-                .setAttribute('title', title)
-                .setAttribute('tabIndex', 0)
-                .setAttribute('data-draggroups', this.groups)
-                .setAttribute('aria-grabbed', 'false')
-                .setAttribute('role', 'button');
-            dragelement.appendChild(dragicon);
-            dragelement.addClass(MOVEICON.cssclass);
-
-            return dragelement;
-        },
-
-        lock_drag_handle: function(drag, classname) {
-            drag.removeHandle('.'+classname);
-        },
-
-        unlock_drag_handle: function(drag, classname) {
-            drag.addHandle('.'+classname);
-        },
-
-        ajax_failure: function(response) {
-            var e = {
-                name : response.status+' '+response.statusText,
-                message : response.responseText
-            };
-            return new M.core.exception(e);
-        },
-
-        in_group: function(target) {
-            var ret = false;
-            Y.each(this.groups, function(v, k) {
-                if (target._groups[v]) {
-                    ret = true;
-                }
-            }, this);
-            return ret;
-        },
-        /*
-         * Drag-dropping related functions
-         */
-        global_drag_start : function(e) {
-            // Get our drag object
-            var drag = e.target;
-            // Check that drag object belongs to correct group
-            if (!this.in_group(drag)) {
-                return;
-            }
-            // Set some general styles here
-            drag.get('node').setStyle('opacity', '.25');
-            drag.get('dragNode').setStyles({
-                opacity: '.75',
-                borderColor: drag.get('node').getStyle('borderColor'),
-                backgroundColor: drag.get('node').getStyle('backgroundColor')
-            });
-            drag.get('dragNode').empty();
-            this.drag_start(e);
-        },
-
-        global_drag_end : function(e) {
-            var drag = e.target;
-            // Check that drag object belongs to correct group
-            if (!this.in_group(drag)) {
-                return;
-            }
-            //Put our general styles back
-            drag.get('node').setStyles({
-                visibility: '',
-                opacity: '1'
-            });
-            this.drag_end(e);
-        },
-
-        global_drag_drag : function(e) {
-            var drag = e.target,
-                info = e.info;
-
-            // Check that drag object belongs to correct group
-            if (!this.in_group(drag)) {
-                return;
-            }
-
-            // Note, we test both < and > situations here. We don't want to
-            // effect a change in direction if the user is only moving side
-            // to side with no Y position change.
-
-            // Detect changes in the position relative to the start point.
-            if (info.start[1] < info.xy[1]) {
-                // We are going up if our final position is higher than our start position.
-                this.absgoingup = true;
-
-            } else if (info.start[1] > info.xy[1]) {
-                // Otherwise we're going down.
-                this.absgoingup = false;
-            }
-
-            // Detect changes in the position relative to the last movement.
-            if (info.delta[1] < 0) {
-                // We are going up if our final position is higher than our start position.
-                this.goingup = true;
-
-            } else if (info.delta[1] > 0) {
-                // Otherwise we're going down.
-                this.goingup = false;
-            }
-
-            this.drag_drag(e);
-        },
-
-        global_drop_over : function(e) {
-            // Check that drop object belong to correct group.
-            if (!e.drop || !e.drop.inGroup(this.groups)) {
-                return;
-            }
-
-            // Get a reference to our drag and drop nodes.
-            var drag = e.drag.get('node'),
-                drop = e.drop.get('node');
-
-            // Save last drop target for the case of missed target processing.
-            this.lastdroptarget = e.drop;
-
-            // Are we dropping within the same parent node?
-            if (drop.hasClass(this.samenodeclass)) {
-                var where;
-
-                if (this.goingup) {
-                    where = "before";
-                } else {
-                    where = "after";
-                }
-
-                // Add the node contents so that it's moved, otherwise only the drag handle is moved.
-                drop.insert(drag, where);
-            } else if ((drop.hasClass(this.parentnodeclass) || drop.test('[data-droptarget="1"]')) && !drop.contains(drag)) {
-                // We are dropping on parent node and it is empty
-                if (this.goingup) {
-                    drop.append(drag);
-                } else {
-                    drop.prepend(drag);
-                }
-            }
-            this.drop_over(e);
-        },
-
-        global_drag_dropmiss : function(e) {
-            // drag:dropmiss does not have e.drag and e.drop properties
-            // we substitute them for the ease of use. For e.drop we use,
-            // this.lastdroptarget (ghost node we use for indicating where to drop)
-            e.drag = e.target;
-            e.drop = this.lastdroptarget;
-            // Check that drag object belongs to correct group
-            if (!this.in_group(e.drag)) {
-                return;
-            }
-            // Check that drop object belong to correct group
-            if (!e.drop || !e.drop.inGroup(this.groups)) {
-                return;
-            }
-            this.drag_dropmiss(e);
-        },
-
-        global_drop_hit : function(e) {
-            // Check that drop object belong to correct group
-            if (!e.drop || !e.drop.inGroup(this.groups)) {
-                return;
-            }
-            this.drop_hit(e);
-        },
-
-        /**
-         * This is used to build the text for the heading of the keyboard
-         * drag drop menu and the text for the nodes in the list.
-         * @method find_element_text
-         * @param {Node} n The node to start searching for a valid text node.
-         * @returns {string} The text of the first text-like child node of n.
-         */
-        find_element_text : function(n) {
-            // The valid node types to get text from.
-            var nodes = n.all('h2, h3, h4, h5, span, p, div.no-overflow, div.dimmed_text');
-            var text = '';
-
-            nodes.each(function () {
-                if (text == '') {
-                    if (Y.Lang.trim(this.get('text')) != '') {
-                        text = this.get('text');
-                    }
-                }
-            });
-
-            if (text != '') {
-                return text;
-            }
-            return M.util.get_string('emptydragdropregion', 'moodle');
-        },
-
-        /**
-         * This is used to initiate a keyboard version of a drag and drop.
-         * A dialog will open listing all the valid drop targets that can be selected
-         * using tab, tab, tab, enter.
-         * @method global_start_keyboard_drag
-         * @param {Event} e The keydown / click event on the grab handle.
-         * @param {Node} dragcontainer The resolved draggable node (an ancestor of the drag handle).
-         * @param {Node} draghandle The node that triggered this action.
-         */
-        global_start_keyboard_drag : function(e, draghandle, dragcontainer) {
-            M.core.dragdrop.keydragcontainer = dragcontainer;
-            M.core.dragdrop.keydraghandle = draghandle;
-
-            // Indicate to a screenreader the node that is selected for drag and drop.
-            dragcontainer.setAttribute('aria-grabbed', 'true');
-            // Get the name of the thing to move.
-            var nodetitle = this.find_element_text(dragcontainer);
-            var dialogtitle = M.util.get_string('movecontent', 'moodle', nodetitle);
-
-            // Build the list of drop targets.
-            var droplist = Y.Node.create('<ul></ul>');
-            droplist.addClass('dragdrop-keyboard-drag');
-            var listitem;
-            var listitemtext;
-
-            // Search for possible drop targets.
-            var droptargets = Y.all('.' + this.samenodeclass + ', .' + this.parentnodeclass);
-
-            droptargets.each(function (node) {
-                var validdrop = false, labelroot = node;
-                if (node.drop && node.drop.inGroup(this.groups) && node.drop.get('node') != dragcontainer) {
-                    // This is a drag and drop target with the same class as the grabbed node.
-                    validdrop = true;
-                } else {
-                    var elementgroups = node.getAttribute('data-draggroups').split(' ');
-                    var i, j;
-                    for (i = 0; i < elementgroups.length; i++) {
-                        for (j = 0; j < this.groups.length; j++) {
-                            if (elementgroups[i] == this.groups[j]) {
-                                // This is a parent node of the grabbed node (used for dropping in empty sections).
-                                validdrop = true;
-                                // This node will have no text - so we get the first valid text from the parent.
-                                labelroot = node.get('parentNode');
-                                break;
-                            }
-                        }
-                        if (validdrop) {
-                            break;
-                        }
-                    }
-                }
-
-                if (validdrop) {
-                    // It is a valid drop target - create a list item for it.
-                    listitem = Y.Node.create('<li></li>');
-                    listlink = Y.Node.create('<a></a>');
-                    nodetitle = this.find_element_text(labelroot);
-
-                    listitemtext = M.util.get_string('tocontent', 'moodle', nodetitle);
-                    listlink.setContent(listitemtext);
-
-                    // Add a data attribute so we can get the real drop target.
-                    listlink.setAttribute('data-drop-target', node.get('id'));
-                    // Notify the screen reader this is a valid drop target.
-                    listlink.setAttribute('aria-dropeffect', 'move');
-                    // Allow tabbing to the link.
-                    listlink.setAttribute('tabindex', '0');
-
-                    // Set the event listeners for enter, space or click.
-                    listlink.on('click', this.global_keyboard_drop, this);
-                    listlink.on('key', this.global_keyboard_drop, 'down:enter,32', this);
-
-                    // Add to the list or drop targets.
-                    listitem.append(listlink);
-                    droplist.append(listitem);
-                }
-            }, this);
-
-            // Create the dialog for the interaction.
-            M.core.dragdrop.dropui = new M.core.dialogue({
-                headerContent : dialogtitle,
-                bodyContent : droplist,
-                draggable : true,
-                visible : true,
-                centered : true
-            });
-
-            // Focus the first drop target.
-            if (droplist.one('a')) {
-                droplist.one('a').focus();
-            }
-        },
-
-        /**
-         * This is used as a simulated drag/drop event in order to prevent any
-         * subtle bugs from creating a real instance of a drag drop event. This means
-         * there are no state changes in the Y.DD.DDM and any undefined functions
-         * will trigger an obvious and fatal error.
-         * The end result is that we call all our drag/drop handlers but do not bubble the
-         * event to anyone else.
-         *
-         * The functions/properties implemented in the wrapper are:
-         * e.target
-         * e.drag
-         * e.drop
-         * e.drag.get('node')
-         * e.drop.get('node')
-         * e.drag.addHandle()
-         * e.drag.removeHandle()
-         *
-         * @class simulated_drag_drop_event
-         * @param {Node} dragnode The drag container node
-         * @param {Node} dropnode The node to initiate the drop on
-         */
-        simulated_drag_drop_event : function(dragnode, dropnode) {
-
-            // Subclass for wrapping both drag and drop.
-            var dragdropwrapper = function(node) {
-                this.node = node;
-            }
-
-            // Method e.drag.get() - get the node.
-            dragdropwrapper.prototype.get = function(param) {
-                if (param == 'node' || param == 'dragNode' || param == 'dropNode') {
-                    return this.node;
-                }
-                return null;
-            };
-
-            // Method e.drag.inGroup() - we have already run the group checks before triggering the event.
-            dragdropwrapper.prototype.inGroup = function() {
-                return true;
-            };
-
-            // Method e.drag.addHandle() - we don't want to run this.
-            dragdropwrapper.prototype.addHandle = function() {};
-            // Method e.drag.removeHandle() - we don't want to run this.
-            dragdropwrapper.prototype.removeHandle = function() {};
-
-            // Create instances of the dragdropwrapper.
-            this.drop = new dragdropwrapper(dropnode);
-            this.drag = new dragdropwrapper(dragnode);
-            this.target = this.drop;
-        },
-
-        /**
-         * This is used to complete a keyboard version of a drag and drop.
-         * A drop event will be simulated based on the drag and drop nodes.
-         * @method global_keyboard_drop
-         * @param {Event} e The keydown / click event on the proxy drop node.
-         */
-        global_keyboard_drop : function(e) {
-            // The drag node was saved.
-            var dragcontainer = M.core.dragdrop.keydragcontainer;
-            dragcontainer.setAttribute('aria-grabbed', 'false');
-            // The real drop node is stored in an attribute of the proxy.
-            var droptarget = Y.one('#' + e.target.getAttribute('data-drop-target'));
-
-            // Close the dialog.
-            M.core.dragdrop.dropui.hide();
-            // Cancel the event.
-            e.preventDefault();
-            // Convert to drag drop events.
-            var dragevent = new this.simulated_drag_drop_event(dragcontainer, dragcontainer);
-            var dropevent = new this.simulated_drag_drop_event(dragcontainer, droptarget);
-            // Simulate the full sequence.
-            this.drag_start(dragevent);
-            this.global_drop_over(dropevent);
-            this.global_drop_hit(dropevent);
-            M.core.dragdrop.keydraghandle.focus();
-        },
-
-        /**
-         * This is used to cancel a keyboard version of a drag and drop.
-         *
-         * @method global_cancel_keyboard_drag
-         */
-        global_cancel_keyboard_drag : function() {
-            if (M.core.dragdrop.keydragcontainer) {
-                M.core.dragdrop.keydragcontainer.setAttribute('aria-grabbed', 'false');
-                M.core.dragdrop.keydraghandle.focus();
-                M.core.dragdrop.keydragcontainer = null;
-            }
-        },
-
-        /**
-         * Process key events on the drag handles.
-         * @method global_keydown
-         * @param {Event} e The keydown / click event on the drag handle.
-         */
-        global_keydown : function(e) {
-            var draghandle = e.target.ancestor('.' + MOVEICON.cssclass, true),
-                dragcontainer,
-                draggroups;
-
-            if (draghandle === null) {
-                // The element clicked did not have a a draghandle in it's lineage.
-                return;
-            }
-
-            if (e.keyCode === 27 ) {
-                // Escape to cancel from anywhere.
-                this.global_cancel_keyboard_drag();
-                e.preventDefault();
-                return;
-            }
-
-            // Only process events on a drag handle.
-            if (!draghandle.hasClass(MOVEICON.cssclass)) {
-                return;
-            }
-
-            // Do nothing if not space or enter.
-            if (e.keyCode !== 13 && e.keyCode !== 32 && e.type !== 'click') {
-                return;
-            }
-
-            // Check the drag groups to see if we are the handler for this node.
-            draggroups = draghandle.getAttribute('data-draggroups').split(' ');
-            var i, j, validgroup = false;
-
-            for (i = 0; i < draggroups.length; i++) {
-                for (j = 0; j < this.groups.length; j++) {
-                    if (draggroups[i] === this.groups[j]) {
-                        validgroup = true;
-                        break;
-                    }
-                }
-                if (validgroup) {
-                    break;
-                }
-            }
-            if (!validgroup) {
-                return;
-            }
-
-            // Valid event - start the keyboard drag.
-            dragcontainer = draghandle.ancestor('.yui3-dd-drop');
-            this.global_start_keyboard_drag(e, draghandle, dragcontainer);
-
-            e.preventDefault();
-        },
-
-        /*
-         * Abstract functions definitions
-         */
-        drag_start : function(e) {},
-        drag_end : function(e) {},
-        drag_drag : function(e) {},
-        drag_dropmiss : function(e) {},
-        drop_over : function(e) {},
-        drop_hit : function(e) {}
-    }, {
-        NAME : 'dragdrop',
-        ATTRS : {}
-    });
-
-M.core = M.core || {};
-M.core.dragdrop = DRAGDROP;
-
-}, '@VERSION@', {requires:['base', 'node', 'io', 'dom', 'dd', 'event-key', 'event-focus', 'moodle-core-notification']});
index 6aa9f69..06a82ea 100644 (file)
@@ -61,7 +61,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
 
         // See if we are missing either of block regions,
         // if yes we need to add an empty one to use as target
-        if (blockregionlist.size() != this.get('regions').length) {
+        if (blockregionlist.size() !== this.get('regions').length) {
             var blockregion = Y.Node.create('<div></div>')
                 .addClass(CSS.BLOCKREGION);
             var regioncontent = Y.Node.create('<div></div>')
@@ -88,7 +88,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
             // Setting blockregion as droptarget (the case when it is empty)
             // The region-post (the right one)
             // is very narrow, so add extra padding on the left to drop block on it.
-            var tar = new Y.DD.Drop({
+            new Y.DD.Drop({
                 node: blockregionnode.one('div.'+CSS.REGIONCONTENT),
                 groups: this.groups,
                 padding: '40 240 40 240'
@@ -197,7 +197,7 @@ Y.extend(DRAGBLOCK, M.core.dragdrop, {
         // Moving from empty region-content towards the opposite one,
         // hide empty one (only for region-pre, region-post areas at the moment).
         regionname = this.get_region_id(drop.ancestor('div.'+CSS.BLOCKREGION));
-        if (this.dragsourceregion.all('.'+CSS.BLOCK).size() == 0 && this.dragsourceregion.get('id').match(/(region-pre|region-post)/i)) {
+        if (this.dragsourceregion.all('.'+CSS.BLOCK).size() === 0 && this.dragsourceregion.get('id').match(/(region-pre|region-post)/i)) {
             if (!documentbody.hasClass('side-'+regionname+'-only')) {
                 documentbody.addClass('side-'+regionname+'-only');
             }
diff --git a/lib/yui/src/dragdrop/build.json b/lib/yui/src/dragdrop/build.json
new file mode 100644 (file)
index 0000000..e21619a
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "name": "moodle-core-dragdrop",
+    "builds": {
+        "moodle-core-dragdrop": {
+            "jsfiles": [
+                "dragdrop.js"
+            ]
+        }
+    }
+}
diff --git a/lib/yui/src/dragdrop/js/dragdrop.js b/lib/yui/src/dragdrop/js/dragdrop.js
new file mode 100644 (file)
index 0000000..87bfd03
--- /dev/null
@@ -0,0 +1,640 @@
+/**
+ * The core drag and drop module for Moodle which extends the YUI drag and
+ * drop functionality with additional features.
+ *
+ * @module moodle-core-dragdrop
+ */
+var MOVEICON = {
+    pix: "i/move_2d",
+    largepix: "i/dragdrop",
+    component: 'moodle',
+    cssclass: 'moodle-core-dragdrop-draghandle'
+};
+
+/**
+ * General DRAGDROP class, this should not be used directly,
+ * it is supposed to be extended by your class
+ *
+ * @class M.core.dragdrop
+ * @constructor
+ * @extends Base
+ */
+var DRAGDROP = function() {
+    DRAGDROP.superclass.constructor.apply(this, arguments);
+};
+
+Y.extend(DRAGDROP, Y.Base, {
+    /**
+     * Whether the item is being moved upwards compared with the last
+     * location.
+     *
+     * @property goingup
+     * @type Boolean
+     * @default null
+     */
+    goingup: null,
+
+    /**
+     * Whether the item is being moved upwards compared with the start
+     * point.
+     *
+     * @property absgoingup
+     * @type Boolean
+     * @default null
+     */
+    absgoingup: null,
+
+    /**
+     * The class for the object.
+     *
+     * @property samenodeclass
+     * @type String
+     * @default null
+     */
+    samenodeclass: null,
+
+    /**
+     * The class on the parent of the item being moved.
+     *
+     * @property parentnodeclass
+     * @type String
+     * @default
+     */
+    parentnodeclass: null,
+
+    /**
+     * The groups for this instance.
+     *
+     * @property groups
+     * @type Array
+     * @default []
+     */
+    groups: [],
+
+    /**
+     * The previous drop location.
+     *
+     * @property lastdroptarget
+     * @type Node
+     * @default null
+     */
+    lastdroptarget: null,
+
+    /**
+     * The initializer which sets up the move action.
+     *
+     * @method initializer
+     * @protected
+     */
+    initializer: function() {
+        // Listen for all drag:start events.
+        Y.DD.DDM.on('drag:start', this.global_drag_start, this);
+
+        // Listen for all drag:end events.
+        Y.DD.DDM.on('drag:end', this.global_drag_end, this);
+
+        // Listen for all drag:drag events.
+        Y.DD.DDM.on('drag:drag', this.global_drag_drag, this);
+
+        // Listen for all drop:over events.
+        Y.DD.DDM.on('drop:over', this.global_drop_over, this);
+
+        // Listen for all drop:hit events.
+        Y.DD.DDM.on('drop:hit', this.global_drop_hit, this);
+
+        // Listen for all drop:miss events.
+        Y.DD.DDM.on('drag:dropmiss', this.global_drag_dropmiss, this);
+
+        // Add keybaord listeners for accessible drag/drop
+        Y.one(Y.config.doc.body).delegate('key', this.global_keydown,
+                'down:32, enter, esc', '.' + MOVEICON.cssclass, this);
+
+        // Make the accessible drag/drop respond to a single click.
+        Y.one(Y.config.doc.body).delegate('click', this.global_keydown,
+                '.' + MOVEICON.cssclass , this);
+    },
+
+    /**
+     * Build a new drag handle Node.
+     *
+     * @method get_drag_handle
+     * @param {String} title The title on the drag handle
+     * @param {String} classname The name of the class to add to the node
+     * wrapping the drag icon
+     * @param {String} [iconclass] The class to add to the icon
+     * @param {Boolean} [large=false] whether to use the larger version of
+     * the drag icon
+     * @return Node The built drag handle.
+     */
+    get_drag_handle: function(title, classname, iconclass, large) {
+        var iconname = MOVEICON.pix;
+        if (large) {
+            iconname = MOVEICON.largepix;
+        }
+        var dragicon = Y.Node.create('<img />')
+            .setStyle('cursor', 'move')
+            .setAttrs({
+                'src': M.util.image_url(iconname, MOVEICON.component),
+                'alt': title
+            });
+        if (iconclass) {
+            dragicon.addClass(iconclass);
+        }
+
+        var dragelement = Y.Node.create('<span></span>')
+            .addClass(classname)
+            .setAttribute('title', title)
+            .setAttribute('tabIndex', 0)
+            .setAttribute('data-draggroups', this.groups)
+            .setAttribute('role', 'button')
+            .setAttribute('aria-grabbed', 'false');
+        dragelement.appendChild(dragicon);
+        dragelement.addClass(MOVEICON.cssclass);
+
+        return dragelement;
+    },
+
+    lock_drag_handle: function(drag, classname) {
+        drag.removeHandle('.'+classname);
+    },
+
+    unlock_drag_handle: function(drag, classname) {
+        drag.addHandle('.'+classname);
+    },
+
+    ajax_failure: function(response) {
+        var e = {
+            name: response.status+' '+response.statusText,
+            message: response.responseText
+        };
+        return new M.core.exception(e);
+    },
+
+    in_group: function(target) {
+        var ret = false;
+        Y.each(this.groups, function(v) {
+            if (target._groups[v]) {
+                ret = true;
+            }
+        }, this);
+        return ret;
+    },
+    /*
+        * Drag-dropping related functions
+        */
+    global_drag_start: function(e) {
+        // Get our drag object
+        var drag = e.target;
+        // Check that drag object belongs to correct group
+        if (!this.in_group(drag)) {
+            return;
+        }
+        // Set some general styles here
+        drag.get('node').setStyle('opacity', '.25');
+        drag.get('dragNode').setStyles({
+            opacity: '.75',
+            borderColor: drag.get('node').getStyle('borderColor'),
+            backgroundColor: drag.get('node').getStyle('backgroundColor')
+        });
+        drag.get('dragNode').empty();
+        this.drag_start(e);
+    },
+
+    global_drag_end: function(e) {
+        var drag = e.target;
+        // Check that drag object belongs to correct group
+        if (!this.in_group(drag)) {
+            return;
+        }
+        //Put our general styles back
+        drag.get('node').setStyles({
+            visibility: '',
+            opacity: '1'
+        });
+        this.drag_end(e);
+    },
+
+    global_drag_drag: function(e) {
+        var drag = e.target,
+            info = e.info;
+
+        // Check that drag object belongs to correct group
+        if (!this.in_group(drag)) {
+            return;
+        }
+
+        // Note, we test both < and > situations here. We don't want to
+        // effect a change in direction if the user is only moving side
+        // to side with no Y position change.
+
+        // Detect changes in the position relative to the start point.
+        if (info.start[1] < info.xy[1]) {
+            // We are going up if our final position is higher than our start position.
+            this.absgoingup = true;
+
+        } else if (info.start[1] > info.xy[1]) {
+            // Otherwise we're going down.
+            this.absgoingup = false;
+        }
+
+        // Detect changes in the position relative to the last movement.
+        if (info.delta[1] < 0) {
+            // We are going up if our final position is higher than our start position.
+            this.goingup = true;
+
+        } else if (info.delta[1] > 0) {
+            // Otherwise we're going down.
+            this.goingup = false;
+        }
+
+        this.drag_drag(e);
+    },
+
+    global_drop_over: function(e) {
+        // Check that drop object belong to correct group.
+        if (!e.drop || !e.drop.inGroup(this.groups)) {
+            return;
+        }
+
+        // Get a reference to our drag and drop nodes.
+        var drag = e.drag.get('node'),
+            drop = e.drop.get('node');
+
+        // Save last drop target for the case of missed target processing.
+        this.lastdroptarget = e.drop;
+
+        // Are we dropping within the same parent node?
+        if (drop.hasClass(this.samenodeclass)) {
+            var where;
+
+            if (this.goingup) {
+                where = "before";
+            } else {
+                where = "after";
+            }
+
+            // Add the node contents so that it's moved, otherwise only the drag handle is moved.
+            drop.insert(drag, where);
+        } else if ((drop.hasClass(this.parentnodeclass) || drop.test('[data-droptarget="1"]')) && !drop.contains(drag)) {
+            // We are dropping on parent node and it is empty
+            if (this.goingup) {
+                drop.append(drag);
+            } else {
+                drop.prepend(drag);
+            }
+        }
+        this.drop_over(e);
+    },
+
+    global_drag_dropmiss: function(e) {
+        // drag:dropmiss does not have e.drag and e.drop properties
+        // we substitute them for the ease of use. For e.drop we use,
+        // this.lastdroptarget (ghost node we use for indicating where to drop)
+        e.drag = e.target;
+        e.drop = this.lastdroptarget;
+        // Check that drag object belongs to correct group
+        if (!this.in_group(e.drag)) {
+            return;
+        }
+        // Check that drop object belong to correct group
+        if (!e.drop || !e.drop.inGroup(this.groups)) {
+            return;
+        }
+        this.drag_dropmiss(e);
+    },
+
+    global_drop_hit: function(e) {
+        // Check that drop object belong to correct group
+        if (!e.drop || !e.drop.inGroup(this.groups)) {
+            return;
+        }
+        this.drop_hit(e);
+    },
+
+    /**
+     * This is used to build the text for the heading of the keyboard
+     * drag drop menu and the text for the nodes in the list.
+     * @method find_element_text
+     * @param {Node} n The node to start searching for a valid text node.
+     * @return {string} The text of the first text-like child node of n.
+     */
+    find_element_text: function(n) {
+        // The valid node types to get text from.
+        var nodes = n.all('h2, h3, h4, h5, span, p, div.no-overflow, div.dimmed_text');
+        var text = '';
+
+        nodes.each(function () {
+            if (text === '') {
+                if (Y.Lang.trim(this.get('text')) !== '') {
+                    text = this.get('text');
+                }
+            }
+        });
+
+        if (text !== '') {
+            return text;
+        }
+        return M.util.get_string('emptydragdropregion', 'moodle');
+    },
+
+    /**
+     * This is used to initiate a keyboard version of a drag and drop.
+     * A dialog will open listing all the valid drop targets that can be selected
+     * using tab, tab, tab, enter.
+     * @method global_start_keyboard_drag
+     * @param {Event} e The keydown / click event on the grab handle.
+     * @param {Node} dragcontainer The resolved draggable node (an ancestor of the drag handle).
+     * @param {Node} draghandle The node that triggered this action.
+     */
+    global_start_keyboard_drag: function(e, draghandle, dragcontainer) {
+        M.core.dragdrop.keydragcontainer = dragcontainer;
+        M.core.dragdrop.keydraghandle = draghandle;
+
+        // Indicate to a screenreader the node that is selected for drag and drop.
+        dragcontainer.setAttribute('aria-grabbed', 'true');
+        // Get the name of the thing to move.
+        var nodetitle = this.find_element_text(dragcontainer);
+        var dialogtitle = M.util.get_string('movecontent', 'moodle', nodetitle);
+
+        // Build the list of drop targets.
+        var droplist = Y.Node.create('<ul></ul>');
+        droplist.addClass('dragdrop-keyboard-drag');
+        var listitem;
+        var listitemtext;
+
+        // Search for possible drop targets.
+        var droptargets = Y.all('.' + this.samenodeclass + ', .' + this.parentnodeclass);
+
+        droptargets.each(function (node) {
+            var validdrop = false, labelroot = node;
+            if (node.drop && node.drop.inGroup(this.groups) && node.drop.get('node') !== dragcontainer) {
+                // This is a drag and drop target with the same class as the grabbed node.
+                validdrop = true;
+            } else {
+                var elementgroups = node.getAttribute('data-draggroups').split(' ');
+                var i, j;
+                for (i = 0; i < elementgroups.length; i++) {
+                    for (j = 0; j < this.groups.length; j++) {
+                        if (elementgroups[i] === this.groups[j]) {
+                            // This is a parent node of the grabbed node (used for dropping in empty sections).
+                            validdrop = true;
+                            // This node will have no text - so we get the first valid text from the parent.
+                            labelroot = node.get('parentNode');
+                            break;
+                        }
+                    }
+                    if (validdrop) {
+                        break;
+                    }
+                }
+            }
+
+            if (validdrop) {
+                // It is a valid drop target - create a list item for it.
+                listitem = Y.Node.create('<li></li>');
+                listlink = Y.Node.create('<a></a>');
+                nodetitle = this.find_element_text(labelroot);
+
+                listitemtext = M.util.get_string('tocontent', 'moodle', nodetitle);
+                listlink.setContent(listitemtext);
+
+                // Add a data attribute so we can get the real drop target.
+                listlink.setAttribute('data-drop-target', node.get('id'));
+                // Notify the screen reader this is a valid drop target.
+                listlink.setAttribute('aria-dropeffect', 'move');
+                // Allow tabbing to the link.
+                listlink.setAttribute('tabindex', '0');
+
+                // Set the event listeners for enter, space or click.
+                listlink.on('click', this.global_keyboard_drop, this);
+                listlink.on('key', this.global_keyboard_drop, 'down:enter,32', this);
+
+                // Add to the list or drop targets.
+                listitem.append(listlink);
+                droplist.append(listitem);
+            }
+        }, this);
+
+        // Create the dialog for the interaction.
+        M.core.dragdrop.dropui = new M.core.dialogue({
+            headerContent: dialogtitle,
+            bodyContent: droplist,
+            draggable: true,
+            visible: true,
+            centered: true
+        });
+
+        // Focus the first drop target.
+        if (droplist.one('a')) {
+            droplist.one('a').focus();
+        }
+    },
+
+    /**
+     * This is used as a simulated drag/drop event in order to prevent any
+     * subtle bugs from creating a real instance of a drag drop event. This means
+     * there are no state changes in the Y.DD.DDM and any undefined functions
+     * will trigger an obvious and fatal error.
+     * The end result is that we call all our drag/drop handlers but do not bubble the
+     * event to anyone else.
+     *
+     * The functions/properties implemented in the wrapper are:
+     * e.target
+     * e.drag
+     * e.drop
+     * e.drag.get('node')
+     * e.drop.get('node')
+     * e.drag.addHandle()
+     * e.drag.removeHandle()
+     *
+     * @method simulated_drag_drop_event
+     * @param {Node} dragnode The drag container node
+     * @param {Node} dropnode The node to initiate the drop on
+     */
+    simulated_drag_drop_event: function(dragnode, dropnode) {
+
+        // Subclass for wrapping both drag and drop.
+        var DragDropWrapper = function(node) {
+            this.node = node;
+        };
+
+        // Method e.drag.get() - get the node.
+        DragDropWrapper.prototype.get = function(param) {
+            if (param === 'node' || param === 'dragNode' || param === 'dropNode') {
+                return this.node;
+            }
+            return null;
+        };
+
+        // Method e.drag.inGroup() - we have already run the group checks before triggering the event.
+        DragDropWrapper.prototype.inGroup = function() {
+            return true;
+        };
+
+        // Method e.drag.addHandle() - we don't want to run this.
+        DragDropWrapper.prototype.addHandle = function() {};
+        // Method e.drag.removeHandle() - we don't want to run this.
+        DragDropWrapper.prototype.removeHandle = function() {};
+
+        // Create instances of the DragDropWrapper.
+        this.drop = new DragDropWrapper(dropnode);
+        this.drag = new DragDropWrapper(dragnode);
+        this.target = this.drop;
+    },
+
+    /**
+     * This is used to complete a keyboard version of a drag and drop.
+     * A drop event will be simulated based on the drag and drop nodes.
+     * @method global_keyboard_drop
+     * @param {Event} e The keydown / click event on the proxy drop node.
+     */
+    global_keyboard_drop: function(e) {
+        // The drag node was saved.
+        var dragcontainer = M.core.dragdrop.keydragcontainer;
+        dragcontainer.setAttribute('aria-grabbed', 'false');
+        // The real drop node is stored in an attribute of the proxy.
+        var droptarget = Y.one('#' + e.target.getAttribute('data-drop-target'));
+
+        // Close the dialog.
+        M.core.dragdrop.dropui.hide();
+        // Cancel the event.
+        e.preventDefault();
+        // Convert to drag drop events.
+        var dragevent = new this.simulated_drag_drop_event(dragcontainer, dragcontainer);
+        var dropevent = new this.simulated_drag_drop_event(dragcontainer, droptarget);
+        // Simulate the full sequence.
+        this.drag_start(dragevent);
+        this.global_drop_over(dropevent);
+        this.global_drop_hit(dropevent);
+        M.core.dragdrop.keydraghandle.focus();
+    },
+
+    /**
+     * This is used to cancel a keyboard version of a drag and drop.
+     *
+     * @method global_cancel_keyboard_drag
+     */
+    global_cancel_keyboard_drag: function() {
+        if (M.core.dragdrop.keydragcontainer) {
+            M.core.dragdrop.keydragcontainer.setAttribute('aria-grabbed', 'false');
+            M.core.dragdrop.keydraghandle.focus();
+            M.core.dragdrop.keydragcontainer = null;
+        }
+    },
+
+    /**
+     * Process key events on the drag handles.
+     *
+     * @method global_keydown
+     * @param {EventFacade} e The keydown / click event on the drag handle.
+     */
+    global_keydown: function(e) {
+        var draghandle = e.target.ancestor('.' + MOVEICON.cssclass, true),
+            dragcontainer,
+            draggroups;
+
+        if (draghandle === null) {
+            // The element clicked did not have a a draghandle in it's lineage.
+            return;
+        }
+
+        if (e.keyCode === 27 ) {
+            // Escape to cancel from anywhere.
+            this.global_cancel_keyboard_drag();
+            e.preventDefault();
+            return;
+        }
+
+        // Only process events on a drag handle.
+        if (!draghandle.hasClass(MOVEICON.cssclass)) {
+            return;
+        }
+
+        // Do nothing if not space or enter.
+        if (e.keyCode !== 13 && e.keyCode !== 32 && e.type !== 'click') {
+            return;
+        }
+
+        // Check the drag groups to see if we are the handler for this node.
+        draggroups = draghandle.getAttribute('data-draggroups').split(' ');
+        var i, j, validgroup = false;
+
+        for (i = 0; i < draggroups.length; i++) {
+            for (j = 0; j < this.groups.length; j++) {
+                if (draggroups[i] === this.groups[j]) {
+                    validgroup = true;
+                    break;
+                }
+            }
+            if (validgroup) {
+                break;
+            }
+        }
+        if (!validgroup) {
+            return;
+        }
+
+        // Valid event - start the keyboard drag.
+        dragcontainer = draghandle.ancestor('.yui3-dd-drop');
+        this.global_start_keyboard_drag(e, draghandle, dragcontainer);
+
+        e.preventDefault();
+    },
+
+
+    // Abstract functions definitions.
+
+    /**
+     * Callback to use when dragging starts.
+     *
+     * @method drag_start
+     * @param {EventFacade} e
+     */
+    drag_start: function() {},
+
+    /**
+     * Callback to use when dragging ends.
+     *
+     * @method drag_end
+     * @param {EventFacade} e
+     */
+    drag_end: function() {},
+
+    /**
+     * Callback to use during dragging.
+     *
+     * @method drag_drag
+     * @param {EventFacade} e
+     */
+    drag_drag: function() {},
+
+    /**
+     * Callback to use when dragging ends and is not over a drop target.
+     *
+     * @method drag_dropmiss
+     * @param {EventFacade} e
+     */
+    drag_dropmiss: function() {},
+
+    /**
+     * Callback to use when a drop over event occurs.
+     *
+     * @method drop_over
+     * @param {EventFacade} e
+     */
+    drop_over: function() {},
+
+    /**
+     * Callback to use on drop:hit.
+     *
+     * @method drop_hit
+     * @param {EventFacade} e
+     */
+    drop_hit: function() {}
+}, {
+    NAME: 'dragdrop',
+    ATTRS: {}
+});
+
+M.core = M.core || {};
+M.core.dragdrop = DRAGDROP;
diff --git a/lib/yui/src/dragdrop/meta/dragdrop.json b/lib/yui/src/dragdrop/meta/dragdrop.json
new file mode 100644 (file)
index 0000000..4e4f51c
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "moodle-core-dragdrop": {
+        "requires": [
+            "base",
+            "node",
+            "io",
+            "dom",
+            "dd",
+            "event-key",
+            "event-focus",
+            "moodle-core-notification"
+        ]
+    }
+}
index b6a84b7..e405752 100644 (file)
@@ -7,7 +7,7 @@ http://yuilibrary.com/license/
 
 if (typeof __coverage__ === 'undefined') { __coverage__ = {}; }
 if (!__coverage__['build/io-upload-iframe/io-upload-iframe.js']) {
-   __coverage__['build/io-upload-iframe/io-upload-iframe.js'] = {"path":"build/io-upload-iframe/io-upload-iframe.js","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":28},"end":{"line":1,"column":47}}},"2":{"name":"_cFrame","line":27,"loc":{"start":{"line":27,"column":0},"end":{"line":27,"column":27}}},"3":{"name":"(anonymous_3)","line":34,"loc":{"start":{"line":34,"column":17},"end":{"line":34,"column":28}}},"4":{"name":"_dFrame","line":45,"loc":{"start":{"line":45,"column":0},"end":{"line":45,"column":21}}},"5":{"name":"(anonymous_5)","line":61,"loc":{"start":{"line":61,"column":14},"end":{"line":61,"column":29}}},"6":{"name":"(anonymous_6)","line":92,"loc":{"start":{"line":92,"column":17},"end":{"line":92,"column":32}}},"7":{"name":"(anonymous_7)","line":110,"loc":{"start":{"line":110,"column":15},"end":{"line":110,"column":36}}},"8":{"name":"(anonymous_8)","line":131,"loc":{"start":{"line":131,"column":17},"end":{"line":131,"column":32}}},"9":{"name":"(anonymous_9)","line":132,"loc":{"start":{"line":132,"column":25},"end":{"line":132,"column":40}}},"10":{"name":"(anonymous_10)","line":152,"loc":{"start":{"line":152,"column":25},"end":{"line":152,"column":40}}},"11":{"name":"(anonymous_11)","line":156,"loc":{"start":{"line":156,"column":12},"end":{"line":156,"column":23}}},"12":{"name":"(anonymous_12)","line":171,"loc":{"start":{"line":171,"column":25},"end":{"line":171,"column":38}}},"13":{"name":"(anonymous_13)","line":187,"loc":{"start":{"line":187,"column":21},"end":{"line":187,"column":36}}},"14":{"name":"(anonymous_14)","line":217,"loc":{"start":{"line":217,"column":22},"end":{"line":217,"column":33}}},"15":{"name":"(anonymous_15)","line":230,"loc":{"start":{"line":230,"column":13},"end":{"line":230,"column":33}}},"16":{"name":"(anonymous_16)","line":257,"loc":{"start":{"line":257,"column":19},"end":{"line":257,"column":30}}},"17":{"name":"(anonymous_17)","line":269,"loc":{"start":{"line":269,"column":26},"end":{"line":269,"column":37}}},"18":{"name":"(anonymous_18)","line":276,"loc":{"start":{"line":276,"column":12},"end":{"line":276,"column":32}}},"19":{"name":"(anonymous_19)","line":281,"loc":{"start":{"line":281,"column":9},"end":{"line":281,"column":39}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":302,"column":53}},"2":{"start":{"line":11,"column":0},"end":{"line":15,"column":30}},"3":{"start":{"line":27,"column":0},"end":{"line":35,"column":1}},"4":{"start":{"line":28,"column":4},"end":{"line":28,"column":104}},"5":{"start":{"line":29,"column":8},"end":{"line":29,"column":44}},"6":{"start":{"line":30,"column":8},"end":{"line":30,"column":38}},"7":{"start":{"line":31,"column":8},"end":{"line":31,"column":39}},"8":{"start":{"line":32,"column":8},"end":{"line":32,"column":37}},"9":{"start":{"line":34,"column":4},"end":{"line":34,"column":80}},"10":{"start":{"line":34,"column":30},"end":{"line":34,"column":55}},"11":{"start":{"line":45,"column":0},"end":{"line":48,"column":1}},"12":{"start":{"line":46,"column":1},"end":{"line":46,"column":48}},"13":{"start":{"line":47,"column":1},"end":{"line":47,"column":53}},"14":{"start":{"line":50,"column":0},"end":{"line":299,"column":9}},"15":{"start":{"line":64,"column":8},"end":{"line":66,"column":9}},"16":{"start":{"line":65,"column":12},"end":{"line":65,"column":43}},"17":{"start":{"line":68,"column":8},"end":{"line":70,"column":17}},"18":{"start":{"line":72,"column":8},"end":{"line":78,"column":9}},"19":{"start":{"line":73,"column":12},"end":{"line":73,"column":44}},"20":{"start":{"line":74,"column":12},"end":{"line":74,"column":33}},"21":{"start":{"line":75,"column":12},"end":{"line":75,"column":70}},"22":{"start":{"line":76,"column":12},"end":{"line":76,"column":111}},"23":{"start":{"line":77,"column":12},"end":{"line":77,"column":32}},"24":{"start":{"line":80,"column":8},"end":{"line":80,"column":17}},"25":{"start":{"line":93,"column":8},"end":{"line":93,"column":17}},"26":{"start":{"line":95,"column":8},"end":{"line":97,"column":9}},"27":{"start":{"line":96,"column":12},"end":{"line":96,"column":32}},"28":{"start":{"line":112,"column":8},"end":{"line":115,"column":10}},"29":{"start":{"line":117,"column":8},"end":{"line":117,"column":38}},"30":{"start":{"line":118,"column":8},"end":{"line":118,"column":41}},"31":{"start":{"line":119,"column":8},"end":{"line":119,"column":52}},"32":{"start":{"line":120,"column":8},"end":{"line":120,"column":89}},"33":{"start":{"line":132,"column":8},"end":{"line":139,"column":11}},"34":{"start":{"line":133,"column":12},"end":{"line":138,"column":13}},"35":{"start":{"line":134,"column":16},"end":{"line":134,"column":37}},"36":{"start":{"line":137,"column":16},"end":{"line":137,"column":37}},"37":{"start":{"line":153,"column":8},"end":{"line":153,"column":22}},"38":{"start":{"line":155,"column":8},"end":{"line":161,"column":26}},"39":{"start":{"line":157,"column":16},"end":{"line":157,"column":29}},"40":{"start":{"line":158,"column":16},"end":{"line":158,"column":41}},"41":{"start":{"line":159,"column":16},"end":{"line":159,"column":34}},"42":{"start":{"line":160,"column":16},"end":{"line":160,"column":29}},"43":{"start":{"line":172,"column":8},"end":{"line":172,"column":22}},"44":{"start":{"line":174,"column":8},"end":{"line":174,"column":40}},"45":{"start":{"line":175,"column":8},"end":{"line":175,"column":31}},"46":{"start":{"line":188,"column":8},"end":{"line":191,"column":14}},"47":{"start":{"line":193,"column":8},"end":{"line":195,"column":9}},"48":{"start":{"line":194,"column":12},"end":{"line":194,"column":41}},"49":{"start":{"line":197,"column":2},"end":{"line":210,"column":3}},"50":{"start":{"line":198,"column":3},"end":{"line":206,"column":4}},"51":{"start":{"line":201,"column":4},"end":{"line":201,"column":33}},"52":{"start":{"line":202,"column":4},"end":{"line":202,"column":57}},"53":{"start":{"line":205,"column":4},"end":{"line":205,"column":30}},"54":{"start":{"line":209,"column":3},"end":{"line":209,"column":26}},"55":{"start":{"line":212,"column":8},"end":{"line":212,"column":26}},"56":{"start":{"line":213,"column":8},"end":{"line":213,"column":21}},"57":{"start":{"line":217,"column":8},"end":{"line":217,"column":56}},"58":{"start":{"line":217,"column":35},"end":{"line":217,"column":49}},"59":{"start":{"line":231,"column":8},"end":{"line":233,"column":19}},"60":{"start":{"line":237,"column":8},"end":{"line":237,"column":35}},"61":{"start":{"line":238,"column":8},"end":{"line":240,"column":9}},"62":{"start":{"line":239,"column":12},"end":{"line":239,"column":44}},"63":{"start":{"line":244,"column":8},"end":{"line":246,"column":9}},"64":{"start":{"line":245,"column":12},"end":{"line":245,"column":41}},"65":{"start":{"line":249,"column":8},"end":{"line":249,"column":19}},"66":{"start":{"line":250,"column":8},"end":{"line":250,"column":23}},"67":{"start":{"line":251,"column":8},"end":{"line":253,"column":9}},"68":{"start":{"line":252,"column":12},"end":{"line":252,"column":38}},"69":{"start":{"line":255,"column":8},"end":{"line":273,"column":10}},"70":{"start":{"line":258,"column":16},"end":{"line":258,"column":29}},"71":{"start":{"line":259,"column":16},"end":{"line":259,"column":39}},"72":{"start":{"line":260,"column":16},"end":{"line":267,"column":17}},"73":{"start":{"line":261,"column":20},"end":{"line":261,"column":34}},"74":{"start":{"line":262,"column":20},"end":{"line":262,"column":38}},"75":{"start":{"line":263,"column":20},"end":{"line":263,"column":33}},"76":{"start":{"line":266,"column":20},"end":{"line":266,"column":33}},"77":{"start":{"line":270,"column":16},"end":{"line":270,"column":65}},"78":{"start":{"line":277,"column":8},"end":{"line":277,"column":28}},"79":{"start":{"line":278,"column":8},"end":{"line":278,"column":39}},"80":{"start":{"line":282,"column":8},"end":{"line":282,"column":21}},"81":{"start":{"line":284,"column":8},"end":{"line":295,"column":9}},"82":{"start":{"line":285,"column":12},"end":{"line":285,"column":31}},"83":{"start":{"line":287,"column":12},"end":{"line":294,"column":13}},"84":{"start":{"line":288,"column":16},"end":{"line":288,"column":26}},"85":{"start":{"line":291,"column":16},"end":{"line":291,"column":91}},"86":{"start":{"line":293,"column":16},"end":{"line":293,"column":62}},"87":{"start":{"line":297,"column":8},"end":{"line":297,"column":52}}},"branchMap":{"1":{"line":13,"type":"binary-expr","locations":[{"start":{"line":13,"column":12},"end":{"line":13,"column":26}},{"start":{"line":13,"column":30},"end":{"line":13,"column":49}}]},"2":{"line":64,"type":"if","locations":[{"start":{"line":64,"column":8},"end":{"line":64,"column":8}},{"start":{"line":64,"column":8},"end":{"line":64,"column":8}}]},"3":{"line":76,"type":"cond-expr","locations":[{"start":{"line":76,"column":41},"end":{"line":76,"column":53}},{"start":{"line":76,"column":56},"end":{"line":76,"column":110}}]},"4":{"line":120,"type":"cond-expr","locations":[{"start":{"line":120,"column":42},"end":{"line":120,"column":52}},{"start":{"line":120,"column":55},"end":{"line":120,"column":64}}]},"5":{"line":120,"type":"binary-expr","locations":[{"start":{"line":120,"column":23},"end":{"line":120,"column":30}},{"start":{"line":120,"column":34},"end":{"line":120,"column":39}}]},"6":{"line":133,"type":"if","locations":[{"start":{"line":133,"column":12},"end":{"line":133,"column":12}},{"start":{"line":133,"column":12},"end":{"line":133,"column":12}}]},"7":{"line":193,"type":"if","locations":[{"start":{"line":193,"column":8},"end":{"line":193,"column":8}},{"start":{"line":193,"column":8},"end":{"line":193,"column":8}}]},"8":{"line":198,"type":"if","locations":[{"start":{"line":198,"column":3},"end":{"line":198,"column":3}},{"start":{"line":198,"column":3},"end":{"line":198,"column":3}}]},"9":{"line":202,"type":"cond-expr","locations":[{"start":{"line":202,"column":27},"end":{"line":202,"column":40}},{"start":{"line":202,"column":43},"end":{"line":202,"column":56}}]},"10":{"line":232,"type":"cond-expr","locations":[{"start":{"line":232,"column":50},"end":{"line":232,"column":77}},{"start":{"line":232,"column":80},"end":{"line":232,"column":89}}]},"11":{"line":238,"type":"if","locations":[{"start":{"line":238,"column":8},"end":{"line":238,"column":8}},{"start":{"line":238,"column":8},"end":{"line":238,"column":8}}]},"12":{"line":244,"type":"if","locations":[{"start":{"line":244,"column":8},"end":{"line":244,"column":8}},{"start":{"line":244,"column":8},"end":{"line":244,"column":8}}]},"13":{"line":251,"type":"if","locations":[{"start":{"line":251,"column":8},"end":{"line":251,"column":8}},{"start":{"line":251,"column":8},"end":{"line":251,"column":8}}]},"14":{"line":260,"type":"if","locations":[{"start":{"line":260,"column":16},"end":{"line":260,"column":16}},{"start":{"line":260,"column":16},"end":{"line":260,"column":16}}]},"15":{"line":270,"type":"cond-expr","locations":[{"start":{"line":270,"column":52},"end":{"line":270,"column":56}},{"start":{"line":270,"column":59},"end":{"line":270,"column":64}}]},"16":{"line":284,"type":"if","locations":[{"start":{"line":284,"column":8},"end":{"line":284,"column":8}},{"start":{"line":284,"column":8},"end":{"line":284,"column":8}}]},"17":{"line":287,"type":"if","locations":[{"start":{"line":287,"column":12},"end":{"line":287,"column":12}},{"start":{"line":287,"column":12},"end":{"line":287,"column":12}}]},"18":{"line":287,"type":"binary-expr","locations":[{"start":{"line":287,"column":16},"end":{"line":287,"column":20}},{"start":{"line":287,"column":24},"end":{"line":287,"column":35}}]},"19":{"line":291,"type":"cond-expr","locations":[{"start":{"line":291,"column":55},"end":{"line":291,"column":80}},{"start":{"line":291,"column":83},"end":{"line":291,"column":90}}]}},"code":["(function () { YUI.add('io-upload-iframe', function (Y, NAME) {","","/**","Extends the IO  to enable file uploads, with HTML forms","using an iframe as the transport medium.","@module io","@submodule io-upload-iframe","@for IO","**/","","var w = Y.config.win,","    d = Y.config.doc,","    _std = (d.documentMode && d.documentMode >= 8),","    _d = decodeURIComponent,","    _end = Y.IO.prototype.end;","","/**"," * Creates the iframe transported used in file upload"," * transactions, and binds the response event handler."," *"," * @method _cFrame"," * @private"," * @param {Object} o Transaction object generated by _create()."," * @param {Object} c Configuration object passed to YUI.io()."," * @param {Object} io"," */","function _cFrame(o, c, io) {","    var i = Y.Node.create('<iframe src=\"#\" id=\"io_iframe' + o.id + '\" name=\"io_iframe' + o.id + '\" />');","        i._node.style.position = 'absolute';","        i._node.style.top = '-1000px';","        i._node.style.left = '-1000px';","        Y.one('body').appendChild(i);","    // Bind the onload handler to the iframe to detect the file upload response.","    Y.on(\"load\", function() { io._uploadComplete(o, c); }, '#io_iframe' + o.id);","}","","/**"," * Removes the iframe transport used in the file upload"," * transaction."," *"," * @method _dFrame"," * @private"," * @param {Number} id The transaction ID used in the iframe's creation."," */","function _dFrame(id) {","\tY.Event.purgeElement('#io_iframe' + id, false);","\tY.one('body').removeChild(Y.one('#io_iframe' + id));","}","","Y.mix(Y.IO.prototype, {","   /**","    * Parses the POST data object and creates hidden form elements","    * for each key-value, and appends them to the HTML form object.","    * @method _addData","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {String} s The key-value POST data.","    * @return {Array} o Array of created fields.","    */","    _addData: function(f, s) {","        // Serialize an object into a key-value string using","        // querystring-stringify-simple.","        if (Y.Lang.isObject(s)) {","            s = Y.QueryString.stringify(s);","        }","","        var o = [],","            m = s.split('='),","            i, l;","","        for (i = 0, l = m.length - 1; i < l; i++) {","            o[i] = d.createElement('input');","            o[i].type = 'hidden';","            o[i].name = _d(m[i].substring(m[i].lastIndexOf('&') + 1));","            o[i].value = (i + 1 === l) ? _d(m[i + 1]) : _d(m[i + 1].substring(0, (m[i + 1].lastIndexOf('&'))));","            f.appendChild(o[i]);","        }","","        return o;","    },","","   /**","    * Removes the custom fields created to pass additional POST","    * data, along with the HTML form fields.","    * @method _removeData","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {Object} o HTML form fields created from configuration.data.","    */","    _removeData: function(f, o) {","        var i, l;","","        for (i = 0, l = o.length; i < l; i++) {","            f.removeChild(o[i]);","        }","    },","","   /**","    * Sets the appropriate attributes and values to the HTML","    * form, in preparation of a file upload transaction.","    * @method _setAttrs","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {Object} id The Transaction ID.","    * @param {Object} uri Qualified path to transaction resource.","    */","    _setAttrs: function(f, id, uri) {","        // Track original HTML form attribute values.","        this._originalFormAttrs = {","            action: f.getAttribute('action'),","            target: f.getAttribute('target')","        };","","        f.setAttribute('action', uri);","        f.setAttribute('method', 'POST');","        f.setAttribute('target', 'io_iframe' + id );","        f.setAttribute(Y.UA.ie && !_std ? 'encoding' : 'enctype', 'multipart/form-data');","    },","","   /**","    * Reset the HTML form attributes to their original values.","    * @method _resetAttrs","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {Object} a Object of original attributes.","    */","    _resetAttrs: function(f, a) {","        Y.Object.each(a, function(v, p) {","            if (v) {","                f.setAttribute(p, v);","            }","            else {","                f.removeAttribute(p);","            }","        });","    },","","   /**","    * Starts timeout count if the configuration object","    * has a defined timeout property.","    *","    * @method _startUploadTimeout","    * @private","    * @static","    * @param {Object} o Transaction object generated by _create().","    * @param {Object} c Configuration object passed to YUI.io().","    */","    _startUploadTimeout: function(o, c) {","        var io = this;","","        io._timeout[o.id] = w.setTimeout(","            function() {","                o.status = 0;","                o.statusText = 'timeout';","                io.complete(o, c);","                io.end(o, c);","            }, c.timeout);","    },","","   /**","    * Clears the timeout interval started by _startUploadTimeout().","    * @method _clearUploadTimeout","    * @private","    * @static","    * @param {Number} id - Transaction ID.","    */","    _clearUploadTimeout: function(id) {","        var io = this;","","        w.clearTimeout(io._timeout[id]);","        delete io._timeout[id];","    },","","   /**","    * Bound to the iframe's Load event and processes","    * the response data.","    * @method _uploadComplete","    * @private","    * @static","    * @param {Object} o The transaction object","    * @param {Object} c Configuration object for the transaction.","    */","    _uploadComplete: function(o, c) {","        var io = this,","            d = Y.one('#io_iframe' + o.id).get('contentWindow.document'),","            b = d.one('body'),","            p;","","        if (c.timeout) {","            io._clearUploadTimeout(o.id);","        }","","\t\ttry {","\t\t\tif (b) {","\t\t\t\t// When a response Content-Type of \"text/plain\" is used, Firefox and Safari","\t\t\t\t// will wrap the response string with <pre></pre>.","\t\t\t\tp = b.one('pre:first-child');","\t\t\t\to.c.responseText = p ? p.get('text') : b.get('text');","\t\t\t}","\t\t\telse {","\t\t\t\to.c.responseXML = d._node;","\t\t\t}","\t\t}","\t\tcatch (e) {","\t\t\to.e = \"upload failure\";","\t\t}","","        io.complete(o, c);","        io.end(o, c);","        // The transaction is complete, so call _dFrame to remove","        // the event listener bound to the iframe transport, and then","        // destroy the iframe.","        w.setTimeout( function() { _dFrame(o.id); }, 0);","    },","","   /**","    * Uploads HTML form data, inclusive of files/attachments,","    * using the iframe created in _create to facilitate the transaction.","    * @method _upload","    * @private","    * @static","    * @param {Object} o The transaction object","    * @param {Object} uri Qualified path to transaction resource.","    * @param {Object} c Configuration object for the transaction.","    */","    _upload: function(o, uri, c) {","        var io = this,","            f = (typeof c.form.id === 'string') ? d.getElementById(c.form.id) : c.form.id,","            fields;","","        // Initialize the HTML form properties in case they are","        // not defined in the HTML form.","        io._setAttrs(f, o.id, uri);","        if (c.data) {","            fields = io._addData(f, c.data);","        }","","        // Start polling if a callback is present and the timeout","        // property has been defined.","        if (c.timeout) {","            io._startUploadTimeout(o, c);","        }","","        // Start file upload.","        f.submit();","        io.start(o, c);","        if (c.data) {","            io._removeData(f, fields);","        }","","        return {","            id: o.id,","            abort: function() {","                o.status = 0;","                o.statusText = 'abort';","                if (Y.one('#io_iframe' + o.id)) {","                    _dFrame(o.id);","                    io.complete(o, c);","                    io.end(o, c);","                }","                else {","                    return false;","                }","            },","            isInProgress: function() {","                return Y.one('#io_iframe' + o.id) ? true : false;","            },","            io: io","        };","    },","","    upload: function(o, uri, c) {","        _cFrame(o, c, this);","        return this._upload(o, uri, c);","    },","","    end: function(transaction, config) {","        var form, io;","","        if (config) {","            form = config.form;","","            if (form && form.upload) {","                io = this;","","                // Restore HTML form attributes to their original values.","                form = (typeof form.id === 'string') ? d.getElementById(form.id) : form.id;","","                io._resetAttrs(form, this._originalFormAttrs);","            }","        }","","        return _end.call(this, transaction, config);","    }","}, true);","","","}, '3.13.0', {\"requires\": [\"io-base\", \"node-base\"]});","","}());"]};
+   __coverage__['build/io-upload-iframe/io-upload-iframe.js'] = {"path":"build/io-upload-iframe/io-upload-iframe.js","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":28},"end":{"line":1,"column":47}}},"2":{"name":"_cFrame","line":27,"loc":{"start":{"line":27,"column":0},"end":{"line":27,"column":27}}},"3":{"name":"(anonymous_3)","line":34,"loc":{"start":{"line":34,"column":17},"end":{"line":34,"column":28}}},"4":{"name":"_dFrame","line":45,"loc":{"start":{"line":45,"column":0},"end":{"line":45,"column":21}}},"5":{"name":"(anonymous_5)","line":61,"loc":{"start":{"line":61,"column":14},"end":{"line":61,"column":29}}},"6":{"name":"(anonymous_6)","line":92,"loc":{"start":{"line":92,"column":17},"end":{"line":92,"column":32}}},"7":{"name":"(anonymous_7)","line":110,"loc":{"start":{"line":110,"column":15},"end":{"line":110,"column":36}}},"8":{"name":"(anonymous_8)","line":131,"loc":{"start":{"line":131,"column":17},"end":{"line":131,"column":32}}},"9":{"name":"(anonymous_9)","line":132,"loc":{"start":{"line":132,"column":25},"end":{"line":132,"column":40}}},"10":{"name":"(anonymous_10)","line":152,"loc":{"start":{"line":152,"column":25},"end":{"line":152,"column":40}}},"11":{"name":"(anonymous_11)","line":156,"loc":{"start":{"line":156,"column":12},"end":{"line":156,"column":23}}},"12":{"name":"(anonymous_12)","line":171,"loc":{"start":{"line":171,"column":25},"end":{"line":171,"column":38}}},"13":{"name":"(anonymous_13)","line":187,"loc":{"start":{"line":187,"column":21},"end":{"line":187,"column":36}}},"14":{"name":"(anonymous_14)","line":217,"loc":{"start":{"line":217,"column":22},"end":{"line":217,"column":33}}},"15":{"name":"(anonymous_15)","line":230,"loc":{"start":{"line":230,"column":13},"end":{"line":230,"column":33}}},"16":{"name":"(anonymous_16)","line":257,"loc":{"start":{"line":257,"column":19},"end":{"line":257,"column":30}}},"17":{"name":"(anonymous_17)","line":269,"loc":{"start":{"line":269,"column":26},"end":{"line":269,"column":37}}},"18":{"name":"(anonymous_18)","line":276,"loc":{"start":{"line":276,"column":12},"end":{"line":276,"column":32}}},"19":{"name":"(anonymous_19)","line":281,"loc":{"start":{"line":281,"column":9},"end":{"line":281,"column":39}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":305,"column":53}},"2":{"start":{"line":11,"column":0},"end":{"line":15,"column":30}},"3":{"start":{"line":27,"column":0},"end":{"line":35,"column":1}},"4":{"start":{"line":28,"column":4},"end":{"line":28,"column":104}},"5":{"start":{"line":29,"column":8},"end":{"line":29,"column":44}},"6":{"start":{"line":30,"column":8},"end":{"line":30,"column":38}},"7":{"start":{"line":31,"column":8},"end":{"line":31,"column":39}},"8":{"start":{"line":32,"column":8},"end":{"line":32,"column":37}},"9":{"start":{"line":34,"column":4},"end":{"line":34,"column":80}},"10":{"start":{"line":34,"column":30},"end":{"line":34,"column":55}},"11":{"start":{"line":45,"column":0},"end":{"line":48,"column":1}},"12":{"start":{"line":46,"column":1},"end":{"line":46,"column":48}},"13":{"start":{"line":47,"column":1},"end":{"line":47,"column":53}},"14":{"start":{"line":50,"column":0},"end":{"line":302,"column":9}},"15":{"start":{"line":64,"column":8},"end":{"line":66,"column":9}},"16":{"start":{"line":65,"column":12},"end":{"line":65,"column":43}},"17":{"start":{"line":68,"column":8},"end":{"line":70,"column":17}},"18":{"start":{"line":72,"column":8},"end":{"line":78,"column":9}},"19":{"start":{"line":73,"column":12},"end":{"line":73,"column":44}},"20":{"start":{"line":74,"column":12},"end":{"line":74,"column":33}},"21":{"start":{"line":75,"column":12},"end":{"line":75,"column":70}},"22":{"start":{"line":76,"column":12},"end":{"line":76,"column":111}},"23":{"start":{"line":77,"column":12},"end":{"line":77,"column":32}},"24":{"start":{"line":80,"column":8},"end":{"line":80,"column":17}},"25":{"start":{"line":93,"column":8},"end":{"line":93,"column":17}},"26":{"start":{"line":95,"column":8},"end":{"line":97,"column":9}},"27":{"start":{"line":96,"column":12},"end":{"line":96,"column":32}},"28":{"start":{"line":112,"column":8},"end":{"line":115,"column":10}},"29":{"start":{"line":117,"column":8},"end":{"line":117,"column":38}},"30":{"start":{"line":118,"column":8},"end":{"line":118,"column":41}},"31":{"start":{"line":119,"column":8},"end":{"line":119,"column":52}},"32":{"start":{"line":120,"column":8},"end":{"line":120,"column":89}},"33":{"start":{"line":132,"column":8},"end":{"line":139,"column":11}},"34":{"start":{"line":133,"column":12},"end":{"line":138,"column":13}},"35":{"start":{"line":134,"column":16},"end":{"line":134,"column":37}},"36":{"start":{"line":137,"column":16},"end":{"line":137,"column":37}},"37":{"start":{"line":153,"column":8},"end":{"line":153,"column":22}},"38":{"start":{"line":155,"column":8},"end":{"line":161,"column":26}},"39":{"start":{"line":157,"column":16},"end":{"line":157,"column":29}},"40":{"start":{"line":158,"column":16},"end":{"line":158,"column":41}},"41":{"start":{"line":159,"column":16},"end":{"line":159,"column":34}},"42":{"start":{"line":160,"column":16},"end":{"line":160,"column":29}},"43":{"start":{"line":172,"column":8},"end":{"line":172,"column":22}},"44":{"start":{"line":174,"column":8},"end":{"line":174,"column":40}},"45":{"start":{"line":175,"column":8},"end":{"line":175,"column":31}},"46":{"start":{"line":188,"column":8},"end":{"line":191,"column":14}},"47":{"start":{"line":193,"column":8},"end":{"line":195,"column":9}},"48":{"start":{"line":194,"column":12},"end":{"line":194,"column":41}},"49":{"start":{"line":197,"column":2},"end":{"line":210,"column":3}},"50":{"start":{"line":198,"column":3},"end":{"line":206,"column":4}},"51":{"start":{"line":201,"column":4},"end":{"line":201,"column":33}},"52":{"start":{"line":202,"column":4},"end":{"line":202,"column":57}},"53":{"start":{"line":205,"column":4},"end":{"line":205,"column":30}},"54":{"start":{"line":209,"column":3},"end":{"line":209,"column":26}},"55":{"start":{"line":212,"column":8},"end":{"line":212,"column":26}},"56":{"start":{"line":213,"column":8},"end":{"line":213,"column":21}},"57":{"start":{"line":217,"column":8},"end":{"line":217,"column":56}},"58":{"start":{"line":217,"column":35},"end":{"line":217,"column":49}},"59":{"start":{"line":231,"column":8},"end":{"line":233,"column":19}},"60":{"start":{"line":237,"column":8},"end":{"line":237,"column":35}},"61":{"start":{"line":238,"column":8},"end":{"line":240,"column":9}},"62":{"start":{"line":239,"column":12},"end":{"line":239,"column":44}},"63":{"start":{"line":244,"column":8},"end":{"line":246,"column":9}},"64":{"start":{"line":245,"column":12},"end":{"line":245,"column":41}},"65":{"start":{"line":249,"column":8},"end":{"line":249,"column":19}},"66":{"start":{"line":250,"column":8},"end":{"line":250,"column":23}},"67":{"start":{"line":251,"column":8},"end":{"line":253,"column":9}},"68":{"start":{"line":252,"column":12},"end":{"line":252,"column":38}},"69":{"start":{"line":255,"column":8},"end":{"line":273,"column":10}},"70":{"start":{"line":258,"column":16},"end":{"line":258,"column":29}},"71":{"start":{"line":259,"column":16},"end":{"line":259,"column":39}},"72":{"start":{"line":260,"column":16},"end":{"line":267,"column":17}},"73":{"start":{"line":261,"column":20},"end":{"line":261,"column":34}},"74":{"start":{"line":262,"column":20},"end":{"line":262,"column":38}},"75":{"start":{"line":263,"column":20},"end":{"line":263,"column":33}},"76":{"start":{"line":266,"column":20},"end":{"line":266,"column":33}},"77":{"start":{"line":270,"column":16},"end":{"line":270,"column":65}},"78":{"start":{"line":277,"column":8},"end":{"line":277,"column":28}},"79":{"start":{"line":278,"column":8},"end":{"line":278,"column":39}},"80":{"start":{"line":282,"column":8},"end":{"line":282,"column":21}},"81":{"start":{"line":284,"column":8},"end":{"line":298,"column":9}},"82":{"start":{"line":285,"column":12},"end":{"line":285,"column":31}},"83":{"start":{"line":287,"column":12},"end":{"line":297,"column":13}},"84":{"start":{"line":288,"column":16},"end":{"line":288,"column":26}},"85":{"start":{"line":291,"column":16},"end":{"line":291,"column":91}},"86":{"start":{"line":294,"column":16},"end":{"line":296,"column":17}},"87":{"start":{"line":295,"column":20},"end":{"line":295,"column":66}},"88":{"start":{"line":300,"column":8},"end":{"line":300,"column":52}}},"branchMap":{"1":{"line":13,"type":"binary-expr","locations":[{"start":{"line":13,"column":12},"end":{"line":13,"column":26}},{"start":{"line":13,"column":30},"end":{"line":13,"column":49}}]},"2":{"line":64,"type":"if","locations":[{"start":{"line":64,"column":8},"end":{"line":64,"column":8}},{"start":{"line":64,"column":8},"end":{"line":64,"column":8}}]},"3":{"line":76,"type":"cond-expr","locations":[{"start":{"line":76,"column":41},"end":{"line":76,"column":53}},{"start":{"line":76,"column":56},"end":{"line":76,"column":110}}]},"4":{"line":120,"type":"cond-expr","locations":[{"start":{"line":120,"column":42},"end":{"line":120,"column":52}},{"start":{"line":120,"column":55},"end":{"line":120,"column":64}}]},"5":{"line":120,"type":"binary-expr","locations":[{"start":{"line":120,"column":23},"end":{"line":120,"column":30}},{"start":{"line":120,"column":34},"end":{"line":120,"column":39}}]},"6":{"line":133,"type":"if","locations":[{"start":{"line":133,"column":12},"end":{"line":133,"column":12}},{"start":{"line":133,"column":12},"end":{"line":133,"column":12}}]},"7":{"line":193,"type":"if","locations":[{"start":{"line":193,"column":8},"end":{"line":193,"column":8}},{"start":{"line":193,"column":8},"end":{"line":193,"column":8}}]},"8":{"line":198,"type":"if","locations":[{"start":{"line":198,"column":3},"end":{"line":198,"column":3}},{"start":{"line":198,"column":3},"end":{"line":198,"column":3}}]},"9":{"line":202,"type":"cond-expr","locations":[{"start":{"line":202,"column":27},"end":{"line":202,"column":40}},{"start":{"line":202,"column":43},"end":{"line":202,"column":56}}]},"10":{"line":232,"type":"cond-expr","locations":[{"start":{"line":232,"column":50},"end":{"line":232,"column":77}},{"start":{"line":232,"column":80},"end":{"line":232,"column":89}}]},"11":{"line":238,"type":"if","locations":[{"start":{"line":238,"column":8},"end":{"line":238,"column":8}},{"start":{"line":238,"column":8},"end":{"line":238,"column":8}}]},"12":{"line":244,"type":"if","locations":[{"start":{"line":244,"column":8},"end":{"line":244,"column":8}},{"start":{"line":244,"column":8},"end":{"line":244,"column":8}}]},"13":{"line":251,"type":"if","locations":[{"start":{"line":251,"column":8},"end":{"line":251,"column":8}},{"start":{"line":251,"column":8},"end":{"line":251,"column":8}}]},"14":{"line":260,"type":"if","locations":[{"start":{"line":260,"column":16},"end":{"line":260,"column":16}},{"start":{"line":260,"column":16},"end":{"line":260,"column":16}}]},"15":{"line":270,"type":"cond-expr","locations":[{"start":{"line":270,"column":52},"end":{"line":270,"column":56}},{"start":{"line":270,"column":59},"end":{"line":270,"column":64}}]},"16":{"line":284,"type":"if","locations":[{"start":{"line":284,"column":8},"end":{"line":284,"column":8}},{"start":{"line":284,"column":8},"end":{"line":284,"column":8}}]},"17":{"line":287,"type":"if","locations":[{"start":{"line":287,"column":12},"end":{"line":287,"column":12}},{"start":{"line":287,"column":12},"end":{"line":287,"column":12}}]},"18":{"line":287,"type":"binary-expr","locations":[{"start":{"line":287,"column":16},"end":{"line":287,"column":20}},{"start":{"line":287,"column":24},"end":{"line":287,"column":35}}]},"19":{"line":291,"type":"cond-expr","locations":[{"start":{"line":291,"column":55},"end":{"line":291,"column":80}},{"start":{"line":291,"column":83},"end":{"line":291,"column":90}}]},"20":{"line":294,"type":"if","locations":[{"start":{"line":294,"column":16},"end":{"line":294,"column":16}},{"start":{"line":294,"column":16},"end":{"line":294,"column":16}}]}},"code":["(function () { YUI.add('io-upload-iframe', function (Y, NAME) {","","/**","Extends the IO  to enable file uploads, with HTML forms","using an iframe as the transport medium.","@module io","@submodule io-upload-iframe","@for IO","**/","","var w = Y.config.win,","    d = Y.config.doc,","    _std = (d.documentMode && d.documentMode >= 8),","    _d = decodeURIComponent,","    _end = Y.IO.prototype.end;","","/**"," * Creates the iframe transported used in file upload"," * transactions, and binds the response event handler."," *"," * @method _cFrame"," * @private"," * @param {Object} o Transaction object generated by _create()."," * @param {Object} c Configuration object passed to YUI.io()."," * @param {Object} io"," */","function _cFrame(o, c, io) {","    var i = Y.Node.create('<iframe src=\"#\" id=\"io_iframe' + o.id + '\" name=\"io_iframe' + o.id + '\" />');","        i._node.style.position = 'absolute';","        i._node.style.top = '-1000px';","        i._node.style.left = '-1000px';","        Y.one('body').appendChild(i);","    // Bind the onload handler to the iframe to detect the file upload response.","    Y.on(\"load\", function() { io._uploadComplete(o, c); }, '#io_iframe' + o.id);","}","","/**"," * Removes the iframe transport used in the file upload"," * transaction."," *"," * @method _dFrame"," * @private"," * @param {Number} id The transaction ID used in the iframe's creation."," */","function _dFrame(id) {","\tY.Event.purgeElement('#io_iframe' + id, false);","\tY.one('body').removeChild(Y.one('#io_iframe' + id));","}","","Y.mix(Y.IO.prototype, {","   /**","    * Parses the POST data object and creates hidden form elements","    * for each key-value, and appends them to the HTML form object.","    * @method _addData","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {String} s The key-value POST data.","    * @return {Array} o Array of created fields.","    */","    _addData: function(f, s) {","        // Serialize an object into a key-value string using","        // querystring-stringify-simple.","        if (Y.Lang.isObject(s)) {","            s = Y.QueryString.stringify(s);","        }","","        var o = [],","            m = s.split('='),","            i, l;","","        for (i = 0, l = m.length - 1; i < l; i++) {","            o[i] = d.createElement('input');","            o[i].type = 'hidden';","            o[i].name = _d(m[i].substring(m[i].lastIndexOf('&') + 1));","            o[i].value = (i + 1 === l) ? _d(m[i + 1]) : _d(m[i + 1].substring(0, (m[i + 1].lastIndexOf('&'))));","            f.appendChild(o[i]);","        }","","        return o;","    },","","   /**","    * Removes the custom fields created to pass additional POST","    * data, along with the HTML form fields.","    * @method _removeData","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {Object} o HTML form fields created from configuration.data.","    */","    _removeData: function(f, o) {","        var i, l;","","        for (i = 0, l = o.length; i < l; i++) {","            f.removeChild(o[i]);","        }","    },","","   /**","    * Sets the appropriate attributes and values to the HTML","    * form, in preparation of a file upload transaction.","    * @method _setAttrs","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {Object} id The Transaction ID.","    * @param {Object} uri Qualified path to transaction resource.","    */","    _setAttrs: function(f, id, uri) {","        // Track original HTML form attribute values.","        this._originalFormAttrs = {","            action: f.getAttribute('action'),","            target: f.getAttribute('target')","        };","","        f.setAttribute('action', uri);","        f.setAttribute('method', 'POST');","        f.setAttribute('target', 'io_iframe' + id );","        f.setAttribute(Y.UA.ie && !_std ? 'encoding' : 'enctype', 'multipart/form-data');","    },","","   /**","    * Reset the HTML form attributes to their original values.","    * @method _resetAttrs","    * @private","    * @static","    * @param {Object} f HTML form object.","    * @param {Object} a Object of original attributes.","    */","    _resetAttrs: function(f, a) {","        Y.Object.each(a, function(v, p) {","            if (v) {","                f.setAttribute(p, v);","            }","            else {","                f.removeAttribute(p);","            }","        });","    },","","   /**","    * Starts timeout count if the configuration object","    * has a defined timeout property.","    *","    * @method _startUploadTimeout","    * @private","    * @static","    * @param {Object} o Transaction object generated by _create().","    * @param {Object} c Configuration object passed to YUI.io().","    */","    _startUploadTimeout: function(o, c) {","        var io = this;","","        io._timeout[o.id] = w.setTimeout(","            function() {","                o.status = 0;","                o.statusText = 'timeout';","                io.complete(o, c);","                io.end(o, c);","            }, c.timeout);","    },","","   /**","    * Clears the timeout interval started by _startUploadTimeout().","    * @method _clearUploadTimeout","    * @private","    * @static","    * @param {Number} id - Transaction ID.","    */","    _clearUploadTimeout: function(id) {","        var io = this;","","        w.clearTimeout(io._timeout[id]);","        delete io._timeout[id];","    },","","   /**","    * Bound to the iframe's Load event and processes","    * the response data.","    * @method _uploadComplete","    * @private","    * @static","    * @param {Object} o The transaction object","    * @param {Object} c Configuration object for the transaction.","    */","    _uploadComplete: function(o, c) {","        var io = this,","            d = Y.one('#io_iframe' + o.id).get('contentWindow.document'),","            b = d.one('body'),","            p;","","        if (c.timeout) {","            io._clearUploadTimeout(o.id);","        }","","\t\ttry {","\t\t\tif (b) {","\t\t\t\t// When a response Content-Type of \"text/plain\" is used, Firefox and Safari","\t\t\t\t// will wrap the response string with <pre></pre>.","\t\t\t\tp = b.one('pre:first-child');","\t\t\t\to.c.responseText = p ? p.get('text') : b.get('text');","\t\t\t}","\t\t\telse {","\t\t\t\to.c.responseXML = d._node;","\t\t\t}","\t\t}","\t\tcatch (e) {","\t\t\to.e = \"upload failure\";","\t\t}","","        io.complete(o, c);","        io.end(o, c);","        // The transaction is complete, so call _dFrame to remove","        // the event listener bound to the iframe transport, and then","        // destroy the iframe.","        w.setTimeout( function() { _dFrame(o.id); }, 0);","    },","","   /**","    * Uploads HTML form data, inclusive of files/attachments,","    * using the iframe created in _create to facilitate the transaction.","    * @method _upload","    * @private","    * @static","    * @param {Object} o The transaction object","    * @param {Object} uri Qualified path to transaction resource.","    * @param {Object} c Configuration object for the transaction.","    */","    _upload: function(o, uri, c) {","        var io = this,","            f = (typeof c.form.id === 'string') ? d.getElementById(c.form.id) : c.form.id,","            fields;","","        // Initialize the HTML form properties in case they are","        // not defined in the HTML form.","        io._setAttrs(f, o.id, uri);","        if (c.data) {","            fields = io._addData(f, c.data);","        }","","        // Start polling if a callback is present and the timeout","        // property has been defined.","        if (c.timeout) {","            io._startUploadTimeout(o, c);","        }","","        // Start file upload.","        f.submit();","        io.start(o, c);","        if (c.data) {","            io._removeData(f, fields);","        }","","        return {","            id: o.id,","            abort: function() {","                o.status = 0;","                o.statusText = 'abort';","                if (Y.one('#io_iframe' + o.id)) {","                    _dFrame(o.id);","                    io.complete(o, c);","                    io.end(o, c);","                }","                else {","                    return false;","                }","            },","            isInProgress: function() {","                return Y.one('#io_iframe' + o.id) ? true : false;","            },","            io: io","        };","    },","","    upload: function(o, uri, c) {","        _cFrame(o, c, this);","        return this._upload(o, uri, c);","    },","","    end: function(transaction, config) {","        var form, io;","","        if (config) {","            form = config.form;","","            if (form && form.upload) {","                io = this;","","                // Restore HTML form attributes to their original values.","                form = (typeof form.id === 'string') ? d.getElementById(form.id) : form.id;","","                // Check whether the form still exists before resetting it.","                if (form) {","                    io._resetAttrs(form, this._originalFormAttrs);","                }","            }","        }","","        return _end.call(this, transaction, config);","    }","}, true);","","","}, '3.13.0', {\"requires\": [\"io-base\", \"node-base\"]});","","}());"]};
 }
 var __cov_qyKMyH$gi2n6_r8dBYGRlg = __coverage__['build/io-upload-iframe/io-upload-iframe.js'];
-__cov_qyKMyH$gi2n6_r8dBYGRlg.s['1']++;YUI.add('io-upload-iframe',function(Y,NAME){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['1']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['2']++;var w=Y.config.win,d=Y.config.doc,_std=(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['1'][0]++,d.documentMode)&&(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['1'][1]++,d.documentMode>=8),_d=decodeURIComponent,_end=Y.IO.prototype.end;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['3']++;function _cFrame(o,c,io){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['2']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['4']++;var i=Y.Node.create('<iframe src="#" id="io_iframe'+o.id+'" name="io_iframe'+o.id+'" />');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['5']++;i._node.style.position='absolute';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['6']++;i._node.style.top='-1000px';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['7']++;i._node.style.left='-1000px';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['8']++;Y.one('body').appendChild(i);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['9']++;Y.on('load',function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['3']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['10']++;io._uploadComplete(o,c);},'#io_iframe'+o.id);}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['11']++;function _dFrame(id){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['4']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['12']++;Y.Event.purgeElement('#io_iframe'+id,false);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['13']++;Y.one('body').removeChild(Y.one('#io_iframe'+id));}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['14']++;Y.mix(Y.IO.prototype,{_addData:function(f,s){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['5']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['15']++;if(Y.Lang.isObject(s)){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['2'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['16']++;s=Y.QueryString.stringify(s);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['2'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['17']++;var o=[],m=s.split('='),i,l;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['18']++;for(i=0,l=m.length-1;i<l;i++){__cov_qyKMyH$gi2n6_r8dBYGRlg.s['19']++;o[i]=d.createElement('input');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['20']++;o[i].type='hidden';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['21']++;o[i].name=_d(m[i].substring(m[i].lastIndexOf('&')+1));__cov_qyKMyH$gi2n6_r8dBYGRlg.s['22']++;o[i].value=i+1===l?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['3'][0]++,_d(m[i+1])):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['3'][1]++,_d(m[i+1].substring(0,m[i+1].lastIndexOf('&'))));__cov_qyKMyH$gi2n6_r8dBYGRlg.s['23']++;f.appendChild(o[i]);}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['24']++;return o;},_removeData:function(f,o){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['6']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['25']++;var i,l;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['26']++;for(i=0,l=o.length;i<l;i++){__cov_qyKMyH$gi2n6_r8dBYGRlg.s['27']++;f.removeChild(o[i]);}},_setAttrs:function(f,id,uri){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['7']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['28']++;this._originalFormAttrs={action:f.getAttribute('action'),target:f.getAttribute('target')};__cov_qyKMyH$gi2n6_r8dBYGRlg.s['29']++;f.setAttribute('action',uri);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['30']++;f.setAttribute('method','POST');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['31']++;f.setAttribute('target','io_iframe'+id);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['32']++;f.setAttribute((__cov_qyKMyH$gi2n6_r8dBYGRlg.b['5'][0]++,Y.UA.ie)&&(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['5'][1]++,!_std)?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['4'][0]++,'encoding'):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['4'][1]++,'enctype'),'multipart/form-data');},_resetAttrs:function(f,a){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['8']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['33']++;Y.Object.each(a,function(v,p){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['9']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['34']++;if(v){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['6'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['35']++;f.setAttribute(p,v);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['6'][1]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['36']++;f.removeAttribute(p);}});},_startUploadTimeout:function(o,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['10']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['37']++;var io=this;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['38']++;io._timeout[o.id]=w.setTimeout(function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['11']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['39']++;o.status=0;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['40']++;o.statusText='timeout';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['41']++;io.complete(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['42']++;io.end(o,c);},c.timeout);},_clearUploadTimeout:function(id){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['12']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['43']++;var io=this;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['44']++;w.clearTimeout(io._timeout[id]);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['45']++;delete io._timeout[id];},_uploadComplete:function(o,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['13']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['46']++;var io=this,d=Y.one('#io_iframe'+o.id).get('contentWindow.document'),b=d.one('body'),p;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['47']++;if(c.timeout){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['7'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['48']++;io._clearUploadTimeout(o.id);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['7'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['49']++;try{__cov_qyKMyH$gi2n6_r8dBYGRlg.s['50']++;if(b){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['8'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['51']++;p=b.one('pre:first-child');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['52']++;o.c.responseText=p?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['9'][0]++,p.get('text')):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['9'][1]++,b.get('text'));}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['8'][1]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['53']++;o.c.responseXML=d._node;}}catch(e){__cov_qyKMyH$gi2n6_r8dBYGRlg.s['54']++;o.e='upload failure';}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['55']++;io.complete(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['56']++;io.end(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['57']++;w.setTimeout(function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['14']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['58']++;_dFrame(o.id);},0);},_upload:function(o,uri,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['15']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['59']++;var io=this,f=typeof c.form.id==='string'?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['10'][0]++,d.getElementById(c.form.id)):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['10'][1]++,c.form.id),fields;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['60']++;io._setAttrs(f,o.id,uri);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['61']++;if(c.data){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['11'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['62']++;fields=io._addData(f,c.data);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['11'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['63']++;if(c.timeout){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['12'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['64']++;io._startUploadTimeout(o,c);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['12'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['65']++;f.submit();__cov_qyKMyH$gi2n6_r8dBYGRlg.s['66']++;io.start(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['67']++;if(c.data){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['13'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['68']++;io._removeData(f,fields);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['13'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['69']++;return{id:o.id,abort:function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['16']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['70']++;o.status=0;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['71']++;o.statusText='abort';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['72']++;if(Y.one('#io_iframe'+o.id)){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['14'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['73']++;_dFrame(o.id);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['74']++;io.complete(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['75']++;io.end(o,c);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['14'][1]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['76']++;return false;}},isInProgress:function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['17']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['77']++;return Y.one('#io_iframe'+o.id)?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['15'][0]++,true):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['15'][1]++,false);},io:io};},upload:function(o,uri,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['18']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['78']++;_cFrame(o,c,this);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['79']++;return this._upload(o,uri,c);},end:function(transaction,config){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['19']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['80']++;var form,io;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['81']++;if(config){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['16'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['82']++;form=config.form;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['83']++;if((__cov_qyKMyH$gi2n6_r8dBYGRlg.b['18'][0]++,form)&&(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['18'][1]++,form.upload)){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['17'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['84']++;io=this;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['85']++;form=typeof form.id==='string'?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['19'][0]++,d.getElementById(form.id)):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['19'][1]++,form.id);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['86']++;io._resetAttrs(form,this._originalFormAttrs);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['17'][1]++;}}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['16'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['87']++;return _end.call(this,transaction,config);}},true);},'3.13.0',{'requires':['io-base','node-base']});
+__cov_qyKMyH$gi2n6_r8dBYGRlg.s['1']++;YUI.add('io-upload-iframe',function(Y,NAME){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['1']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['2']++;var w=Y.config.win,d=Y.config.doc,_std=(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['1'][0]++,d.documentMode)&&(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['1'][1]++,d.documentMode>=8),_d=decodeURIComponent,_end=Y.IO.prototype.end;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['3']++;function _cFrame(o,c,io){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['2']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['4']++;var i=Y.Node.create('<iframe src="#" id="io_iframe'+o.id+'" name="io_iframe'+o.id+'" />');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['5']++;i._node.style.position='absolute';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['6']++;i._node.style.top='-1000px';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['7']++;i._node.style.left='-1000px';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['8']++;Y.one('body').appendChild(i);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['9']++;Y.on('load',function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['3']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['10']++;io._uploadComplete(o,c);},'#io_iframe'+o.id);}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['11']++;function _dFrame(id){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['4']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['12']++;Y.Event.purgeElement('#io_iframe'+id,false);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['13']++;Y.one('body').removeChild(Y.one('#io_iframe'+id));}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['14']++;Y.mix(Y.IO.prototype,{_addData:function(f,s){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['5']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['15']++;if(Y.Lang.isObject(s)){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['2'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['16']++;s=Y.QueryString.stringify(s);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['2'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['17']++;var o=[],m=s.split('='),i,l;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['18']++;for(i=0,l=m.length-1;i<l;i++){__cov_qyKMyH$gi2n6_r8dBYGRlg.s['19']++;o[i]=d.createElement('input');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['20']++;o[i].type='hidden';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['21']++;o[i].name=_d(m[i].substring(m[i].lastIndexOf('&')+1));__cov_qyKMyH$gi2n6_r8dBYGRlg.s['22']++;o[i].value=i+1===l?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['3'][0]++,_d(m[i+1])):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['3'][1]++,_d(m[i+1].substring(0,m[i+1].lastIndexOf('&'))));__cov_qyKMyH$gi2n6_r8dBYGRlg.s['23']++;f.appendChild(o[i]);}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['24']++;return o;},_removeData:function(f,o){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['6']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['25']++;var i,l;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['26']++;for(i=0,l=o.length;i<l;i++){__cov_qyKMyH$gi2n6_r8dBYGRlg.s['27']++;f.removeChild(o[i]);}},_setAttrs:function(f,id,uri){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['7']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['28']++;this._originalFormAttrs={action:f.getAttribute('action'),target:f.getAttribute('target')};__cov_qyKMyH$gi2n6_r8dBYGRlg.s['29']++;f.setAttribute('action',uri);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['30']++;f.setAttribute('method','POST');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['31']++;f.setAttribute('target','io_iframe'+id);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['32']++;f.setAttribute((__cov_qyKMyH$gi2n6_r8dBYGRlg.b['5'][0]++,Y.UA.ie)&&(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['5'][1]++,!_std)?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['4'][0]++,'encoding'):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['4'][1]++,'enctype'),'multipart/form-data');},_resetAttrs:function(f,a){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['8']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['33']++;Y.Object.each(a,function(v,p){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['9']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['34']++;if(v){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['6'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['35']++;f.setAttribute(p,v);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['6'][1]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['36']++;f.removeAttribute(p);}});},_startUploadTimeout:function(o,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['10']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['37']++;var io=this;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['38']++;io._timeout[o.id]=w.setTimeout(function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['11']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['39']++;o.status=0;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['40']++;o.statusText='timeout';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['41']++;io.complete(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['42']++;io.end(o,c);},c.timeout);},_clearUploadTimeout:function(id){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['12']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['43']++;var io=this;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['44']++;w.clearTimeout(io._timeout[id]);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['45']++;delete io._timeout[id];},_uploadComplete:function(o,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['13']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['46']++;var io=this,d=Y.one('#io_iframe'+o.id).get('contentWindow.document'),b=d.one('body'),p;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['47']++;if(c.timeout){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['7'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['48']++;io._clearUploadTimeout(o.id);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['7'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['49']++;try{__cov_qyKMyH$gi2n6_r8dBYGRlg.s['50']++;if(b){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['8'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['51']++;p=b.one('pre:first-child');__cov_qyKMyH$gi2n6_r8dBYGRlg.s['52']++;o.c.responseText=p?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['9'][0]++,p.get('text')):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['9'][1]++,b.get('text'));}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['8'][1]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['53']++;o.c.responseXML=d._node;}}catch(e){__cov_qyKMyH$gi2n6_r8dBYGRlg.s['54']++;o.e='upload failure';}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['55']++;io.complete(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['56']++;io.end(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['57']++;w.setTimeout(function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['14']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['58']++;_dFrame(o.id);},0);},_upload:function(o,uri,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['15']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['59']++;var io=this,f=typeof c.form.id==='string'?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['10'][0]++,d.getElementById(c.form.id)):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['10'][1]++,c.form.id),fields;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['60']++;io._setAttrs(f,o.id,uri);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['61']++;if(c.data){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['11'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['62']++;fields=io._addData(f,c.data);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['11'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['63']++;if(c.timeout){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['12'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['64']++;io._startUploadTimeout(o,c);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['12'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['65']++;f.submit();__cov_qyKMyH$gi2n6_r8dBYGRlg.s['66']++;io.start(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['67']++;if(c.data){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['13'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['68']++;io._removeData(f,fields);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['13'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['69']++;return{id:o.id,abort:function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['16']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['70']++;o.status=0;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['71']++;o.statusText='abort';__cov_qyKMyH$gi2n6_r8dBYGRlg.s['72']++;if(Y.one('#io_iframe'+o.id)){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['14'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['73']++;_dFrame(o.id);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['74']++;io.complete(o,c);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['75']++;io.end(o,c);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['14'][1]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['76']++;return false;}},isInProgress:function(){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['17']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['77']++;return Y.one('#io_iframe'+o.id)?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['15'][0]++,true):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['15'][1]++,false);},io:io};},upload:function(o,uri,c){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['18']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['78']++;_cFrame(o,c,this);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['79']++;return this._upload(o,uri,c);},end:function(transaction,config){__cov_qyKMyH$gi2n6_r8dBYGRlg.f['19']++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['80']++;var form,io;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['81']++;if(config){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['16'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['82']++;form=config.form;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['83']++;if((__cov_qyKMyH$gi2n6_r8dBYGRlg.b['18'][0]++,form)&&(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['18'][1]++,form.upload)){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['17'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['84']++;io=this;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['85']++;form=typeof form.id==='string'?(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['19'][0]++,d.getElementById(form.id)):(__cov_qyKMyH$gi2n6_r8dBYGRlg.b['19'][1]++,form.id);__cov_qyKMyH$gi2n6_r8dBYGRlg.s['86']++;if(form){__cov_qyKMyH$gi2n6_r8dBYGRlg.b['20'][0]++;__cov_qyKMyH$gi2n6_r8dBYGRlg.s['87']++;io._resetAttrs(form,this._originalFormAttrs);}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['20'][1]++;}}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['17'][1]++;}}else{__cov_qyKMyH$gi2n6_r8dBYGRlg.b['16'][1]++;}__cov_qyKMyH$gi2n6_r8dBYGRlg.s['88']++;return _end.call(this,transaction,config);}},true);},'3.13.0',{'requires':['io-base','node-base']});
index 23c4526..5e029e8 100644 (file)
@@ -305,7 +305,10 @@ Y.mix(Y.IO.prototype, {
                 // Restore HTML form attributes to their original values.
                 form = (typeof form.id === 'string') ? d.getElementById(form.id) : form.id;
 
-                io._resetAttrs(form, this._originalFormAttrs);
+                // Check whether the form still exists before resetting it.
+                if (form) {
+                    io._resetAttrs(form, this._originalFormAttrs);
+                }
             }
         }
 
index ba2a8d1..f39f257 100644 (file)
@@ -5,4 +5,4 @@ Licensed under the BSD License.
 http://yuilibrary.com/license/
 */
 
-YUI.add("io-upload-iframe",function(e,t){function u(t,n,r){var i=e.Node.create('<iframe src="#" id="io_iframe'+t.id+'" name="io_iframe'+t.id+'" />');i._node.style.position="absolute",i._node.style.top="-1000px",i._node.style.left="-1000px",e.one("body").appendChild(i),e.on("load",function(){r._uploadComplete(t,n)},"#io_iframe"+t.id)}function a(t){e.Event.purgeElement("#io_iframe"+t,!1),e.one("body").removeChild(e.one("#io_iframe"+t))}var n=e.config.win,r=e.config.doc,i=r.documentMode&&r.documentMode>=8,s=decodeURIComponent,o=e.IO.prototype.end;e.mix(e.IO.prototype,{_addData:function(t,n){e.Lang.isObject(n)&&(n=e.QueryString.stringify(n));var i=[],o=n.split("="),u,a;for(u=0,a=o.length-1;u<a;u++)i[u]=r.createElement("input"),i[u].type="hidden",i[u].name=s(o[u].substring(o[u].lastIndexOf("&")+1)),i[u].value=u+1===a?s(o[u+1]):s(o[u+1].substring(0,o[u+1].lastIndexOf("&"))),t.appendChild(i[u]);return i},_removeData:function(e,t){var n,r;for(n=0,r=t.length;n<r;n++)e.removeChild(t[n])},_setAttrs:function(t,n,r){this._originalFormAttrs={action:t.getAttribute("action"),target:t.getAttribute("target")},t.setAttribute("action",r),t.setAttribute("method","POST"),t.setAttribute("target","io_iframe"+n),t.setAttribute(e.UA.ie&&!i?"encoding":"enctype","multipart/form-data")},_resetAttrs:function(t,n){e.Object.each(n,function(e,n){e?t.setAttribute(n,e):t.removeAttribute(n)})},_startUploadTimeout:function(e,t){var r=this;r._timeout[e.id]=n.setTimeout(function(){e.status=0,e.statusText="timeout",r.complete(e,t),r.end(e,t)},t.timeout)},_clearUploadTimeout:function(e){var t=this;n.clearTimeout(t._timeout[e]),delete t._timeout[e]},_uploadComplete:function(t,r){var i=this,s=e.one("#io_iframe"+t.id).get("contentWindow.document"),o=s.one("body"),u;r.timeout&&i._clearUploadTimeout(t.id);try{o?(u=o.one("pre:first-child"),t.c.responseText=u?u.get("text"):o.get("text")):t.c.responseXML=s._node}catch(f){t.e="upload failure"}i.complete(t,r),i.end(t,r),n.setTimeout(function(){a(t.id)},0)},_upload:function(t,n,i){var s=this,o=typeof i.form.id=="string"?r.getElementById(i.form.id):i.form.id,u;return s._setAttrs(o,t.id,n),i.data&&(u=s._addData(o,i.data)),i.timeout&&s._startUploadTimeout(t,i),o.submit(),s.start(t,i),i.data&&s._removeData(o,u),{id:t.id,abort:function(){t.status=0,t.statusText="abort";if(!e.one("#io_iframe"+t.id))return!1;a(t.id),s.complete(t,i),s.end(t,i)},isInProgress:function(){return e.one("#io_iframe"+t.id)?!0:!1},io:s}},upload:function(e,t,n){return u(e,n,this),this._upload(e,t,n)},end:function(e,t){var n,i;return t&&(n=t.form,n&&n.upload&&(i=this,n=typeof n.id=="string"?r.getElementById(n.id):n.id,i._resetAttrs(n,this._originalFormAttrs))),o.call(this,e,t)}},!0)},"3.13.0",{requires:["io-base","node-base"]});
+YUI.add("io-upload-iframe",function(e,t){function u(t,n,r){var i=e.Node.create('<iframe src="#" id="io_iframe'+t.id+'" name="io_iframe'+t.id+'" />');i._node.style.position="absolute",i._node.style.top="-1000px",i._node.style.left="-1000px",e.one("body").appendChild(i),e.on("load",function(){r._uploadComplete(t,n)},"#io_iframe"+t.id)}function a(t){e.Event.purgeElement("#io_iframe"+t,!1),e.one("body").removeChild(e.one("#io_iframe"+t))}var n=e.config.win,r=e.config.doc,i=r.documentMode&&r.documentMode>=8,s=decodeURIComponent,o=e.IO.prototype.end;e.mix(e.IO.prototype,{_addData:function(t,n){e.Lang.isObject(n)&&(n=e.QueryString.stringify(n));var i=[],o=n.split("="),u,a;for(u=0,a=o.length-1;u<a;u++)i[u]=r.createElement("input"),i[u].type="hidden",i[u].name=s(o[u].substring(o[u].lastIndexOf("&")+1)),i[u].value=u+1===a?s(o[u+1]):s(o[u+1].substring(0,o[u+1].lastIndexOf("&"))),t.appendChild(i[u]);return i},_removeData:function(e,t){var n,r;for(n=0,r=t.length;n<r;n++)e.removeChild(t[n])},_setAttrs:function(t,n,r){this._originalFormAttrs={action:t.getAttribute("action"),target:t.getAttribute("target")},t.setAttribute("action",r),t.setAttribute("method","POST"),t.setAttribute("target","io_iframe"+n),t.setAttribute(e.UA.ie&&!i?"encoding":"enctype","multipart/form-data")},_resetAttrs:function(t,n){e.Object.each(n,function(e,n){e?t.setAttribute(n,e):t.removeAttribute(n)})},_startUploadTimeout:function(e,t){var r=this;r._timeout[e.id]=n.setTimeout(function(){e.status=0,e.statusText="timeout",r.complete(e,t),r.end(e,t)},t.timeout)},_clearUploadTimeout:function(e){var t=this;n.clearTimeout(t._timeout[e]),delete t._timeout[e]},_uploadComplete:function(t,r){var i=this,s=e.one("#io_iframe"+t.id).get("contentWindow.document"),o=s.one("body"),u;r.timeout&&i._clearUploadTimeout(t.id);try{o?(u=o.one("pre:first-child"),t.c.responseText=u?u.get("text"):o.get("text")):t.c.responseXML=s._node}catch(f){t.e="upload failure"}i.complete(t,r),i.end(t,r),n.setTimeout(function(){a(t.id)},0)},_upload:function(t,n,i){var s=this,o=typeof i.form.id=="string"?r.getElementById(i.form.id):i.form.id,u;return s._setAttrs(o,t.id,n),i.data&&(u=s._addData(o,i.data)),i.timeout&&s._startUploadTimeout(t,i),o.submit(),s.start(t,i),i.data&&s._removeData(o,u),{id:t.id,abort:function(){t.status=0,t.statusText="abort";if(!e.one("#io_iframe"+t.id))return!1;a(t.id),s.complete(t,i),s.end(t,i)},isInProgress:function(){return e.one("#io_iframe"+t.id)?!0:!1},io:s}},upload:function(e,t,n){return u(e,n,this),this._upload(e,t,n)},end:function(e,t){var n,i;return t&&(n=t.form,n&&n.upload&&(i=this,n=typeof n.id=="string"?r.getElementById(n.id):n.id,n&&i._resetAttrs(n,this._originalFormAttrs))),o.call(this,e,t)}},!0)},"3.13.0",{requires:["io-base","node-base"]});
index 51aa4bb..abc4ef6 100644 (file)
@@ -297,7 +297,10 @@ Y.mix(Y.IO.prototype, {
                 // Restore HTML form attributes to their original values.
                 form = (typeof form.id === 'string') ? d.getElementById(form.id) : form.id;
 
-                io._resetAttrs(form, this._originalFormAttrs);
+                // Check whether the form still exists before resetting it.
+                if (form) {
+                    io._resetAttrs(form, this._originalFormAttrs);
+                }
             }
         }
 
index 620053e..ad42d99 100644 (file)
@@ -780,17 +780,25 @@ class worker extends singleton_pattern {
             $this->log('Current plugin code location: '.$sourcelocation);
             $this->log('Moving the current code into archive: '.$backuplocation);
 
-            // We don't want to touch files unless we are pretty sure it would be all ok.
-            if (!$this->move_directory_source_precheck($sourcelocation)) {
-                throw new backup_folder_exception('Unable to backup the current version of the plugin (source precheck failed)');
-            }
-            if (!$this->move_directory_target_precheck($backuplocation)) {
-                throw new backup_folder_exception('Unable to backup the current version of the plugin (backup precheck failed)');
-            }
+            if (file_exists($sourcelocation)) {
+                // We don't want to touch files unless we are pretty sure it would be all ok.
+                if (!$this->move_directory_source_precheck($sourcelocation)) {
+                    throw new backup_folder_exception('Unable to backup the current version of the plugin (source precheck failed)');
+                }
+                if (!$this->move_directory_target_precheck($backuplocation)) {
+                    throw new backup_folder_exception('Unable to backup the current version of the plugin (backup precheck failed)');
+                }
 
-            // Looking good, let's try it.
-            if (!$this->move_directory($sourcelocation, $backuplocation, true)) {
-                throw new backup_folder_exception('Unable to backup the current version of the plugin (moving failed)');
+                // Looking good, let's try it.
+                if (!$this->move_directory($sourcelocation, $backuplocation, true)) {
+                    throw new backup_folder_exception('Unable to backup the current version of the plugin (moving failed)');
+                }
+
+            } else {
+                // Upgrading missing plugin - this happens often during upgrades.
+                if (!$this->create_directory_precheck($sourcelocation)) {
+                    throw new filesystem_exception('Unable to prepare the plugin location (cannot create new directory)');
+                }
             }
 
             // Unzip the plugin package file into the target location.
index d1080aa..741dbc9 100644 (file)
@@ -120,4 +120,22 @@ class restore_assign_activity_task extends restore_activity_task {
         return $rules;
     }
 
+    /**
+     * Given a comment area, return the itemname that contains the itemid mappings.
+     *
+     * @param string $commentarea
+     * @return string
+     */
+    public function get_comment_mapping_itemname($commentarea) {
+        switch ($commentarea) {
+            case 'submission_comments':
+                $itemname = 'submission';
+                break;
+            default:
+                $itemname = parent::get_comment_mapping_itemname($commentarea);
+                break;
+        }
+
+        return $itemname;
+    }
 }
index 6609552..2981464 100644 (file)
@@ -150,9 +150,11 @@ M.mod_assign.init_grading_options = function(Y) {
             });
         }
         var showonlyactiveenrolelement = Y.one('#id_showonlyactiveenrol');
-        showonlyactiveenrolelement.on('change', function(e) {
+        if (showonlyactiveenrolelement) {
+            showonlyactiveenrolelement.on('change', function(e) {
             Y.one('form.gradingoptionsform').submit();
-        });
+            });
+        }
     });
 };
 
index 7bc5380..4e33ee9 100644 (file)
@@ -31,13 +31,13 @@ Feature: In an assignment, students can upload files for assessment
     And I follow "Course 1"
     And I follow "Test assignment name"
     When I press "Add submission"
-    And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filepicker
+    And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
     And I press "Save changes"
     Then I should see "Submitted for grading"
     And I should see "empty.txt"
     And I should see "Not graded"
     And I press "Edit submission"
-    And I upload "lib/tests/fixtures/upload_users.csv" file to "File submissions" filepicker
+    And I upload "lib/tests/fixtures/upload_users.csv" file to "File submissions" filemanager
     And ".ffilemanager .fm-maxfiles .fp-btn-add" "css_element" should exists
     And I press "Save changes"
     And I should see "Submitted for grading"
diff --git a/mod/book/classes/event/course_module_instance_list_viewed.php b/mod/book/classes/event/course_module_instance_list_viewed.php
new file mode 100644 (file)
index 0000000..29ddf51
--- /dev/null
@@ -0,0 +1,37 @@
+<?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/>.
+
+/**
+ * mod_book course module instance list viewed event.
+ *
+ * @package    mod_book
+ * @copyright  2013 Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_book\event;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * mod_book course module instance list viewed event class.
+ *
+ * @package    mod_book
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
+}
+
diff --git a/mod/book/classes/event/instances_list_viewed.php b/mod/book/classes/event/instances_list_viewed.php
deleted file mode 100644 (file)
index 3630e41..0000000
+++ /dev/null
@@ -1,73 +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/>.
-
-/**
- * mod_book instances list viewed event.
- *
- * @package    mod_book
- * @copyright  2013 Frédéric Massart
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-namespace mod_book\event;
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * mod_book instances list viewed event class.
- *
- * @package    mod_book
- * @copyright  2013 Frédéric Massart
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class instances_list_viewed extends \core\event\course_module_instances_list_viewed {
-
-    /**
-     * Returns description of what happened.
-     *
-     * @return string
-     */
-    public function get_description() {
-        return "User $this->userid viewed the list of book activities in the course $this->courseid.";
-    }
-
-    /**
-     * Return the legacy event log data.
-     *
-     * @return array|null
-     */
-    protected function get_legacy_logdata() {
-        return array($this->courseid, 'book', 'view all', 'index.php?id=' . $this->courseid, '');
-    }
-
-    /**
-     * Return localised event name.
-     *
-     * @return string
-     */
-    public static function get_name() {
-        return get_string('event_instances_list_viewed', 'mod_book');
-    }
-
-    /**
-     * Get URL related to the action
-     *
-     * @return \moodle_url
-     */
-    public function get_url() {
-        return new \moodle_url('/mod/book/index.php', array('id' => $this->courseid));
-    }
-
-}
index 4467391..027f235 100644 (file)
@@ -50,7 +50,7 @@ echo $OUTPUT->header();
 $params = array(
     'context' => context_course::instance($course->id)
 );
-$event = \mod_book\event\instances_list_viewed::create($params);
+$event = \mod_book\event\course_module_instance_list_viewed::create($params);
 $event->trigger();
 
 // Get all the appropriate data
index f35e4e2..33e96cd 100644 (file)
@@ -50,7 +50,6 @@ $string['event_chapter_created'] = 'Chapter created';
 $string['event_chapter_deleted'] = 'Chapter deleted';
 $string['event_chapter_updated'] = 'Chapter updated';
 $string['event_chapter_viewed'] = 'Chapter viewed';
-$string['event_instances_list_viewed'] = 'Instances list viewed';
 $string['subchapter'] = 'Subchapter';
 $string['nocontent'] = 'No content has been added to this book yet.';
 $string['numbering'] = 'Chapter formatting';
index d53db31..81d5089 100644 (file)
@@ -137,7 +137,7 @@ class mod_book_events_testcase extends advanced_testcase {
         $this->assertEventLegacyLogData(array('1', 2, false), $event);
     }
 
-    public function test_instances_list_viewed() {
+    public function test_course_module_instance_list_viewed() {
         // There is no proper API to call to trigger this event, so what we are
         // doing here is simply making sure that the events returns the right information.
 
@@ -145,7 +145,7 @@ class mod_book_events_testcase extends advanced_testcase {
         $params = array(
             'context' => context_course::instance($course->id)
         );
-        $event = \mod_book\event\instances_list_viewed::create($params);
+        $event = \mod_book\event\course_module_instance_list_viewed::create($params);
 
         // Triggering and capturing the event.
         $sink = $this->redirectEvents();
@@ -155,7 +155,7 @@ class mod_book_events_testcase extends advanced_testcase {
         $event = reset($events);
 
         // Checking that the event contains the expected values.
-        $this->assertInstanceOf('\mod_book\event\instances_list_viewed', $event);
+        $this->assertInstanceOf('\mod_book\event\course_module_instance_list_viewed', $event);
         $this->assertEquals(context_course::instance($course->id), $event->get_context());
         $expected = array($course->id, 'book', 'view all', 'index.php?id='.$course->id, '');
         $this->assertEventLegacyLogData($expected, $event);
diff --git a/mod/chat/classes/event/course_module_instance_list_viewed.php b/mod/chat/classes/event/course_module_instance_list_viewed.php
new file mode 100644 (file)
index 0000000..c7b3b36
--- /dev/null
@@ -0,0 +1,37 @@
+<?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/>.
+
+/**
+ * mod_chat course module instance list viewed event.
+ *
+ * @package    mod_chat
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_chat\event;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * mod_chat course module instance list viewed event class.
+ *
+ * @package    mod_chat
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
+}
+
diff --git a/mod/chat/classes/event/instances_list_viewed.php b/mod/chat/classes/event/instances_list_viewed.php
deleted file mode 100644 (file)
index d6bcade..0000000
+++ /dev/null
@@ -1,73 +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/>.
-
-/**
- * mod_chat instances list viewed event.
- *
- * @package    mod_chat
- * @copyright  2013 Frédéric Massart
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-namespace mod_chat\event;
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * mod_chat instances list viewed event class.
- *
- * @package    mod_chat
- * @copyright  2013 Frédéric Massart
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class instances_list_viewed extends \core\event\course_module_instances_list_viewed {
-
-    /**
-     * Returns description of what happened.
-     *
-     * @return string
-     */
-    public function get_description() {
-        return "User $this->userid viewed the list of chat activities in the course $this->courseid.";
-    }
-
-    /**
-     * Return the legacy event log data.
-     *
-     * @return array|null
-     */
-    protected function get_legacy_logdata() {
-        return array($this->courseid, 'chat', 'view all', 'index.php?id=' . $this->courseid, '');
-    }
-
-    /**
-     * Return localised event name.
-     *
-     * @return string
-     */
-    public static function get_name() {
-        return get_string('event_instances_list_viewed', 'mod_chat');
-    }
-
-    /**
-     * Get URL related to the action
-     *
-     * @return \moodle_url
-     */
-    public function get_url() {
-        return new \moodle_url('/mod/chat/index.php', array('id' => $this->courseid));
-    }
-
-}
index 9b8b855..35a43aa 100644 (file)
@@ -17,7 +17,7 @@ $PAGE->set_pagelayout('incourse');
 $params = array(
     'context' => context_course::instance($id)
 );
-$event = \mod_chat\event\instances_list_viewed::create($params);
+$event = \mod_chat\event\course_module_instance_list_viewed::create($params);
 $event->trigger();
 
 /// Get all required strings
index 139ef6d..3d03baf 100644 (file)
@@ -64,7 +64,6 @@ $string['chatreport'] = 'Chat sessions';
 $string['chat:talk'] = 'Talk in a chat';
 $string['chattime'] = 'Next chat time';
 $string['entermessage'] = "Enter your message";
-$string['event_instances_list_viewed'] = 'Instances list viewed';
 $string['event_message_sent'] = 'Message sent';
 $string['event_sessions_viewed'] = 'Sessions viewed';
 $string['idle'] = 'Idle';
index 1ba312f..fe115e0 100644 (file)
@@ -134,7 +134,7 @@ class mod_chat_events_testcase extends advanced_testcase {
         $this->assertEventLegacyLogData($expected, $event);
     }
 
-    public function test_instances_list_viewed() {
+    public function test_course_module_instance_list_viewed() {
         global $USER;
         $this->resetAfterTest();
 
@@ -146,12 +146,12 @@ class mod_chat_events_testcase extends advanced_testcase {
         $params = array(
             'context' => context_course::instance($course->id)
         );
-        $event = \mod_chat\event\instances_list_viewed::create($params);
+        $event = \mod_chat\event\course_module_instance_list_viewed::create($params);
         $sink = $this->redirectEvents();
         $event->trigger();
         $events = $sink->get_events();
         $event = reset($events);
-        $this->assertInstanceOf('\mod_chat\event\instances_list_viewed', $event);
+        $this->assertInstanceOf('\mod_chat\event\course_module_instance_list_viewed', $event);
         $this->assertEquals($USER->id, $event->userid);
         $this->assertEquals(context_course::instance($course->id), $event->get_context());
         $expected = array($course->id, 'chat', 'view all', "index.php?id=$course->id", '');
diff --git a/mod/choice/classes/event/course_module_instance_list_viewed.php b/mod/choice/classes/event/course_module_instance_list_viewed.php
new file mode 100644 (file)
index 0000000..6174c86
--- /dev/null
@@ -0,0 +1,37 @@
+<?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/>.
+
+/**
+ * mod_choice course module instance list viewed event.
+ *
+ * @package    mod_choice
+ * @copyright  2013 Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_choice\event;
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * mod_choice course module instance list event class.
+ *
+ * @package    mod_choice
+ * @copyright  2013 onwards Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
+}
+
diff --git a/mod/choice/classes/event/instances_list_viewed.php b/mod/choice/classes/event/instances_list_viewed.php
deleted file mode 100644 (file)
index 165d58f..0000000
+++ /dev/null
@@ -1,72 +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/>.
-
-/**
- * Course module instances list_viewed event.
- *
- * @package    mod_choice
- * @copyright  2013 Adrian Greeve
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-namespace mod_choice\event;
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * Course module instances list viewed event class for mod_choice.
- *
- * @package    mod_choice
- * @copyright  2013 Adrian Greeve
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class instances_list_viewed extends \core\event\course_module_instances_list_viewed {
-
-    /**
-     * Returns description of what happened.
-     *
-     * @return string
-     */
-    public function get_description() {
-        return "User $this->userid viewed the list of choice activities in the course $this->courseid.";
-    }
-
-    /**
-     * Return the legacy event log data.
-     *
-     * @return array
-     */
-    protected function get_legacy_logdata() {
-        return array($this->courseid, 'choice', 'view all', 'index.php?id=' . $this->courseid, '');
-    }
-
-    /**
-     * Return localised event name.
-     *
-     * @return string
-     */
-    public static function get_name() {
-        return get_string('event_instances_list_viewed', 'mod_choice');
-    }
-
-    /**
-     * Get URL related to the action
-     *
-     * @return \moodle_url
-     */
-    public function get_url() {
-        return new \moodle_url('/mod/choice/index.php', array('id' => $this->courseid));
-    }
-}
index 471ff22..07e4234 100644 (file)
@@ -15,7 +15,7 @@
     $PAGE->set_pagelayout('incourse');
 
     $eventdata = array('context' => context_course::instance($id));
-    $event = \mod_choice\event\instances_list_viewed::create($eventdata);
+    $event = \mod_choice\event\course_module_instance_list_viewed::create($eventdata);
     $event->trigger();
 
     $strchoice = get_string("modulename", "choice");
index 3bd8291..fb350ed 100644 (file)
@@ -33,7 +33,6 @@ $string['displayvertical'] = 'Display vertically';
 $string['event_answer_created'] = 'Choice made';
 $string['event_answer_updated'] = 'Choice updated';
 $string['event_report_viewed'] = 'Choice report viewed';
-$string['event_instances_list_viewed'] = 'Instances list viewed';
 $string['expired'] = 'Sorry, this activity closed on {$a} and is no longer available';
 $string['atleastoneoption'] = 'You need to provide at least one possible answer.';
 $string['full'] = '(Full)';
index ef38abb..b747e93 100644 (file)
@@ -236,7 +236,7 @@ class mod_choice_events_testcase extends advanced_testcase {
     /**
      * Test to ensure that event data is being stored correctly.
      */
-    public function test_instances_list_viewed() {
+    public function test_course_module_instance_list_viewed_viewed() {
         global $USER;
 
         // Not much can be tested here as the event is only triggered on a page load,
@@ -244,12 +244,12 @@ class mod_choice_events_testcase extends advanced_testcase {
         $this->setAdminUser();
 
         $params = array('context' => context_course::instance($this->course->id));
-        $event = \mod_choice\event\instances_list_viewed::create($params);
+        $event = \mod_choice\event\course_module_instance_list_viewed::create($params);
         $sink = $this->redirectEvents();
         $event->trigger();
         $events = $sink->get_events();
         $event = reset($events);
-        $this->assertInstanceOf('\mod_choice\event\instances_list_viewed', $event);
+        $this->assertInstanceOf('\mod_choice\event\course_module_instance_list_viewed', $event);
         $this->assertEquals($USER->id, $event->userid);
         $this->assertEquals(context_course::instance($this->course->id), $event->get_context());
         $expected = array($this->course->id, 'choice', 'view all', 'index.php?id=' . $this->course->id, '');
index 79f1b37..a733dbf 100644 (file)
@@ -39,43 +39,6 @@ function showHideAdvSearch(checked) {
     }
 }
 
-M.data_filepicker = {};
-
-
-M.data_filepicker.callback = function(params) {
-    var html = '<a href="'+params['url']+'">'+params['file']+'</a>';
-    document.getElementById('file_info_'+params['client_id']).innerHTML = html;
-};
-
-/**
- * Deprecated since 2.5, will be removed in 2.7.
- * Please don't use this function.
- * Use the filemanager instead. (/lib/form/filemanager.js)
- * This fucntion is called for each file picker on page.
- */
-M.data_filepicker.init = function(Y, options) {
-    if (M.cfg.developerdebug) {
-        Y.log("You are using a deprecated function call (M.data_filepicker). Please look at rewriting your call to use M.form_filemanager");
-    }
-    options.formcallback = M.data_filepicker.callback;
-    if (!M.core_filepicker.instances[options.client_id]) {
-        M.core_filepicker.init(Y, options);
-    }
-    Y.on('click', function(e, client_id) {
-        e.preventDefault();
-        M.core_filepicker.instances[client_id].show();
-    }, '#filepicker-button-'+options.client_id, null, options.client_id);
-
-    var item = document.getElementById('nonjs-filepicker-'+options.client_id);
-    if (item) {
-        item.parentNode.removeChild(item);
-    }
-    item = document.getElementById('filepicker-wrapper-'+options.client_id);
-    if (item) {
-        item.style.display = '';
-    }
-};
-
 M.data_urlpicker = {};
 
 M.data_urlpicker.init = function(Y, options) {
@@ -93,39 +56,3 @@ M.data_urlpicker.init = function(Y, options) {
 M.data_urlpicker.callback = function (params) {
     document.getElementById('field_url_'+params.client_id).value = params.url;
 };
-
-M.data_imagepicker = {};
-
-M.data_imagepicker.callback = function(params) {
-    var html = '<a href="'+params['url']+'"><img src="'+params['url']+'" /> '+params['file']+'</a>';
-    document.getElementById('file_info_'+params['client_id']).innerHTML = html;
-};
-
-/**
- * Deprecated since 2.5, will be removed in 2.7.
- * Please don't use this function.
- * Use the filemanager instead. (/lib/form/filemanager.js)
- * This fucntion is called for each file picker on page.
- */
-M.data_imagepicker.init = function(Y, options) {
-    if (M.cfg.developerdebug) {
-        Y.log("You are using a deprecated function call (M.data_imagepicker). Please look at rewriting your call to use M.form_filemanager");
-    }
-    options.formcallback = M.data_imagepicker.callback;