Merge branch 'wip-MDL-39298-master' of git://github.com/abgreeve/moodle
authorSam Hemelryk <sam@moodle.com>
Sun, 28 Apr 2013 22:45:33 +0000 (10:45 +1200)
committerSam Hemelryk <sam@moodle.com>
Sun, 28 Apr 2013 22:45:33 +0000 (10:45 +1200)
310 files changed:
admin/plugins.php
admin/registration/forms.php
admin/renderer.php
admin/settings/courses.php
admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php
admin/tool/dbtransfer/database_export_form.php
admin/tool/dbtransfer/database_transfer_form.php
admin/tool/qeupgradehelper/cronsetup_form.php
admin/tool/qeupgradehelper/extracttestcase_form.php
admin/tool/uploaduser/index.php
admin/webservice/forms.php
admin/webservice/testclient.php
admin/webservice/testclient_forms.php
backup/util/ui/base_moodleform.class.php
blocks/community/forms.php
blocks/dock.js
blocks/moodleblock.class.php
cache/README.md
cache/classes/definition.php
cache/classes/factory.php
cache/classes/helper.php
cache/classes/interfaces.php
cache/classes/loaders.php
cache/classes/store.php
cache/forms.php
cache/locallib.php
cache/stores/file/lib.php
cache/stores/session/lib.php
cache/tests/cache_test.php
cache/tests/fixtures/lib.php
comment/lib.php
course/edit_form.php
course/externallib.php
course/moodleform_mod.php
course/publish/forms.php
course/publish/index.php
course/renderer.php
enrol/externallib.php
enrol/manual/externallib.php
files/externallib.php
grade/edit/tree/grade_form.php
grade/lib.php
group/externallib.php
group/import_form.php
install/lang/ru/install.php
install/lang/sr_cr/install.php
install/lang/sr_lt/install.php
lang/en/admin.php
lang/en/block.php
lang/en/cache.php
lang/en/completion.php
lang/en/error.php
lang/en/moodle.php
lang/en/plugin.php
lang/en/repository.php
lib/blocklib.php
lib/coursecatlib.php
lib/cronlib.php
lib/csslib.php
lib/datalib.php
lib/db/caches.php
lib/db/install.xml
lib/db/upgrade.php
lib/ddl/tests/ddl_test.php
lib/editor/tinymce/lib.php
lib/editor/tinymce/yui/build/moodle-editor_tinymce-collapse/moodle-editor_tinymce-collapse-debug.js
lib/editor/tinymce/yui/build/moodle-editor_tinymce-collapse/moodle-editor_tinymce-collapse-min.js
lib/editor/tinymce/yui/build/moodle-editor_tinymce-collapse/moodle-editor_tinymce-collapse.js
lib/editor/tinymce/yui/src/collapse/js/collapse.js
lib/filestorage/file_storage.php
lib/filestorage/tests/file_storage_test.php
lib/moodlelib.php
lib/outputrequirementslib.php
lib/pluginlib.php
lib/portfolio/caller.php
lib/portfolio/forms.php
lib/portfoliolib.php
lib/tests/csslib_test.php
lib/tests/fixtures/mockplugins/mod/new/version.php [new file with mode: 0644]
lib/tests/moodlelib_test.php
lib/tests/pluginlib_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
lib/xmldb/xmldb_table.php
message/externallib.php
mod/assign/extensionform.php
mod/assign/feedback/file/batchuploadfilesform.php
mod/assign/feedback/file/importzipform.php
mod/assign/feedback/file/locallib.php
mod/assign/feedback/file/uploadzipform.php
mod/assign/feedback/offline/importgradesform.php
mod/assign/feedback/offline/uploadgradesform.php
mod/assign/gradingbatchoperationsform.php
mod/assign/locallib.php
mod/assign/mod_form.php
mod/assign/submission/comments/lib.php
mod/assign/submission/comments/locallib.php
mod/chat/lang/en/chat.php
mod/chat/mod_form.php
mod/data/field/file/field.class.php
mod/data/field/picture/field.class.php
mod/data/import_form.php
mod/data/preset.php
mod/data/preset_form.php
mod/folder/backup/moodle2/backup_folder_stepslib.php
mod/folder/backup/moodle2/restore_folder_stepslib.php
mod/folder/db/install.xml
mod/folder/db/upgrade.php
mod/folder/lang/en/folder.php
mod/folder/lib.php
mod/folder/mod_form.php
mod/folder/renderer.php
mod/folder/settings.php
mod/folder/version.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/mod_form.php
mod/forum/post.php
mod/forum/post_form.php
mod/forum/upgrade.txt
mod/forum/view.php
mod/lti/edit_form.php
mod/quiz/accessmanager.php
mod/quiz/accessmanager_form.php
mod/quiz/accessrule/accessrulebase.php
mod/quiz/lib.php
mod/quiz/mod_form.php
mod/quiz/module.js
mod/quiz/settings.php
mod/scorm/module.js
mod/scorm/player.php
mod/scorm/report/graphs/graph.php
mod/workshop/lang/en/workshop.php
mod/workshop/lib.php
mod/workshop/locallib.php
mod/workshop/mod_form.php
notes/externallib.php
pix/i/moodle_host.png [new file with mode: 0644]
portfolio/boxnet/lib.php
portfolio/flickr/lib.php
portfolio/mahara/lib.php
question/behaviour/adaptivenopenalty/renderer.php
question/behaviour/adaptivenopenalty/tests/walkthrough_test.php
question/format/blackboard_six/format.php
question/format/blackboard_six/formatpool.php
question/format/blackboard_six/formatqti.php
question/format/examview/format.php
question/format/gift/format.php
question/format/xml/format.php
report/completion/index.php
report/progress/index.php
repository/coursefiles/pix/icon.png
repository/lib.php
repository/local/pix/icon.png
repository/recent/pix/icon.png
repository/upload/lib.php
repository/user/pix/icon.png
theme/afterburner/settings.php
theme/anomaly/settings.php
theme/arialist/settings.php
theme/base/style/admin.css
theme/base/style/filemanager.css
theme/bootstrap/javascript/moodlebootstrap.js [deleted file]
theme/bootstrap/less/moodle/blocks.less [deleted file]
theme/bootstrap/less/moodle/recess.txt [deleted file]
theme/bootstrap/pix/screenshot.jpg [deleted file]
theme/bootstrap/style/README [deleted file]
theme/bootstrap/style/generated.css [deleted file]
theme/bootstrapbase/README.txt [moved from theme/bootstrap/README.txt with 97% similarity]
theme/bootstrapbase/config.php [moved from theme/bootstrap/config.php with 97% similarity]
theme/bootstrapbase/javascript/html5shiv.js [moved from theme/bootstrap/javascript/html5shiv.js with 100% similarity]
theme/bootstrapbase/javascript/moodlebootstrap.js [new file with mode: 0644]
theme/bootstrapbase/lang/en/theme_bootstrapbase.php [moved from theme/bootstrap/lang/en/theme_bootstrap.php with 97% similarity]
theme/bootstrapbase/layout/general.php [moved from theme/bootstrap/layout/general.php with 90% similarity]
theme/bootstrapbase/less/README [moved from theme/bootstrap/less/README with 85% similarity]
theme/bootstrapbase/less/bootstrap/accordion.less [moved from theme/bootstrap/less/bootstrap/accordion.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/alerts.less [moved from theme/bootstrap/less/bootstrap/alerts.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/bootstrap.less [moved from theme/bootstrap/less/bootstrap/bootstrap.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/breadcrumbs.less [moved from theme/bootstrap/less/bootstrap/breadcrumbs.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/button-groups.less [moved from theme/bootstrap/less/bootstrap/button-groups.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/buttons.less [moved from theme/bootstrap/less/bootstrap/buttons.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/carousel.less [moved from theme/bootstrap/less/bootstrap/carousel.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/close.less [moved from theme/bootstrap/less/bootstrap/close.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/code.less [moved from theme/bootstrap/less/bootstrap/code.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/component-animations.less [moved from theme/bootstrap/less/bootstrap/component-animations.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/dropdowns.less [moved from theme/bootstrap/less/bootstrap/dropdowns.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/forms.less [moved from theme/bootstrap/less/bootstrap/forms.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/grid.less [moved from theme/bootstrap/less/bootstrap/grid.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/hero-unit.less [moved from theme/bootstrap/less/bootstrap/hero-unit.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/labels-badges.less [moved from theme/bootstrap/less/bootstrap/labels-badges.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/layouts.less [moved from theme/bootstrap/less/bootstrap/layouts.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/media.less [moved from theme/bootstrap/less/bootstrap/media.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/mixins.less [moved from theme/bootstrap/less/bootstrap/mixins.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/modals.less [moved from theme/bootstrap/less/bootstrap/modals.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/navbar.less [moved from theme/bootstrap/less/bootstrap/navbar.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/navs.less [moved from theme/bootstrap/less/bootstrap/navs.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/pager.less [moved from theme/bootstrap/less/bootstrap/pager.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/pagination.less [moved from theme/bootstrap/less/bootstrap/pagination.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/popovers.less [moved from theme/bootstrap/less/bootstrap/popovers.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/progress-bars.less [moved from theme/bootstrap/less/bootstrap/progress-bars.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/reset.less [moved from theme/bootstrap/less/bootstrap/reset.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/responsive-1200px-min.less [moved from theme/bootstrap/less/bootstrap/responsive-1200px-min.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/responsive-767px-max.less [moved from theme/bootstrap/less/bootstrap/responsive-767px-max.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/responsive-768px-979px.less [moved from theme/bootstrap/less/bootstrap/responsive-768px-979px.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/responsive-navbar.less [moved from theme/bootstrap/less/bootstrap/responsive-navbar.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/responsive-utilities.less [moved from theme/bootstrap/less/bootstrap/responsive-utilities.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/responsive.less [moved from theme/bootstrap/less/bootstrap/responsive.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/scaffolding.less [moved from theme/bootstrap/less/bootstrap/scaffolding.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/sprites.less [moved from theme/bootstrap/less/bootstrap/sprites.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/tables.less [moved from theme/bootstrap/less/bootstrap/tables.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/thumbnails.less [moved from theme/bootstrap/less/bootstrap/thumbnails.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/tooltip.less [moved from theme/bootstrap/less/bootstrap/tooltip.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/type.less [moved from theme/bootstrap/less/bootstrap/type.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/utilities.less [moved from theme/bootstrap/less/bootstrap/utilities.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/variables.less [moved from theme/bootstrap/less/bootstrap/variables.less with 100% similarity]
theme/bootstrapbase/less/bootstrap/wells.less [moved from theme/bootstrap/less/bootstrap/wells.less with 100% similarity]
theme/bootstrapbase/less/editor.less [moved from theme/bootstrap/less/editor.less with 100% similarity]
theme/bootstrapbase/less/moodle.less [moved from theme/bootstrap/less/moodle.less with 100% similarity]
theme/bootstrapbase/less/moodle/admin.less [moved from theme/bootstrap/less/moodle/admin.less with 96% similarity]
theme/bootstrapbase/less/moodle/backup-restore.less [moved from theme/bootstrap/less/moodle/backup-restore.less with 100% similarity]
theme/bootstrapbase/less/moodle/blocks.less [new file with mode: 0644]
theme/bootstrapbase/less/moodle/buttons.less [moved from theme/bootstrap/less/moodle/buttons.less with 100% similarity]
theme/bootstrapbase/less/moodle/calendar.less [moved from theme/bootstrap/less/moodle/calendar.less with 100% similarity]
theme/bootstrapbase/less/moodle/core.less [moved from theme/bootstrap/less/moodle/core.less with 99% similarity]
theme/bootstrapbase/less/moodle/course.less [moved from theme/bootstrap/less/moodle/course.less with 99% similarity]
theme/bootstrapbase/less/moodle/debug.less [moved from theme/bootstrap/less/moodle/debug.less with 68% similarity]
theme/bootstrapbase/less/moodle/expendable.less [moved from theme/bootstrap/less/moodle/expendable.less with 100% similarity]
theme/bootstrapbase/less/moodle/filemanager.less [moved from theme/bootstrap/less/moodle/filemanager.less with 100% similarity]
theme/bootstrapbase/less/moodle/forms.less [moved from theme/bootstrap/less/moodle/forms.less with 97% similarity]
theme/bootstrapbase/less/moodle/grade.less [moved from theme/bootstrap/less/moodle/grade.less with 100% similarity]
theme/bootstrapbase/less/moodle/message.less [moved from theme/bootstrap/less/moodle/message.less with 100% similarity]
theme/bootstrapbase/less/moodle/modules.less [moved from theme/bootstrap/less/moodle/modules.less with 100% similarity]
theme/bootstrapbase/less/moodle/question.less [moved from theme/bootstrap/less/moodle/question.less with 100% similarity]
theme/bootstrapbase/less/moodle/responsive.less [moved from theme/bootstrap/less/moodle/responsive.less with 100% similarity]
theme/bootstrapbase/less/moodle/tables.less [moved from theme/bootstrap/less/moodle/tables.less with 100% similarity]
theme/bootstrapbase/less/moodle/tabs.less [moved from theme/bootstrap/less/moodle/tabs.less with 100% similarity]
theme/bootstrapbase/less/moodle/undo.less [moved from theme/bootstrap/less/moodle/undo.less with 97% similarity]
theme/bootstrapbase/less/moodle/user.less [moved from theme/bootstrap/less/moodle/user.less with 100% similarity]
theme/bootstrapbase/less/moodle/yui_fixes.less [moved from theme/bootstrap/less/moodle/yui_fixes.less with 100% similarity]
theme/bootstrapbase/pix/favicon.ico [moved from theme/bootstrap/pix/favicon.ico with 100% similarity]
theme/bootstrapbase/pix/fp/alias.png [moved from theme/bootstrap/pix/fp/alias.png with 100% similarity]
theme/bootstrapbase/pix/fp/alias_sm.png [moved from theme/bootstrap/pix/fp/alias_sm.png with 100% similarity]
theme/bootstrapbase/pix/fp/check.png [moved from theme/bootstrap/pix/fp/check.png with 100% similarity]
theme/bootstrapbase/pix/fp/cross.png [moved from theme/bootstrap/pix/fp/cross.png with 100% similarity]
theme/bootstrapbase/pix/fp/dnd_arrow.gif [moved from theme/bootstrap/pix/fp/dnd_arrow.gif with 100% similarity]
theme/bootstrapbase/pix/fp/link.png [moved from theme/bootstrap/pix/fp/link.png with 100% similarity]
theme/bootstrapbase/pix/fp/link_sm.png [moved from theme/bootstrap/pix/fp/link_sm.png with 100% similarity]
theme/bootstrapbase/pix/fp/path_folder.png [moved from theme/bootstrap/pix/fp/path_folder.png with 100% similarity]
theme/bootstrapbase/pix/fp/path_folder_rtl.png [moved from theme/bootstrap/pix/fp/path_folder_rtl.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_icon_active.png [moved from theme/bootstrap/pix/fp/view_icon_active.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_icon_inactive.png [moved from theme/bootstrap/pix/fp/view_icon_inactive.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_icon_selected.png [moved from theme/bootstrap/pix/fp/view_icon_selected.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_list_active.png [moved from theme/bootstrap/pix/fp/view_list_active.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_list_inactive.png [moved from theme/bootstrap/pix/fp/view_list_inactive.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_list_selected.png [moved from theme/bootstrap/pix/fp/view_list_selected.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_tree_active.png [moved from theme/bootstrap/pix/fp/view_tree_active.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_tree_inactive.png [moved from theme/bootstrap/pix/fp/view_tree_inactive.png with 100% similarity]
theme/bootstrapbase/pix/fp/view_tree_selected.png [moved from theme/bootstrap/pix/fp/view_tree_selected.png with 100% similarity]
theme/bootstrapbase/pix/glyphicons-halflings-white.png [moved from theme/bootstrap/pix/glyphicons-halflings-white.png with 100% similarity]
theme/bootstrapbase/pix/glyphicons-halflings.png [moved from theme/bootstrap/pix/glyphicons-halflings.png with 100% similarity]
theme/bootstrapbase/pix/header.jpg [moved from theme/bootstrap/pix/header.jpg with 100% similarity]
theme/bootstrapbase/pix/horizontal-menu-submenu-indicator.png [moved from theme/bootstrap/pix/horizontal-menu-submenu-indicator.png with 100% similarity]
theme/bootstrapbase/pix/screenshot.jpg [new file with mode: 0644]
theme/bootstrapbase/pix/sprite.png [moved from theme/bootstrap/pix/sprite.png with 100% similarity]
theme/bootstrapbase/pix/vertical-menu-submenu-indicator.png [moved from theme/bootstrap/pix/vertical-menu-submenu-indicator.png with 100% similarity]
theme/bootstrapbase/pix/yui2-treeview-sprite-rtl.gif [moved from theme/bootstrap/pix/yui2-treeview-sprite-rtl.gif with 100% similarity]
theme/bootstrapbase/readme_moodle.txt [moved from theme/bootstrap/readme_moodle.txt with 84% similarity]
theme/bootstrapbase/renderers.php [moved from theme/bootstrap/renderers.php with 96% similarity]
theme/bootstrapbase/renderers/core.php [moved from theme/bootstrap/renderers/core.php with 98% similarity]
theme/bootstrapbase/style/README [new file with mode: 0644]
theme/bootstrapbase/style/editor.css [moved from theme/bootstrap/style/editor.css with 100% similarity]
theme/bootstrapbase/style/moodle.css [new file with mode: 0644]
theme/bootstrapbase/version.php [moved from theme/bootstrap/version.php with 93% similarity]
theme/bootstrapbase/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap-debug.js [moved from theme/bootstrap/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap-debug.js with 100% similarity]
theme/bootstrapbase/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap-min.js [moved from theme/bootstrap/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap-min.js with 100% similarity]
theme/bootstrapbase/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap.js [moved from theme/bootstrap/yui/build/moodle-theme_bootstrap-bootstrap/moodle-theme_bootstrap-bootstrap.js with 100% similarity]
theme/bootstrapbase/yui/build/moodle-theme_bootstrapbase-bootstrap/moodle-theme_bootstrapbase-bootstrap-debug.js [new file with mode: 0644]
theme/bootstrapbase/yui/build/moodle-theme_bootstrapbase-bootstrap/moodle-theme_bootstrapbase-bootstrap-min.js [new file with mode: 0644]
theme/bootstrapbase/yui/build/moodle-theme_bootstrapbase-bootstrap/moodle-theme_bootstrapbase-bootstrap.js [new file with mode: 0644]
theme/bootstrapbase/yui/src/bootstrap/build.json [moved from theme/bootstrap/yui/src/bootstrap/build.json with 68% similarity]
theme/bootstrapbase/yui/src/bootstrap/js/bootstrap.js [moved from theme/bootstrap/yui/src/bootstrap/js/bootstrap.js with 95% similarity]
theme/bootstrapbase/yui/src/bootstrap/js/bootstrapcollapse.js [moved from theme/bootstrap/yui/src/bootstrap/js/bootstrapcollapse.js with 100% similarity]
theme/bootstrapbase/yui/src/bootstrap/js/bootstrapdropdown.js [moved from theme/bootstrap/yui/src/bootstrap/js/bootstrapdropdown.js with 100% similarity]
theme/bootstrapbase/yui/src/bootstrap/js/bootstrapengine.js [moved from theme/bootstrap/yui/src/bootstrap/js/bootstrapengine.js with 100% similarity]
theme/bootstrapbase/yui/src/bootstrap/meta/bootstrap.json [moved from theme/bootstrap/yui/src/bootstrap/meta/bootstrap.json with 62% similarity]
theme/brick/settings.php
theme/clean/README.txt [moved from theme/simple/README.txt with 78% similarity]
theme/clean/config.php [moved from theme/simple/config.php with 85% similarity]
theme/clean/lang/en/theme_clean.php [moved from theme/simple/lang/en/theme_simple.php with 82% similarity]
theme/clean/layout/general.php [moved from theme/simple/layout/general.php with 90% similarity]
theme/clean/lib.php [moved from theme/simple/lib.php with 79% similarity]
theme/clean/pix/favicon.ico [new file with mode: 0644]
theme/clean/pix/screenshot.jpg [moved from theme/simple/pix/screenshot.jpg with 100% similarity]
theme/clean/settings.php [moved from theme/simple/settings.php with 67% similarity]
theme/clean/style/custom.css [moved from theme/simple/style/custom.css with 100% similarity]
theme/clean/version.php [moved from theme/simple/version.php with 86% similarity]
theme/formal_white/settings.php
theme/fusion/settings.php
theme/magazine/settings.php
theme/mymobile/settings.php
theme/nimble/settings.php
theme/nonzero/settings.php
theme/overlay/settings.php
theme/sky_high/settings.php
theme/splash/settings.php
theme/styles.php
theme/upgrade.txt
user/externallib.php
version.php
webservice/externallib.php

index 972bf51..08157df 100644 (file)
@@ -152,7 +152,7 @@ if ($fetchremote) {
 $deployer = available_update_deployer::instance();
 if ($deployer->enabled()) {
     $myurl = new moodle_url($PAGE->url, array('updatesonly' => $updatesonly, 'contribonly' => $contribonly));
-    $deployer->initialize($myurl, $myurl);
+    $deployer->initialize($myurl, new moodle_url('/admin'));
 
     $deploydata = $deployer->submitted_data();
     if (!empty($deploydata)) {
index 863af66..9e28f03 100644 (file)
@@ -49,8 +49,10 @@ class site_unregistration_form extends moodleform {
         $unregisterlabel = get_string('unregister', 'hub');
         $mform->addElement('checkbox', 'unpublishalladvertisedcourses', '',
                 ' ' . get_string('unpublishalladvertisedcourses', 'hub'));
+        $mform->setType('unpublishalladvertisedcourses', PARAM_INT);
         $mform->addElement('checkbox', 'unpublishalluploadedcourses', '',
                 ' ' . get_string('unpublishalluploadedcourses', 'hub'));
+        $mform->setType('unpublishalluploadedcourses', PARAM_INT);
 
         $mform->addElement('hidden', 'confirm', 1);
         $mform->setType('confirm', PARAM_INT);
@@ -82,7 +84,6 @@ class site_clean_registration_data_form extends moodleform {
         $unregisterlabel = get_string('forceunregister', 'hub');
         $mform->addElement('static', '', get_string('warning', 'hub'), get_string('forceunregisterconfirmation', 'hub', $hubname));
 
-
         $mform->addElement('hidden', 'confirm', 1);
         $mform->setType('confirm', PARAM_INT);
         $mform->addElement('hidden', 'unregistration', 1);
@@ -149,6 +150,7 @@ class hub_selector_form extends moodleform {
         if (!empty($hubs)) {
             $mform->addElement('select', 'publichub', get_string('publichub', 'hub'),
                     $options, array("size" => 15));
+            $mform->setType('publichub', PARAM_URL);
         }
 
         $mform->addElement('static', 'or', '', get_string('orenterprivatehub', 'hub'));
@@ -156,8 +158,10 @@ class hub_selector_form extends moodleform {
         //Private hub
         $mform->addElement('text', 'unlistedurl', get_string('privatehuburl', 'hub'),
                 array('class' => 'registration_textfield'));
+        $mform->setType('unlistedurl', PARAM_URL);
         $mform->addElement('text', 'password', get_string('password'),
                 array('class' => 'registration_textfield'));
+        $mform->setType('password', PARAM_RAW);
 
         $this->add_action_buttons(false, get_string('selecthub', 'hub'));
     }
@@ -171,11 +175,8 @@ class hub_selector_form extends moodleform {
 
         $unlistedurl = $this->_form->_submitValues['unlistedurl'];
 
-        if (!empty($unlistedurl)) {
-            $unlistedurltotest = clean_param($unlistedurl, PARAM_URL);
-            if (empty($unlistedurltotest)) {
-                $errors['unlistedurl'] = get_string('badurlformat', 'hub');
-            }
+        if (empty($unlistedurl)) {
+            $errors['unlistedurl'] = get_string('badurlformat', 'hub');
         }
 
         return $errors;
@@ -272,6 +273,7 @@ class site_registration_form extends moodleform {
         $options[HUB_SITELINKPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITELINKPUBLISHED);
         $mform->addElement('select', 'privacy', get_string('siteprivacy', 'hub'), $options);
         $mform->setDefault('privacy', $privacy);
+        $mform->setType('privacy', PARAM_ALPHA);
         $mform->addHelpButton('privacy', 'privacy', 'hub');
         unset($options);
 
@@ -305,11 +307,13 @@ class site_registration_form extends moodleform {
         $countries = get_string_manager()->get_list_of_countries();
         $mform->addElement('select', 'countrycode', get_string('sitecountry', 'hub'), $countries);
         $mform->setDefault('countrycode', $country);
+        $mform->setType('countrycode', PARAM_ALPHANUMEXT);
         $mform->addHelpButton('countrycode', 'sitecountry', 'hub');
 
         $mform->addElement('text', 'geolocation', get_string('sitegeolocation', 'hub'),
                 array('class' => 'registration_textfield'));
         $mform->setDefault('geolocation', $geolocation);
+        $mform->setType('geolocation', PARAM_RAW);
         $mform->addHelpButton('geolocation', 'sitegeolocation', 'hub');
 
         $mform->addElement('text', 'contactname', get_string('siteadmin', 'hub'),
@@ -327,7 +331,7 @@ class site_registration_form extends moodleform {
         $mform->addElement('text', 'contactemail', get_string('siteemail', 'hub'),
                 array('class' => 'registration_textfield'));
         $mform->addRule('contactemail', $strrequired, 'required', null, 'client');
-        $mform->setType('contactemail', PARAM_TEXT);
+        $mform->setType('contactemail', PARAM_EMAIL);
         $mform->setDefault('contactemail', $contactemail);
         $mform->addHelpButton('contactemail', 'siteemail', 'hub');
 
@@ -336,6 +340,7 @@ class site_registration_form extends moodleform {
         $options[1] = get_string("registrationcontactyes");
         $mform->addElement('select', 'contactable', get_string('siteregistrationcontact', 'hub'), $options);
         $mform->setDefault('contactable', $contactable);
+        $mform->setType('contactable', PARAM_INT);
         $mform->addHelpButton('contactable', 'siteregistrationcontact', 'hub');
         unset($options);
 
@@ -344,6 +349,7 @@ class site_registration_form extends moodleform {
         $options[1] = get_string("registrationyes");
         $mform->addElement('select', 'emailalert', get_string('siteregistrationemail', 'hub'), $options);
         $mform->setDefault('emailalert', $emailalert);
+        $mform->setType('emailalert', PARAM_INT);
         $mform->addHelpButton('emailalert', 'siteregistrationemail', 'hub');
         unset($options);
 
@@ -381,79 +387,89 @@ class site_registration_form extends moodleform {
         if (HUB_MOODLEORGHUBURL != $huburl) {
             $mform->addElement('checkbox', 'courses', get_string('sendfollowinginfo', 'hub'),
                     " " . get_string('coursesnumber', 'hub', $coursecount));
-            $mform->setDefault('courses', true);
+            $mform->setDefault('courses', 1);
+            $mform->setType('courses', PARAM_INT);
             $mform->addHelpButton('courses', 'sendfollowinginfo', 'hub');
 
             $mform->addElement('checkbox', 'users', '',
                     " " . get_string('usersnumber', 'hub', $usercount));
-            $mform->setDefault('users', true);
+            $mform->setDefault('users', 1);
+            $mform->setType('users', PARAM_INT);
 
             $mform->addElement('checkbox', 'roleassignments', '',
                     " " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
-            $mform->setDefault('roleassignments', true);
+            $mform->setDefault('roleassignments', 1);
+            $mform->setType('roleassignments', PARAM_INT);
 
             $mform->addElement('checkbox', 'posts', '',
                     " " . get_string('postsnumber', 'hub', $postcount));
-            $mform->setDefault('posts', true);
+            $mform->setDefault('posts', 1);
+            $mform->setType('posts', PARAM_INT);
 
             $mform->addElement('checkbox', 'questions', '',
                     " " . get_string('questionsnumber', 'hub', $questioncount));
-            $mform->setDefault('questions', true);
+            $mform->setDefault('questions', 1);
+            $mform->setType('questions', PARAM_INT);
 
             $mform->addElement('checkbox', 'resources', '',
                     " " . get_string('resourcesnumber', 'hub', $resourcecount));
-            $mform->setDefault('resources', true);
+            $mform->setDefault('resources', 1);
+            $mform->setType('resources', PARAM_INT);
 
             $mform->addElement('checkbox', 'badges', '',
                     " " . get_string('badgesnumber', 'hub', $badges));
-            $mform->setDefault('badges', true);
+            $mform->setDefault('badges', 1);
+            $mform->setType('resources', PARAM_INT);
 
             $mform->addElement('checkbox', 'issuedbadges', '',
                     " " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
-            $mform->setDefault('issuedbadges', true);
+            $mform->setDefault('issuedbadges', 1);
+            $mform->setType('resources', PARAM_INT);
 
             $mform->addElement('checkbox', 'participantnumberaverage', '',
                     " " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
-            $mform->setDefault('participantnumberaverage', true);
+            $mform->setDefault('participantnumberaverage', 1);
+            $mform->setType('participantnumberaverage', PARAM_FLOAT);
 
             $mform->addElement('checkbox', 'modulenumberaverage', '',
                     " " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
-            $mform->setDefault('modulenumberaverage', true);
+            $mform->setDefault('modulenumberaverage', 1);
+            $mform->setType('modulenumberaverage', PARAM_FLOAT);
         } else {
             $mform->addElement('static', 'courseslabel', get_string('sendfollowinginfo', 'hub'),
                     " " . get_string('coursesnumber', 'hub', $coursecount));
-            $mform->addElement('hidden', 'courses', true);
-            $mform->setType('courses', PARAM_FLOAT);
+            $mform->addElement('hidden', 'courses', 1);
+            $mform->setType('courses', PARAM_INT);
             $mform->addHelpButton('courseslabel', 'sendfollowinginfo', 'hub');
 
             $mform->addElement('static', 'userslabel', '',
                     " " . get_string('usersnumber', 'hub', $usercount));
-            $mform->addElement('hidden', 'users', true);
-            $mform->setType('users', PARAM_FLOAT);
+            $mform->addElement('hidden', 'users', 1);
+            $mform->setType('users', PARAM_INT);
 
             $mform->addElement('static', 'roleassignmentslabel', '',
                     " " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
-            $mform->addElement('hidden', 'roleassignments', true);
-            $mform->setType('roleassignments', PARAM_FLOAT);
+            $mform->addElement('hidden', 'roleassignments', 1);
+            $mform->setType('roleassignments', PARAM_INT);
 
             $mform->addElement('static', 'postslabel', '',
                     " " . get_string('postsnumber', 'hub', $postcount));
-            $mform->addElement('hidden', 'posts', true);
-            $mform->setType('posts', PARAM_FLOAT);
+            $mform->addElement('hidden', 'posts', 1);
+            $mform->setType('posts', PARAM_INT);
 
             $mform->addElement('static', 'questionslabel', '',
                     " " . get_string('questionsnumber', 'hub', $questioncount));
-            $mform->addElement('hidden', 'questions', true);
-            $mform->setType('questions', PARAM_FLOAT);
+            $mform->addElement('hidden', 'questions', 1);
+            $mform->setType('questions', PARAM_INT);
 
             $mform->addElement('static', 'resourceslabel', '',
                     " " . get_string('resourcesnumber', 'hub', $resourcecount));
-            $mform->addElement('hidden', 'resources', true);
-            $mform->setType('resources', PARAM_FLOAT);
+            $mform->addElement('hidden', 'resources', 1);
+            $mform->setType('resources', PARAM_INT);
 
             $mform->addElement('static', 'badgeslabel', '',
                     " " . get_string('badgesnumber', 'hub', $badges));
-            $mform->addElement('hidden', 'badges', true);
+            $mform->addElement('hidden', 'badges', 1);
             $mform->setType('badges', PARAM_INT);
 
             $mform->addElement('static', 'issuedbadgeslabel', '',
@@ -463,12 +479,12 @@ class site_registration_form extends moodleform {
 
             $mform->addElement('static', 'participantnumberaveragelabel', '',
                     " " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
-            $mform->addElement('hidden', 'participantnumberaverage', true);
+            $mform->addElement('hidden', 'participantnumberaverage', 1);
             $mform->setType('participantnumberaverage', PARAM_FLOAT);
 
             $mform->addElement('static', 'modulenumberaveragelabel', '',
                     " " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
-            $mform->addElement('hidden', 'modulenumberaverage', true);
+            $mform->addElement('hidden', 'modulenumberaverage', 1);
             $mform->setType('modulenumberaverage', PARAM_FLOAT);
         }
 
index 5f96325..9f53ead 100644 (file)
@@ -279,10 +279,10 @@ class core_admin_renderer extends plugin_renderer_base {
             $output .= $this->output->container(get_string('updatepluginconfirmexternal', 'core_plugin', $repotype), 'updatepluginconfirmexternal');
         }
 
-        $widget = $deployer->make_execution_widget($data['updateinfo']);
+        $widget = $deployer->make_execution_widget($data['updateinfo'], $data['returnurl']);
         $output .= $this->output->render($widget);
 
-        $output .= $this->output->single_button($data['returnurl'], get_string('cancel', 'core'), 'get');
+        $output .= $this->output->single_button($data['callerurl'], get_string('cancel', 'core'), 'get');
 
         $output .= $this->container_end();
         $output .= $this->footer();
@@ -896,7 +896,7 @@ class core_admin_renderer extends plugin_renderer_base {
                         continue;
                     }
 
-                } else if ($isstandard and $statusisboring and $dependenciesok and empty($availableupdates)) {
+                } else if ($statusisboring and $dependenciesok and empty($availableupdates)) {
                     // no change is going to happen to the plugin - display it only
                     // if the user wants to see the full list
                     if (empty($options['full'])) {
@@ -1179,9 +1179,12 @@ class core_admin_renderer extends plugin_renderer_base {
                 } else {
                     $icon = $this->output->pix_icon('spacer', '', 'moodle', array('class' => 'icon pluginicon noicon'));
                 }
-                if ($plugin->get_status() === plugin_manager::PLUGIN_STATUS_MISSING) {
-                    $msg = html_writer::tag('span', get_string('status_missing', 'core_plugin'), array('class' => 'notifyproblem'));
-                    $row->attributes['class'] .= ' missingfromdisk';
+                $status = $plugin->get_status();
+                $row->attributes['class'] .= ' status-'.$status;
+                if ($status === plugin_manager::PLUGIN_STATUS_MISSING) {
+                    $msg = html_writer::tag('span', get_string('status_missing', 'core_plugin'), array('class' => 'statusmsg'));
+                } else if ($status === plugin_manager::PLUGIN_STATUS_NEW) {
+                    $msg = html_writer::tag('span', get_string('status_new', 'core_plugin'), array('class' => 'statusmsg'));
                 } else {
                     $msg = '';
                 }
index 9100567..e751525 100644 (file)
@@ -11,30 +11,77 @@ if ($hassiteconfig
     $ADMIN->add('courses', new admin_externalpage('coursemgmt', new lang_string('coursemgmt', 'admin'), $CFG->wwwroot . '/course/manage.php',
             array('moodle/category:manage', 'moodle/course:create')));
 
-/// Course Default Settings Page
-/// NOTE: these settings must be applied after all other settings because they depend on them
-    ///main course settings
+    // Course Default Settings Page.
+    // NOTE: these settings must be applied after all other settings because they depend on them.
+
+
+    // Main course settings.
     $temp = new admin_settingpage('coursesettings', new lang_string('coursesettings'));
     require_once($CFG->dirroot.'/course/lib.php');
+
+    $choices = array();
+    $choices['0'] = new lang_string('hide');
+    $choices['1'] = new lang_string('show');
+    $temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), new lang_string('visible_help'),
+        1, $choices));
+
+
+    // Course format.
+    $temp->add(new admin_setting_heading('courseformathdr', new lang_string('type_format', 'plugin'), ''));
+
     $courseformats = get_sorted_course_formats(true);
     $formcourseformats = array();
     foreach ($courseformats as $courseformat) {
         $formcourseformats[$courseformat] = new lang_string('pluginname', "format_$courseformat");
     }
-    $temp->add(new admin_setting_configselect('moodlecourse/format', new lang_string('format'), new lang_string('coursehelpformat'), 'weeks',$formcourseformats));
+    $temp->add(new admin_setting_configselect('moodlecourse/format', new lang_string('format'), new lang_string('coursehelpformat'),
+        'weeks',$formcourseformats));
 
-    $temp->add(new admin_setting_configtext('moodlecourse/maxsections', new lang_string('maxnumberweeks'), new lang_string('maxnumberweeks_desc'), 52));
+    $temp->add(new admin_setting_configtext('moodlecourse/maxsections', new lang_string('maxnumberweeks'),
+        new lang_string('maxnumberweeks_desc'), 52));
 
-    $temp->add(new admin_settings_num_course_sections('moodlecourse/numsections', new lang_string('numberweeks'), new lang_string('coursehelpnumberweeks'), 10));
+    $temp->add(new admin_settings_num_course_sections('moodlecourse/numsections', new lang_string('numberweeks'),
+        new lang_string('coursehelpnumberweeks'), 10));
 
     $choices = array();
     $choices['0'] = new lang_string('hiddensectionscollapsed');
     $choices['1'] = new lang_string('hiddensectionsinvisible');
-    $temp->add(new admin_setting_configselect('moodlecourse/hiddensections', new lang_string('hiddensections'), new lang_string('coursehelphiddensections'), 0,$choices));
+    $temp->add(new admin_setting_configselect('moodlecourse/hiddensections', new lang_string('hiddensections'),
+        new lang_string('coursehelphiddensections'), 0, $choices));
+
+    $choices = array();
+    $choices[COURSE_DISPLAY_SINGLEPAGE] = new lang_string('coursedisplay_single');
+    $choices[COURSE_DISPLAY_MULTIPAGE] = new lang_string('coursedisplay_multi');
+    $temp->add(new admin_setting_configselect('moodlecourse/coursedisplay', new lang_string('coursedisplay'),
+        new lang_string('coursedisplay_help'), COURSE_DISPLAY_SINGLEPAGE, $choices));
+
+
+    // Appearance.
+    $temp->add(new admin_setting_heading('appearancehdr', new lang_string('appearance'), ''));
+
+    $languages = array();
+    $languages[''] = new lang_string('forceno');
+    $languages += get_string_manager()->get_list_of_translations();
+    $temp->add(new admin_setting_configselect('moodlecourse/lang', new lang_string('forcelanguage'), '', key($languages),
+        $languages));
+
     $options = range(0, 10);
-    $temp->add(new admin_setting_configselect('moodlecourse/newsitems', new lang_string('newsitemsnumber'), new lang_string('coursehelpnewsitemsnumber'), 5,$options));
-    $temp->add(new admin_setting_configselect('moodlecourse/showgrades', new lang_string('showgrades'), new lang_string('coursehelpshowgrades'), 1,array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
-    $temp->add(new admin_setting_configselect('moodlecourse/showreports', new lang_string('showreports'), '', 0,array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
+    $temp->add(new admin_setting_configselect('moodlecourse/newsitems', new lang_string('newsitemsnumber'),
+        new lang_string('coursehelpnewsitemsnumber'), 5, $options));
+    $temp->add(new admin_setting_configselect('moodlecourse/showgrades', new lang_string('showgrades'),
+        new lang_string('coursehelpshowgrades'), 1, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
+    $temp->add(new admin_setting_configselect('moodlecourse/showreports', new lang_string('showreports'), '', 0,
+        array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
+
+
+    // Files and uploads.
+    $temp->add(new admin_setting_heading('filesanduploadshdr', new lang_string('filesanduploads'), ''));
+
+    if (!empty($CFG->legacyfilesinnewcourses)) {
+        $choices = array('0'=>new lang_string('no'), '2'=>new lang_string('yes'));
+        $temp->add(new admin_setting_configselect('moodlecourse/legacyfiles', new lang_string('courselegacyfiles'),
+            new lang_string('courselegacyfiles_help'), key($choices), $choices));
+    }
 
     $currentmaxbytes = get_config('moodlecourse', 'maxbytes');
     if (isset($CFG->maxbytes)) {
@@ -42,18 +89,17 @@ if ($hassiteconfig
     } else {
         $choices = get_max_upload_sizes(0, 0, 0, $currentmaxbytes);
     }
-    $temp->add(new admin_setting_configselect('moodlecourse/maxbytes', new lang_string('maximumupload'), new lang_string('coursehelpmaximumupload'), key($choices), $choices));
+    $temp->add(new admin_setting_configselect('moodlecourse/maxbytes', new lang_string('maximumupload'),
+        new lang_string('coursehelpmaximumupload'), key($choices), $choices));
 
-    if (!empty($CFG->legacyfilesinnewcourses)) {
-        $choices = array('0'=>new lang_string('no'), '2'=>new lang_string('yes'));
-        $temp->add(new admin_setting_configselect('moodlecourse/legacyfiles', new lang_string('courselegacyfiles'), new lang_string('courselegacyfiles_help'), key($choices), $choices));
-    }
 
-    $choices = array();
-    $choices[COURSE_DISPLAY_SINGLEPAGE] = new lang_string('coursedisplay_single');
-    $choices[COURSE_DISPLAY_MULTIPAGE] = new lang_string('coursedisplay_multi');
-    $temp->add(new admin_setting_configselect('moodlecourse/coursedisplay', new lang_string('coursedisplay'), new lang_string('coursedisplay_help'), COURSE_DISPLAY_SINGLEPAGE, $choices));
+    // Completion tracking.
+    $temp->add(new admin_setting_heading('progress', new lang_string('completion','completion'), ''));
+    $temp->add(new admin_setting_configselect('moodlecourse/enablecompletion', new lang_string('completion', 'completion'),
+        new lang_string('enablecompletion_help', 'completion'), 0, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
+
 
+    // Groups.
     $temp->add(new admin_setting_heading('groups', new lang_string('groups', 'group'), ''));
     $choices = array();
     $choices[NOGROUPS] = new lang_string('groupsnone', 'group');
@@ -62,27 +108,10 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configselect('moodlecourse/groupmode', new lang_string('groupmode'), '', key($choices),$choices));
     $temp->add(new admin_setting_configselect('moodlecourse/groupmodeforce', new lang_string('force'), new lang_string('coursehelpforce'), 0,array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
 
-
-    $temp->add(new admin_setting_heading('availability', new lang_string('availability'), ''));
-    $choices = array();
-    $choices['0'] = new lang_string('courseavailablenot');
-    $choices['1'] = new lang_string('courseavailable');
-    $temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), '', 1,$choices));
-
-
-    $temp->add(new admin_setting_heading('language', new lang_string('language'), ''));
-    $languages=array();
-    $languages[''] = new lang_string('forceno');
-    $languages += get_string_manager()->get_list_of_translations();
-    $temp->add(new admin_setting_configselect('moodlecourse/lang', new lang_string('forcelanguage'), '',key($languages),$languages));
-
-    $temp->add(new admin_setting_heading('progress', new lang_string('progress','completion'), ''));
-    $temp->add(new admin_setting_configselect('moodlecourse/enablecompletion', new lang_string('completion','completion'), '',
-        0, array(0 => new lang_string('completiondisabled','completion'), 1 => new lang_string('completionenabled','completion'))));
-
     $ADMIN->add('courses', $temp);
 
-/// "courserequests" settingpage
+
+    // "courserequests" settingpage.
     $temp = new admin_settingpage('courserequest', new lang_string('courserequest'));
     $temp->add(new admin_setting_configcheckbox('enablecourserequests', new lang_string('enablecourserequests', 'admin'), new lang_string('configenablecourserequests', 'admin'), 0));
     $temp->add(new admin_settings_coursecat_select('defaultrequestcategory', new lang_string('defaultrequestcategory', 'admin'), new lang_string('configdefaultrequestcategory', 'admin'), 1));
index a9aeb58..291329d 100644 (file)
@@ -44,6 +44,7 @@ class tool_assignmentupgrade_batchoperations_form extends moodleform {
         $mform->addElement('header', 'general', get_string('batchoperations', 'tool_assignmentupgrade'));
         // Visible elements.
         $mform->addElement('hidden', 'selectedassignments', '', array('class'=>'selectedassignments'));
+        $mform->setType('selectedassignments', PARAM_SEQUENCE);
 
         $mform->addElement('submit', 'upgradeselected', get_string('upgradeselected', 'tool_assignmentupgrade'));
         $mform->addElement('submit', 'upgradeall', get_string('upgradeall', 'tool_assignmentupgrade'));
index 1fb8b9c..715c116 100644 (file)
@@ -43,6 +43,7 @@ class database_export_form extends moodleform {
 
         $mform->addElement('header', 'database', get_string('dbexport', 'tool_dbtransfer'));
         $mform->addElement('textarea', 'description', get_string('description'), array('rows'=>5, 'cols'=>60));
+        $mform->setType('description', PARAM_TEXT);
 
         $this->add_action_buttons(false, get_string('exportdata', 'tool_dbtransfer'));
     }
index d8a9923..3b408e4 100644 (file)
@@ -52,17 +52,32 @@ class database_transfer_form extends moodleform {
         $drivers = array_reverse($drivers, true);
 
         $mform->addElement('select', 'driver', get_string('dbtype', 'install'), $drivers);
+        $mform->setType('driver', PARAM_RAW);
+
         $mform->addElement('text', 'dbhost', get_string('databasehost', 'install'));
+        $mform->setType('dbhost', PARAM_HOST);
+
         $mform->addElement('text', 'dbname', get_string('databasename', 'install'));
+        $mform->setType('dbname', PARAM_ALPHANUMEXT);
+
         $mform->addElement('text', 'dbuser', get_string('databaseuser', 'install'));
+        $mform->setType('dbuser', PARAM_ALPHANUMEXT);
+
         $mform->addElement('passwordunmask', 'dbpass', get_string('databasepass', 'install'));
+        $mform->setType('dbpass', PARAM_RAW);
+
         $mform->addElement('text', 'prefix', get_string('dbprefix', 'install'));
+        $mform->setType('prefix', PARAM_ALPHANUMEXT);
+
         $mform->addElement('text', 'dbport', get_string('dbport', 'install'));
+        $mform->setType('dbport', PARAM_INT);
+
         if ($CFG->ostype !== 'WINDOWS') {
             $mform->addElement('text', 'dbsocket', get_string('databasesocket', 'install'));
         } else {
             $mform->addElement('hidden', 'dbsocket');
         }
+        $mform->setType('dbsocket', PARAM_RAW);
 
         $mform->addRule('driver', get_string('required'), 'required', null);
         $mform->addRule('dbhost', get_string('required'), 'required', null);
@@ -76,6 +91,7 @@ class database_transfer_form extends moodleform {
         $mform->addElement('header', 'database', get_string('options', 'tool_dbtransfer'));
 
         $mform->addElement('advcheckbox', 'enablemaintenance', get_string('enablemaintenance', 'tool_dbtransfer'));
+        $mform->setType('enablemaintenance', PARAM_BOOL);
         $mform->addHelpButton('enablemaintenance', 'enablemaintenance', 'tool_dbtransfer');
 
         $this->add_action_buttons(false, get_string('transferdata', 'tool_dbtransfer'));
index ec41f8e..60473f5 100644 (file)
@@ -40,17 +40,21 @@ class tool_qeupgradehelper_cron_setup_form extends moodleform {
 
         $mform->addElement('selectyesno', 'cronenabled',
                 get_string('cronenabled', 'tool_qeupgradehelper'));
+        $mform->setType('cronenabled', PARAM_BOOL);
 
         $mform->addElement('select', 'starthour',
                 get_string('cronstarthour', 'tool_qeupgradehelper'), range(0, 23));
+        $mform->setType('starthour', PARAM_INT);
 
         $mform->addElement('select', 'stophour',
                 get_string('cronstophour', 'tool_qeupgradehelper'),
                 array_combine(range(1, 24), range(1, 24)));
+        $mform->setType('stophour', PARAM_INT);
         $mform->setDefault('stophour', 24);
 
         $mform->addElement('duration', 'procesingtime',
                 get_string('cronprocesingtime', 'tool_qeupgradehelper'));
+        $mform->setType('procesingtime', PARAM_INT);
         $mform->setDefault('procesingtime', 60);
 
         $mform->disabledIf('starthour', 'cronenabled', 'eq', 0);
index cced4bc..d9c568b 100644 (file)
@@ -51,12 +51,23 @@ class tool_qeupgradehelper_extract_options_form extends moodleform {
 
         $mform->addElement('header', 'h1', 'Either extract a specific question_session');
         $mform->addElement('text', 'attemptid', 'Quiz attempt id', array('size' => '10'));
+        $mform->setType('attemptid', PARAM_INT);
+
         $mform->addElement('text', 'questionid', 'Question id', array('size' => '10'));
+        $mform->setType('questionid', PARAM_INT);
+
         $mform->addElement('header', 'h2', 'Or find and extract an example by type');
         $mform->addElement('select', 'behaviour', 'Behaviour', $behaviour);
+        $mform->setType('behaviour', PARAM_ALPHA);
+
         $mform->addElement('text', 'statehistory', 'State history', array('size' => '10'));
+        $mform->setType('statehistory', PARAM_RAW);
+
         $mform->addElement('select', 'qtype', 'Question type', $qtypes);
+        $mform->setType('qtype', PARAM_PLUGIN);
+
         $mform->addElement('text', 'extratests', 'Extra conditions', array('size' => '50'));
+        $mform->setType('extratests', PARAM_RAW);
         $this->add_action_buttons(false, 'Create test case');
     }
 }
index 88aaeda..dd1baec 100644 (file)
@@ -900,7 +900,28 @@ if ($formdata = $mform2->is_cancelled()) {
                 }
             }
 
-            if ($manual and $manualcache[$courseid]) {
+            if ($courseid == SITEID) {
+                // Technically frontpage does not have enrolments, but only role assignments,
+                // let's not invent new lang strings here for this rarely used feature.
+
+                if (!empty($user->{'role'.$i})) {
+                    $addrole = $user->{'role'.$i};
+                    if (array_key_exists($addrole, $rolecache)) {
+                        $rid = $rolecache[$addrole]->id;
+                    } else {
+                        $upt->track('enrolments', get_string('unknownrole', 'error', s($addrole)), 'error');
+                        continue;
+                    }
+
+                    role_assign($rid, $user->id, context_course::instance($courseid));
+
+                    $a = new stdClass();
+                    $a->course = $shortname;
+                    $a->role   = $rolecache[$rid]->name;
+                    $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
+                }
+
+            } else if ($manual and $manualcache[$courseid]) {
 
                 // find role
                 $rid = false;
index 745e9e1..6a1cc49 100644 (file)
@@ -40,10 +40,12 @@ class external_service_authorised_user_settings_form extends moodleform {
         $mform->addElement('text', 'iprestriction',
                 get_string('iprestriction', 'webservice'));
         $mform->addHelpButton('iprestriction', 'iprestriction', 'webservice');
+        $mform->setType('iprestriction', PARAM_RAW_TRIMMED);
 
         $mform->addElement('date_selector', 'validuntil',
                 get_string('validuntil', 'webservice'), array('optional' => true));
         $mform->addHelpButton('validuntil', 'validuntil', 'webservice');
+        $mform->setType('validuntil', PARAM_INT);
 
         $this->add_action_buttons(true, get_string('updateusersettings', 'webservice'));
 
@@ -65,14 +67,17 @@ class external_service_form extends moodleform {
         $mform->addRule('name', get_string('required'), 'required', null, 'client');
         $mform->setType('name', PARAM_TEXT);
         $mform->addElement('advcheckbox', 'enabled', get_string('enabled', 'webservice'));
+        $mform->setType('enabled', PARAM_BOOL);
         $mform->addElement('advcheckbox', 'restrictedusers',
                 get_string('restrictedusers', 'webservice'));
         $mform->addHelpButton('restrictedusers', 'restrictedusers', 'webservice');
+        $mform->setType('restrictedusers', PARAM_BOOL);
 
         //can users download files
         $mform->addElement('advcheckbox', 'downloadfiles', get_string('downloadfiles', 'webservice'));
         $mform->setAdvanced('downloadfiles');
         $mform->addHelpButton('downloadfiles', 'downloadfiles', 'webservice');
+        $mform->setType('downloadfiles', PARAM_BOOL);
 
         /// needed to select automatically the 'No required capability" option
         $currentcapabilityexist = false;
@@ -100,6 +105,7 @@ class external_service_form extends moodleform {
                 get_string('requiredcapability', 'webservice'), $capabilitychoices);
         $mform->addHelpButton('requiredcapability', 'requiredcapability', 'webservice');
         $mform->setAdvanced('requiredcapability');
+        $mform->setType('requiredcapability', PARAM_RAW);
 /// display notification error if the current requiredcapability doesn't exist anymore
         if (empty($currentcapabilityexist)) {
             global $OUTPUT;
@@ -209,9 +215,11 @@ class web_service_token_form extends moodleform {
                     $options[$userid] = fullname($user);
                 }
                 $mform->addElement('searchableselector', 'user', get_string('user'), $options);
+                $mform->setType('user', PARAM_INT);
             } else {
                 //simple text box for username or user id (if two username exists, a form error is displayed)
                 $mform->addElement('text', 'user', get_string('usernameorid', 'webservice'));
+                $mform->setType('user', PARAM_RAW_TRIMMED);
             }
             $mform->addRule('user', get_string('required'), 'required', null, 'client');
         }
@@ -231,12 +239,14 @@ class web_service_token_form extends moodleform {
         }
         $mform->addElement('select', 'service', get_string('service', 'webservice'), $options);
         $mform->addRule('service', get_string('required'), 'required', null, 'client');
-
+        $mform->setType('service', PARAM_INT);
 
         $mform->addElement('text', 'iprestriction', get_string('iprestriction', 'webservice'));
+        $mform->setType('iprestriction', PARAM_RAW_TRIMMED);
 
         $mform->addElement('date_selector', 'validuntil',
                 get_string('validuntil', 'webservice'), array('optional' => true));
+        $mform->setType('validuntil', PARAM_INT);
 
         $mform->addElement('hidden', 'action');
         $mform->setType('action', PARAM_ALPHANUMEXT);
index 228c7b7..dd9dc48 100644 (file)
@@ -29,9 +29,9 @@ require_once($CFG->libdir.'/adminlib.php');
 require_once("$CFG->libdir/externallib.php");
 require_once($CFG->dirroot . "/" . $CFG->admin . "/webservice/testclient_forms.php");
 
-$function = optional_param('function', '', PARAM_SAFEDIR);
-$protocol = optional_param('protocol', '', PARAM_SAFEDIR);
-$authmethod = optional_param('authmethod', '', PARAM_SAFEDIR);
+$function = optional_param('function', '', PARAM_PLUGIN);
+$protocol = optional_param('protocol', '', PARAM_ALPHA);
+$authmethod = optional_param('authmethod', '', PARAM_ALPHA);
 
 $PAGE->set_url('/' . $CFG->admin . '/webservice/testclient.php');
 $PAGE->navbar->ignore_active(true);
index 04cc360..ab88e23 100644 (file)
@@ -14,10 +14,13 @@ class webservice_test_client_form extends moodleform {
 
         $authmethod = array('simple' => 'simple', 'token' => 'token');
         $mform->addElement('select', 'authmethod', get_string('authmethod', 'webservice'), $authmethod);
+        $mform->setType('simple', PARAM_ALPHA);
 
         $mform->addElement('select', 'protocol', get_string('protocol', 'webservice'), $protocols);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $mform->addElement('select', 'function', get_string('function', 'webservice'), $functions);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $this->add_action_buttons(false, get_string('select'));
     }
@@ -38,9 +41,12 @@ class moodle_user_create_users_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
@@ -48,19 +54,26 @@ class moodle_user_create_users_form extends moodleform {
 
         /// specific to the create users function
         $mform->addElement('text', 'username', 'username');
+        $mform->setType('username', PARAM_USERNAME);
         $mform->addElement('text', 'password', 'password');
+        $mform->setType('password', PARAM_RAW);
         $mform->addElement('text', 'firstname', 'firstname');
+        $mform->setType('firstname', PARAM_RAW);
         $mform->addElement('text', 'lastname', 'lastname');
+        $mform->setType('lastname', PARAM_RAW);
         $mform->addElement('text', 'email', 'email');
+        $mform->setType('email', PARAM_EMAIL);
 
         $mform->addElement('text', 'customfieldtype', 'customfieldtype');
+        $mform->setType('customfieldtype', PARAM_RAW);
         $mform->addElement('text', 'customfieldvalue', 'customfieldvalue');
+        $mform->setType('customfieldvalue', PARAM_RAW);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
 
 
@@ -112,32 +125,43 @@ class moodle_user_update_users_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
 
         /// specific to the create users function
         $mform->addElement('text', 'id', 'id');
         $mform->addRule('id', get_string('required'), 'required', null, 'client');
+        $mform->setType('id', PARAM_INT);
         $mform->addElement('text', 'username', 'username');
+        $mform->setType('username', PARAM_USERNAME);
         $mform->addElement('text', 'password', 'password');
+        $mform->setType('password', PARAM_RAW);
         $mform->addElement('text', 'firstname', 'firstname');
+        $mform->setType('firstname', PARAM_RAW);
         $mform->addElement('text', 'lastname', 'lastname');
+        $mform->setType('lastname', PARAM_RAW);
         $mform->addElement('text', 'email', 'email');
+        $mform->setType('email', PARAM_EMAIL);
 
 
         $mform->addElement('text', 'customfieldtype', 'customfieldtype');
+        $mform->setType('customfieldtype', PARAM_RAW);
         $mform->addElement('text', 'customfieldvalue', 'customfieldvalue');
+        $mform->setType('customfieldvalue', PARAM_RAW);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
 
 
@@ -195,28 +219,30 @@ class moodle_user_delete_users_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
 
         /// beginning of specific code to the create users function
         $mform->addElement('text', 'userids[0]', 'userids[0]');
         $mform->addElement('text', 'userids[1]', 'userids[1]');
         $mform->addElement('text', 'userids[2]', 'userids[2]');
         $mform->addElement('text', 'userids[3]', 'userids[3]');
+        $mform->setType('userids', PARAM_INT);
         /// end of specific code to the create users function
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
-
-
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $mform->addElement('static', 'warning', '', get_string('executewarnign', 'webservice'));
 
@@ -265,26 +291,30 @@ class moodle_user_get_users_by_id_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
 
         /// beginning of specific code to the create users function
         $mform->addElement('text', 'userids[0]', 'userids[0]');
         $mform->addElement('text', 'userids[1]', 'userids[1]');
         $mform->addElement('text', 'userids[2]', 'userids[2]');
         $mform->addElement('text', 'userids[3]', 'userids[3]');
+        $mform->setType('userids', PARAM_INT);
         /// end of specific code to the create users function
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
 
 
@@ -334,24 +364,31 @@ class moodle_group_create_groups_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
 
         $mform->addElement('text', 'courseid', 'courseid');
+        $mform->setType('courseid', PARAM_INT);
         $mform->addElement('text', 'name', 'name');
+        $mform->setType('name', PARAM_TEXT);
         $mform->addElement('text', 'description', 'description');
+        $mform->setType('description', PARAM_TEXT);
         $mform->addElement('text', 'enrolmentkey', 'enrolmentkey');
+        $mform->setType('enrolmentkey', PARAM_RAW);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
 
 
@@ -393,23 +430,27 @@ class moodle_group_get_groups_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'groupids[0]', 'groupids[0]');
         $mform->addElement('text', 'groupids[1]', 'groupids[1]');
         $mform->addElement('text', 'groupids[2]', 'groupids[2]');
         $mform->addElement('text', 'groupids[3]', 'groupids[3]');
+        $mform->setType('groupids', PARAM_INT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -452,20 +493,23 @@ class moodle_group_get_course_groups_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'courseid', 'courseid');
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -502,23 +546,27 @@ class moodle_group_delete_groups_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'groupids[0]', 'groupids[0]');
         $mform->addElement('text', 'groupids[1]', 'groupids[1]');
         $mform->addElement('text', 'groupids[2]', 'groupids[2]');
         $mform->addElement('text', 'groupids[3]', 'groupids[3]');
+        $mform->setType('groupids', PARAM_INT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $mform->addElement('static', 'warning', '', get_string('executewarnign', 'webservice'));
 
@@ -563,23 +611,27 @@ class moodle_group_get_groupmembers_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'groupids[0]', 'groupids[0]');
         $mform->addElement('text', 'groupids[1]', 'groupids[1]');
         $mform->addElement('text', 'groupids[2]', 'groupids[2]');
         $mform->addElement('text', 'groupids[3]', 'groupids[3]');
+        $mform->setType('groupids', PARAM_INT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -622,9 +674,12 @@ class moodle_group_add_groupmembers_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
@@ -633,12 +688,14 @@ class moodle_group_add_groupmembers_form extends moodleform {
         $mform->addElement('text', 'groupid[0]', 'groupid[0]');
         $mform->addElement('text', 'userid[1]', 'userid[1]');
         $mform->addElement('text', 'groupid[1]', 'groupid[1]');
+        $mform->setType('userid', PARAM_INT);
+        $mform->setType('groupids', PARAM_INT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -681,23 +738,28 @@ class moodle_group_delete_groupmembers_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
-        } else  if ($data['authmethod'] == 'token') {
+            $mform->setType('wspassword', PARAM_RAW);
+        } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'userid[0]', 'userid[0]');
         $mform->addElement('text', 'groupid[0]', 'groupid[0]');
         $mform->addElement('text', 'userid[1]', 'userid[1]');
         $mform->addElement('text', 'groupid[1]', 'groupid[1]');
+        $mform->setType('userid', PARAM_INT);
+        $mform->setType('groupids', PARAM_INT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -750,13 +812,16 @@ class core_course_create_categories_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
+            $mform->setType('wspassword', PARAM_RAW);
         } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'name[0]', 'name[0]');
         $mform->addElement('text', 'parent[0]', 'parent[0]');
         $mform->addElement('text', 'idnumber[0]', 'idnumber[0]');
@@ -765,12 +830,16 @@ class core_course_create_categories_form extends moodleform {
         $mform->addElement('text', 'parent[1]', 'parent[1]');
         $mform->addElement('text', 'idnumber[1]', 'idnumber[1]');
         $mform->addElement('text', 'description[1]', 'description[1]');
+        $mform->setType('name', PARAM_TEXT);
+        $mform->setType('parent', PARAM_INT);
+        $mform->setType('idnumber', PARAM_RAW);
+        $mform->setType('description', PARAM_TEXT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -827,25 +896,31 @@ class core_course_delete_categories_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
+            $mform->setType('wspassword', PARAM_RAW);
         } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'id[0]', 'id[0]');
         $mform->addElement('text', 'newparent[0]', 'newparent[0]');
         $mform->addElement('text', 'recursive[0]', 'recursive[0]');
         $mform->addElement('text', 'id[1]', 'id[1]');
         $mform->addElement('text', 'newparent[1]', 'newparent[1]');
         $mform->addElement('text', 'recursive[1]', 'recursive[1]');
+        $mform->setType('id', PARAM_INT);
+        $mform->setType('newparent', PARAM_INT);
+        $mform->setType('recursive', PARAM_BOOL);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
@@ -909,13 +984,16 @@ class core_course_update_categories_form extends moodleform {
         $data = $this->_customdata;
         if ($data['authmethod'] == 'simple') {
             $mform->addElement('text', 'wsusername', 'wsusername');
+            $mform->setType('wsusername', PARAM_USERNAME);
             $mform->addElement('text', 'wspassword', 'wspassword');
+            $mform->setType('wspassword', PARAM_RAW);
         } else if ($data['authmethod'] == 'token') {
             $mform->addElement('text', 'token', 'token');
+            $mform->setType('token', PARAM_RAW_TRIMMED);
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', PARAM_SAFEDIR);
+        $mform->setType('authmethod', PARAM_ALPHA);
         $mform->addElement('text', 'id[0]', 'id[0]');
         $mform->addElement('text', 'name[0]', 'name[0]');
         $mform->addElement('text', 'parent[0]', 'parent[0]');
@@ -926,12 +1004,17 @@ class core_course_update_categories_form extends moodleform {
         $mform->addElement('text', 'parent[1]', 'parent[1]');
         $mform->addElement('text', 'idnumber[1]', 'idnumber[1]');
         $mform->addElement('text', 'description[1]', 'description[1]');
+        $mform->setType('id', PARAM_INT);
+        $mform->setType('name', PARAM_TEXT);
+        $mform->setType('parent', PARAM_INT);
+        $mform->setType('idnumber', PARAM_RAW);
+        $mform->setType('description', PARAM_TEXT);
 
         $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setType('function', PARAM_PLUGIN);
 
         $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_SAFEDIR);
+        $mform->setType('protocol', PARAM_ALPHA);
 
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
index f0604a5..04ccc81 100644 (file)
@@ -97,6 +97,10 @@ abstract class base_moodleform extends moodleform {
                 $stage = $mform->addElement('hidden', $name, $value);
                 if (in_array($name, $intparams)) {
                     $mform->setType($name, PARAM_INT);
+                } else {
+                    // Adding setType() to avoid missing setType() warnings.
+                    // MDL-39126: support $mform->setType() for additional backup parameters.
+                    $mform->setType($name, PARAM_RAW);
                 }
             }
         }
index 3e00e62..cb8d7d3 100644 (file)
@@ -93,7 +93,9 @@ class community_hub_search_form extends moodleform {
 
         //add the course id (of the context)
         $mform->addElement('hidden', 'courseid', $this->_customdata['courseid']);
+        $mform->setType('courseid', PARAM_INT);
         $mform->addElement('hidden', 'executesearch', 1);
+        $mform->setType('executesearch', PARAM_INT);
 
         //retrieve the hub list on the hub directory by web service
         $function = 'hubdirectory_get_hubs';
@@ -298,7 +300,7 @@ class community_hub_search_form extends moodleform {
             $mform->addElement('text', 'search', get_string('keywords', 'block_community'),
                 array('size' => 30));
             $mform->addHelpButton('search', 'keywords', 'block_community');
-
+            $mform->setType('search', PARAM_NOTAGS);
 
             $mform->addElement('submit', 'submitbutton', get_string('search', 'block_community'));
         }
index d555668..bb2fa22 100644 (file)
@@ -836,7 +836,8 @@ M.core_dock.genericblock.prototype = {
         }
 
         // Must set the image src seperatly of we get an error with XML strict headers
-        var moveto = Y.Node.create('<input type="image" class="moveto customcommand requiresjs" alt="'+M.str.block.addtodock+'" title="'+M.str.block.addtodock+'" />');
+        var moveto = Y.Node.create('<input type="image" class="moveto customcommand requiresjs" alt="'+M.str.block.addtodock+'" title="'+
+            Y.Escape.html(M.util.get_string('dockblock', 'block', node.one('.header .title h2').getHTML())) +'" />');
         var icon = 't/block_to_dock';
         if (right_to_left()) {
             icon = 't/block_to_dock_rtl';
@@ -906,7 +907,8 @@ M.core_dock.genericblock.prototype = {
         }
 
         // Must set the image src seperatly of we get an error with XML strict headers
-        var movetoimg = Y.Node.create('<img alt="'+M.str.block.undockitem+'" title="'+M.util.get_string('undockblock', 'block', blocktitle.innerHTML)+'" />');
+        var movetoimg = Y.Node.create('<img alt="'+Y.Escape.html(M.str.block.undockitem)+'" title="'+
+            Y.Escape.html(M.util.get_string('undockblock', 'block', blocktitle.innerHTML)) +'" />');
         var icon = 't/dock_to_block';
         if (right_to_left()) {
             icon = 't/dock_to_block_rtl';
index 236c103..4a54754 100644 (file)
@@ -59,6 +59,12 @@ class block_base {
      */
     var $title         = NULL;
 
+    /**
+     * The name of the block to be displayed in the block title area if the title is empty.
+     * @var string arialabel
+     */
+    var $arialabel         = NULL;
+
     /**
      * The type of content that this block creates. Currently support options - BLOCK_TYPE_LIST, BLOCK_TYPE_TEXT
      * @var int $content_type
@@ -240,8 +246,10 @@ class block_base {
         if (!$this->hide_header()) {
             $bc->title = $this->title;
         }
+
         if (empty($bc->title)) {
             $bc->arialabel = new lang_string('pluginname', get_class($this));
+            $this->arialabel = $bc->arialabel;
         }
 
         if ($this->page->user_is_editing()) {
index 621c09c..3868c90 100644 (file)
@@ -18,6 +18,7 @@ A definition:
             'requiremultipleidentifiers' => false,    // Optional
             'requirelockingread' => false,            // Optional
             'requirelockingwrite' => false,           // Optional
+            'requiresearchable' => false,             // Optional
             'maxsize' => null,                        // Optional
             'overrideclass' => null,                  // Optional
             'overrideclassfile' => null,              // Optional
@@ -135,6 +136,7 @@ The following optional settings can also be defined:
 * requiremultipleidentifiers - If set to true then only stores that support multiple identifiers will be used.
 * requirelockingread - If set to true a lock will be acquired for reading. Don't use this setting unless you have a REALLY good reason to.
 * requirelockingwrite - If set to true a lock will be acquired before writing to the cache. Avoid this unless necessary.
+* requiresearchable - If set to true only stores that support key searching will be used for this definition. Its not recommended to use this unless absolutely unavoidable.
 * maxsize - This gives a cache an indication about the maximum items it should store. Cache stores don't have to use this, it is up to them to decide if its required.
 * overrideclass - If provided this class will be used for the loader. It must extend one of the core loader classes (based upon mode).
 * overrideclassfile - Included if required when using the overrideclass param.
@@ -236,4 +238,4 @@ The following snippet illustates how to configure the three core cache stores th
 
     define('TEST_CACHESTORE_MEMCACHE_TESTSERVERS', '127.0.0.1:11211');
     define('TEST_CACHESTORE_MEMCACHED_TESTSERVERS', '127.0.0.1:11211');
-    define('TEST_CACHESTORE_MONGODB_TESTSERVER', 'mongodb://localhost:27017');
\ No newline at end of file
+    define('TEST_CACHESTORE_MONGODB_TESTSERVER', 'mongodb://localhost:27017');
index 8c5a16a..62732f7 100644 (file)
@@ -183,6 +183,13 @@ class cache_definition {
      */
     protected $requirelockingwrite = false;
 
+    /**
+     * Gets set to true if this definition requires searchable stores.
+     * @since 2.4.4
+     * @var bool
+     */
+    protected $requiresearchable = false;
+
     /**
      * Sets the maximum number of items that can exist in the cache.
      * Please note this isn't a hard limit, and doesn't need to be enforced by the caches. They can choose to do so optionally.
@@ -307,6 +314,7 @@ class cache_definition {
         $requiremultipleidentifiers = false;
         $requirelockingread = false;
         $requirelockingwrite = false;
+        $requiresearchable = ($mode === cache_store::MODE_SESSION) ? true : false;
         $maxsize = null;
         $overrideclass = null;
         $overrideclassfile = null;
@@ -342,6 +350,10 @@ class cache_definition {
         }
         $requirelocking = $requirelockingwrite || $requirelockingread;
 
+        if (array_key_exists('requiresearchable', $definition)) {
+            $requiresearchable = (bool)$definition['requiresearchable'];
+        }
+
         if (array_key_exists('maxsize', $definition)) {
             $maxsize = (int)$definition['maxsize'];
         }
@@ -433,6 +445,7 @@ class cache_definition {
         $cachedefinition->requirelocking = $requirelocking;
         $cachedefinition->requirelockingread = $requirelockingread;
         $cachedefinition->requirelockingwrite = $requirelockingwrite;
+        $cachedefinition->requiresearchable = $requiresearchable;
         $cachedefinition->maxsize = $maxsize;
         $cachedefinition->overrideclass = $overrideclass;
         $cachedefinition->overrideclassfile = $overrideclassfile;
@@ -633,6 +646,15 @@ class cache_definition {
         return $this->requirelockingwrite;
     }
 
+    /**
+     * Returns true if this definition requires a searchable cache.
+     * @since 2.4.4
+     * @return bool
+     */
+    public function require_searchable() {
+        return $this->requiresearchable;
+    }
+
     /**
      * Returns true if this definition has an associated data source.
      * @return bool
@@ -686,6 +708,9 @@ class cache_definition {
         if ($this->require_multiple_identifiers()) {
             $requires += cache_store::SUPPORTS_MULTIPLE_IDENTIFIERS;
         }
+        if ($this->require_searchable()) {
+            $requires += cache_store::IS_SEARCHABLE;
+        }
         return $requires;
     }
 
@@ -694,7 +719,7 @@ class cache_definition {
      * @return bool
      */
     public function should_be_persistent() {
-        return $this->persistent;
+        return $this->persistent || $this->mode === cache_store::MODE_SESSION;
     }
 
     /**
index 9eee85a..e57d6ef 100644 (file)
@@ -207,9 +207,7 @@ class cache_factory {
         if (array_key_exists($key, $this->cachesfromparams)) {
             return $this->cachesfromparams[$key];
         }
-        // Get the class. Note this is a late static binding so we need to use get_called_class.
         $definition = cache_definition::load_adhoc($mode, $component, $area, $options);
-        $config = $this->create_config_instance();
         $definition->set_identifiers($identifiers);
         $cache = $this->create_cache($definition, $identifiers);
         if ($definition->should_be_persistent()) {
index 075dc41..be329f7 100644 (file)
@@ -244,10 +244,9 @@ class cache_helper {
             if ($definition->invalidates_on_event($event)) {
                 // OK at this point we know that the definition has information to invalidate on the event.
                 // There are two routes, either its an application cache in which case we can invalidate it now.
-                // or it is a session cache in which case we need to set something to the "Event invalidation" definition.
-                // No need to deal with request caches, we don't want to change data half way through a request.
-                if ($definition->get_mode() === cache_store::MODE_APPLICATION) {
-                    $cache = $factory->create_cache($definition);
+                // or it is a persistent cache that also needs to be invalidated now.
+                if ($definition->get_mode() === cache_store::MODE_APPLICATION || $definition->should_be_persistent()) {
+                    $cache = $factory->create_cache_from_definition($definition->get_component(), $definition->get_area());
                     $cache->delete_many($keys);
                 }
 
@@ -568,4 +567,64 @@ class cache_helper {
         global $CFG;
         return (string)$CFG->version;
     }
+
+    /**
+     * Runs cron routines for MUC.
+     */
+    public static function cron() {
+        self::clean_old_session_data(true);
+    }
+
+    /**
+     * Cleans old session data from cache stores used for session based definitions.
+     *
+     * @param bool $output If set to true output will be given.
+     */
+    public static function clean_old_session_data($output = false) {
+        global $CFG;
+        if ($output) {
+            mtrace('Cleaning up stale session data from cache stores.');
+        }
+        $factory = cache_factory::instance();
+        $config = $factory->create_config_instance();
+        $definitions = $config->get_definitions();
+        $purgetime = time() - $CFG->sessiontimeout;
+        foreach ($definitions as $definitionarray) {
+            // We are only interested in session caches.
+            if (!($definitionarray['mode'] & cache_store::MODE_SESSION)) {
+                continue;
+            }
+            $definition = $factory->create_definition($definitionarray['component'], $definitionarray['area']);
+            $stores = $config->get_stores_for_definition($definition);
+            // Turn them into store instances.
+            $stores = self::initialise_cachestore_instances($stores, $definition);
+            // Initialise all of the stores used for that definition.
+            foreach ($stores as $store) {
+                // If the store doesn't support searching we can skip it.
+                if (!($store instanceof cache_is_searchable)) {
+                    debugging('Cache stores used for session definitions should ideally be searchable.', DEBUG_DEVELOPER);
+                    continue;
+                }
+                // Get all of the keys.
+                $keys = $store->find_by_prefix(cache_session::KEY_PREFIX);
+                $todelete = array();
+                foreach ($store->get_many($keys) as $key => $value) {
+                    if (strpos($key, cache_session::KEY_PREFIX) !== 0 || !is_array($value) || !isset($value['lastaccess'])) {
+                        continue;
+                    }
+                    if ((int)$value['lastaccess'] < $purgetime || true) {
+                        $todelete[] = $key;
+                    }
+                }
+                if (count($todelete)) {
+                    $outcome = (int)$store->delete_many($todelete);
+                    if ($output) {
+                        $strdef = s($definition->get_id());
+                        $strstore = s($store->my_name());
+                        mtrace("- Removed {$outcome} old {$strdef} sessions from the '{$strstore}' cache store.");
+                    }
+                }
+            }
+        }
+    }
 }
index d548349..24996ed 100644 (file)
@@ -338,6 +338,30 @@ interface cache_is_key_aware {
     public function has_all(array $keys);
 }
 
+/**
+ * Cache store feature: keys are searchable.
+ *
+ * Cache stores can choose to implement this interface.
+ * In order for a store to be usable as a session cache it must implement this interface.
+ *
+ * @since 2.4.4
+ */
+interface cache_is_searchable {
+    /**
+     * Finds all of the keys being used by the cache store.
+     *
+     * @return array.
+     */
+    public function find_all();
+
+    /**
+     * Finds all of the keys whose keys start with the given prefix.
+     *
+     * @param string $prefix
+     */
+    public function find_by_prefix($prefix);
+}
+
 /**
  * Cache store feature: configurable.
  *
index fd1a340..9f7dc79 100644 (file)
@@ -141,7 +141,7 @@ class cache implements cache_loader {
      * and having it here helps speed up processing.
      * @var strubg
      */
-    private $storetype = 'unknown';
+    protected $storetype = 'unknown';
 
     /**
      * Gets set to true if we want to collect performance information about the cache API.
@@ -365,6 +365,7 @@ class cache implements cache_loader {
      */
     public function get_many(array $keys, $strictness = IGNORE_MISSING) {
 
+        $keysparsed = array();
         $parsedkeys = array();
         $resultpersist = array();
         $resultstore = array();
@@ -374,6 +375,7 @@ class cache implements cache_loader {
         $isusingpersist = $this->is_using_persist_cache();
         foreach ($keys as $key) {
             $pkey = $this->parse_key($key);
+            $keysparsed[$key] = $pkey;
             $parsedkeys[$pkey] = $key;
             $keystofind[$pkey] = $key;
             if ($isusingpersist) {
@@ -426,9 +428,11 @@ class cache implements cache_loader {
                     $resultmissing = $this->datasource->load_many_for_cache($missingkeys);
                 }
                 foreach ($resultmissing as $key => $value) {
-                    $result[$key] = $value;
+                    $pkey = ($usingloader) ? $key : $keysparsed[$key];
+                    $realkey = ($usingloader) ? $parsedkeys[$key] : $key;
+                    $result[$pkey] = $value;
                     if ($value !== false) {
-                        $this->set($parsedkeys[$key], $value);
+                        $this->set($realkey, $value);
                     }
                 }
                 unset($resultmissing);
@@ -748,7 +752,7 @@ class cache implements cache_loader {
     public function delete($key, $recurse = true) {
         $parsedkey = $this->parse_key($key);
         $this->delete_from_persist_cache($parsedkey);
-        if ($recurse && !empty($this->loader)) {
+        if ($recurse && $this->loader !== false) {
             // Delete from the bottom of the stack first.
             $this->loader->delete($key, $recurse);
         }
@@ -770,7 +774,7 @@ class cache implements cache_loader {
                 $this->delete_from_persist_cache($parsedkey);
             }
         }
-        if ($recurse && !empty($this->loader)) {
+        if ($recurse && $this->loader !== false) {
             // Delete from the bottom of the stack first.
             $this->loader->delete_many($keys, $recurse);
         }
@@ -848,6 +852,26 @@ class cache implements cache_loader {
         return $this->store;
     }
 
+    /**
+     * Returns the loader associated with this instance.
+     *
+     * @since 2.4.4
+     * @return cache_loader|false
+     */
+    protected function get_loader() {
+        return $this->loader;
+    }
+
+    /**
+     * Returns the data source associated with this cache.
+     *
+     * @since 2.4.4
+     * @return cache_data_source|false
+     */
+    protected function get_datasource() {
+        return $this->datasource;
+    }
+
     /**
      * Returns true if the store supports key awareness.
      *
@@ -1396,6 +1420,18 @@ class cache_application extends cache implements cache_loader_with_locking {
  *
  * This class is used for session caches returned by the cache::make methods.
  *
+ * It differs from the application loader in a couple of noteable ways:
+ *    1. Sessions are always expected to be persistent.
+ *       Because of this we don't ever use the persist cache and instead a session array
+ *       containing all of the data is maintained by this object.
+ *    2. Session data for a loader instance (store + definition) is consolidate into a
+ *       single array for storage within the store.
+ *       Along with this we embed a lastaccessed time with the data. This way we can
+ *       check sessions for a last access time.
+ *    3. Session stores are required to support key searching and must
+ *       implement cache_is_searchable. This ensures stores used for the cache can be
+ *       targetted for garbage collection of session data.
+ *
  * This cache class should never be interacted with directly. Instead you should always use the cache::make methods.
  * It is technically possible to call those methods through this class however there is no guarantee that you will get an
  * instance of this class back again.
@@ -1421,6 +1457,24 @@ class cache_session extends cache {
      * @var int
      */
     protected $currentuserid = null;
+
+    /**
+     * The session id we are currently using.
+     * @var array
+     */
+    protected $sessionid = null;
+
+    /**
+     * The session data for the above session id.
+     * @var array
+     */
+    protected $session = null;
+
+    /**
+     * Constant used to prefix keys.
+     */
+    const KEY_PREFIX = 'sess_';
+
     /**
      * Override the cache::construct method.
      *
@@ -1494,12 +1548,16 @@ class cache_session extends cache {
      * This function is called for every operation that uses keys. For this reason we use this function to also check
      * that the current user is the same as the user who last used this cache.
      *
+     * On top of that if prepends the string 'sess_' to the start of all keys. The _ ensures things are easily identifiable.
+     *
      * @param string|int $key As passed to get|set|delete etc.
      * @return string|array String unless the store supports multi-identifiers in which case an array if returned.
      */
     protected function parse_key($key) {
-        $this->check_tracked_user();
-        return parent::parse_key($key);
+        if ($key === 'lastaccess') {
+            $key = '__lastaccess__';
+        }
+        return 'sess_'.parent::parse_key($key);
     }
 
     /**
@@ -1514,11 +1572,13 @@ class cache_session extends cache {
             $new = 0;
         }
         if ($new !== self::$loadeduserid) {
-            // The current user doesn't match the tracker userid for this request.
+            // The current user doesn't match the tracked userid for this request.
             if (!is_null(self::$loadeduserid)) {
                 // Purge the data we have for the old user.
                 // This way we don't bloat the session.
                 $this->purge();
+                // Update the session id just in case!
+                $this->sessionid = session_id();
             }
             self::$loadeduserid = $new;
             $this->currentuserid = $new;
@@ -1526,7 +1586,426 @@ class cache_session extends cache {
             // The current user matches the loaded user but not the user last used by this cache.
             $this->purge();
             $this->currentuserid = $new;
+            // Update the session id just in case!
+            $this->sessionid = session_id();
+        }
+    }
+
+    /**
+     * Gets the session data.
+     *
+     * @param bool $force If true the session data will be loaded from the store again.
+     * @return array An array of session data.
+     */
+    protected function get_session_data($force = false) {
+        if ($this->sessionid === null) {
+            $this->sessionid = session_id();
+        }
+        if (is_array($this->session) && !$force) {
+            return $this->session;
+        }
+        $session = parent::get($this->sessionid);
+        if ($session === false) {
+            $session = array();
+        }
+        // We have to write here to ensure that the lastaccess time is recorded.
+        // And also in order to ensure the session entry exists as when we save it on __destruct
+        // $CFG is likely to have already been destroyed.
+        $this->save_session($session);
+        return $this->session;
+    }
+
+    /**
+     * Saves the session data.
+     *
+     * This function also updates the last access time.
+     *
+     * @param array $session
+     * @return bool
+     */
+    protected function save_session(array $session) {
+        $session['lastaccess'] = time();
+        $this->session = $session;
+        return parent::set($this->sessionid, $this->session);
+    }
+
+    /**
+     * Retrieves the value for the given key from the cache.
+     *
+     * @param string|int $key The key for the data being requested.
+     *      It can be any structure although using a scalar string or int is recommended in the interests of performance.
+     *      In advanced cases an array may be useful such as in situations requiring the multi-key functionality.
+     * @param int $strictness One of IGNORE_MISSING | MUST_EXIST
+     * @return mixed|false The data from the cache or false if the key did not exist within the cache.
+     * @throws moodle_exception
+     */
+    public function get($key, $strictness = IGNORE_MISSING) {
+        // Check the tracked user.
+        $this->check_tracked_user();
+        // 2. Parse the key.
+        $parsedkey = $this->parse_key($key);
+        // 3. Get it from the store.
+        $result = false;
+        $session = $this->get_session_data();
+        if (array_key_exists($parsedkey, $session)) {
+            $result = $session[$parsedkey];
+            if ($result instanceof cache_ttl_wrapper) {
+                if ($result->has_expired()) {
+                    $this->get_store()->delete($parsedkey);
+                    $result = false;
+                } else {
+                    $result = $result->data;
+                }
+            }
+            if ($result instanceof cache_cached_object) {
+                $result = $result->restore_object();
+            }
+        }
+        // 4. Load if from the loader/datasource if we don't already have it.
+        $setaftervalidation = false;
+        if ($result === false) {
+            if ($this->perfdebug) {
+                cache_helper::record_cache_miss('**static session**', $this->get_definition()->get_id());
+            }
+            if ($this->get_loader() !== false) {
+                // We must pass the original (unparsed) key to the next loader in the chain.
+                // The next loader will parse the key as it sees fit. It may be parsed differently
+                // depending upon the capabilities of the store associated with the loader.
+                $result = $this->get_loader()->get($key);
+            } else if ($this->get_datasource() !== false) {
+                $result = $this->get_datasource()->load_for_cache($key);
+            }
+            $setaftervalidation = ($result !== false);
+        } else if ($this->perfdebug) {
+            cache_helper::record_cache_hit('**static session**', $this->get_definition()->get_id());
+        }
+        // 5. Validate strictness.
+        if ($strictness === MUST_EXIST && $result === false) {
+            throw new moodle_exception('Requested key did not exist in any cache stores and could not be loaded.');
         }
+        // 6. Set it to the store if we got it from the loader/datasource.
+        if ($setaftervalidation) {
+            $this->set($key, $result);
+        }
+        // 7. Make sure we don't pass back anything that could be a reference.
+        //    We don't want people modifying the data in the cache.
+        if (!is_scalar($result)) {
+            // If data is an object it will be a reference.
+            // If data is an array if may contain references.
+            // We want to break references so that the cache cannot be modified outside of itself.
+            // Call the function to unreference it (in the best way possible).
+            $result = $this->unref($result);
+        }
+        return $result;
+    }
+
+    /**
+     * Sends a key => value pair to the cache.
+     *
+     * <code>
+     * // This code will add four entries to the cache, one for each url.
+     * $cache->set('main', 'http://moodle.org');
+     * $cache->set('docs', 'http://docs.moodle.org');
+     * $cache->set('tracker', 'http://tracker.moodle.org');
+     * $cache->set('qa', 'http://qa.moodle.net');
+     * </code>
+     *
+     * @param string|int $key The key for the data being requested.
+     *      It can be any structure although using a scalar string or int is recommended in the interests of performance.
+     *      In advanced cases an array may be useful such as in situations requiring the multi-key functionality.
+     * @param mixed $data The data to set against the key.
+     * @return bool True on success, false otherwise.
+     */
+    public function set($key, $data) {
+        $this->check_tracked_user();
+        if ($this->perfdebug) {
+            cache_helper::record_cache_set('**static session**', $this->get_definition()->get_id());
+        }
+        if (is_object($data) && $data instanceof cacheable_object) {
+            $data = new cache_cached_object($data);
+        } else if (!is_scalar($data)) {
+            // If data is an object it will be a reference.
+            // If data is an array if may contain references.
+            // We want to break references so that the cache cannot be modified outside of itself.
+            // Call the function to unreference it (in the best way possible).
+            $data = $this->unref($data);
+        }
+        // We dont' support native TTL here as we consolidate data for sessions.
+        if ($this->has_a_ttl()) {
+            $data = new cache_ttl_wrapper($data, $this->get_definition()->get_ttl());
+        }
+        $session = $this->get_session_data();
+        $session[$this->parse_key($key)] = $data;
+        return $this->save_session($session);
+    }
+
+    /**
+     * Delete the given key from the cache.
+     *
+     * @param string|int $key The key to delete.
+     * @param bool $recurse When set to true the key will also be deleted from all stacked cache loaders and their stores.
+     *     This happens by default and ensure that all the caches are consistent. It is NOT recommended to change this.
+     * @return bool True of success, false otherwise.
+     */
+    public function delete($key, $recurse = true) {
+        $this->check_tracked_user();
+        $parsedkey = $this->parse_key($key);
+        if ($recurse && $this->get_loader() !== false) {
+            // Delete from the bottom of the stack first.
+            $this->get_loader()->delete($key, $recurse);
+        }
+        $session = $this->get_session_data();
+        unset($session[$parsedkey]);
+        return $this->save_session($session);
+    }
+
+    /**
+     * Retrieves an array of values for an array of keys.
+     *
+     * Using this function comes with potential performance implications.
+     * Not all cache stores will support get_many/set_many operations and in order to replicate this functionality will call
+     * the equivalent singular method for each item provided.
+     * This should not deter you from using this function as there is a performance benefit in situations where the cache store
+     * does support it, but you should be aware of this fact.
+     *
+     * @param array $keys The keys of the data being requested.
+     *      Each key can be any structure although using a scalar string or int is recommended in the interests of performance.
+     *      In advanced cases an array may be useful such as in situations requiring the multi-key functionality.
+     * @param int $strictness One of IGNORE_MISSING or MUST_EXIST.
+     * @return array An array of key value pairs for the items that could be retrieved from the cache.
+     *      If MUST_EXIST was used and not all keys existed within the cache then an exception will be thrown.
+     *      Otherwise any key that did not exist will have a data value of false within the results.
+     * @throws moodle_exception
+     */
+    public function get_many(array $keys, $strictness = IGNORE_MISSING) {
+        $this->check_tracked_user();
+        $return = array();
+        foreach ($keys as $key) {
+            $return[$key] = $this->get($key, $strictness);
+        }
+        return $return;
+    }
+
+    /**
+     * Delete all of the given keys from the cache.
+     *
+     * @param array $keys The key to delete.
+     * @param bool $recurse When set to true the key will also be deleted from all stacked cache loaders and their stores.
+     *     This happens by default and ensure that all the caches are consistent. It is NOT recommended to change this.
+     * @return int The number of items successfully deleted.
+     */
+    public function delete_many(array $keys, $recurse = true) {
+        $this->check_tracked_user();
+        $parsedkeys = array_map(array($this, 'parse_key'), $keys);
+        if ($recurse && $this->get_loader() !== false) {
+            // Delete from the bottom of the stack first.
+            $this->get_loader()->delete_many($keys, $recurse);
+        }
+        $session = $this->get_session_data();
+        foreach ($parsedkeys as $parsedkey) {
+            unset($session[$parsedkey]);
+        }
+        $this->save_session($session);
+        return count($keys);
+    }
+
+    /**
+     * Sends several key => value pairs to the cache.
+     *
+     * Using this function comes with potential performance implications.
+     * Not all cache stores will support get_many/set_many operations and in order to replicate this functionality will call
+     * the equivalent singular method for each item provided.
+     * This should not deter you from using this function as there is a performance benefit in situations where the cache store
+     * does support it, but you should be aware of this fact.
+     *
+     * <code>
+     * // This code will add four entries to the cache, one for each url.
+     * $cache->set_many(array(
+     *     'main' => 'http://moodle.org',
+     *     'docs' => 'http://docs.moodle.org',
+     *     'tracker' => 'http://tracker.moodle.org',
+     *     'qa' => ''http://qa.moodle.net'
+     * ));
+     * </code>
+     *
+     * @param array $keyvaluearray An array of key => value pairs to send to the cache.
+     * @return int The number of items successfully set. It is up to the developer to check this matches the number of items.
+     *      ... if they care that is.
+     */
+    public function set_many(array $keyvaluearray) {
+        $this->check_tracked_user();
+        $session = $this->get_session_data();
+        $simulatettl = $this->has_a_ttl();
+        foreach ($keyvaluearray as $key => $value) {
+            if (is_object($value) && $value instanceof cacheable_object) {
+                $value = new cache_cached_object($value);
+            } else if (!is_scalar($value)) {
+                // If data is an object it will be a reference.
+                // If data is an array if may contain references.
+                // We want to break references so that the cache cannot be modified outside of itself.
+                // Call the function to unreference it (in the best way possible).
+                $value = $this->unref($value);
+            }
+            if ($simulatettl) {
+                $value = new cache_ttl_wrapper($value, $this->get_definition()->get_ttl());
+            }
+            $parsedkey = $this->parse_key($key);
+            $session[$parsedkey] = $value;
+        }
+        if ($this->perfdebug) {
+            cache_helper::record_cache_set($this->storetype, $this->get_definition()->get_id());
+        }
+        $this->save_session($session);
+        return count($keyvaluearray);
+    }
+
+    /**
+     * Purges the cache store, and loader if there is one.
+     *
+     * @return bool True on success, false otherwise
+     */
+    public function purge() {
+        // 1. Purge the session object.
+        $this->session = array();
+        // 2. Delete the record for this users session from the store.
+        $this->get_store()->delete($this->sessionid);
+        // 3. Optionally purge any stacked loaders in the same way.
+        if ($this->get_loader()) {
+            $this->get_loader()->delete($this->sessionid);
+        }
+        return true;
+    }
+
+    /**
+     * Test is a cache has a key.
+     *
+     * The use of the has methods is strongly discouraged. In a high load environment the cache may well change between the
+     * test and any subsequent action (get, set, delete etc).
+     * Instead it is recommended to write your code in such a way they it performs the following steps:
+     * <ol>
+     * <li>Attempt to retrieve the information.</li>
+     * <li>Generate the information.</li>
+     * <li>Attempt to set the information</li>
+     * </ol>
+     *
+     * Its also worth mentioning that not all stores support key tests.
+     * For stores that don't support key tests this functionality is mimicked by using the equivalent get method.
+     * Just one more reason you should not use these methods unless you have a very good reason to do so.
+     *
+     * @param string|int $key
+     * @param bool $tryloadifpossible If set to true, the cache doesn't contain the key, and there is another cache loader or
+     *      data source then the code will try load the key value from the next item in the chain.
+     * @return bool True if the cache has the requested key, false otherwise.
+     */
+    public function has($key, $tryloadifpossible = false) {
+        $this->check_tracked_user();
+        $parsedkey = $this->parse_key($key);
+        $session = $this->get_session_data();
+        $has = false;
+        if ($this->has_a_ttl()) {
+            // The data has a TTL and the store doesn't support it natively.
+            // We must fetch the data and expect a ttl wrapper.
+            if (array_key_exists($parsedkey, $session)) {
+                $data = $session[$parsedkey];
+                $has = ($data instanceof cache_ttl_wrapper && !$data->has_expired());
+            }
+        } else {
+            $has = array_key_exists($parsedkey, $session);
+        }
+        if (!$has && $tryloadifpossible) {
+            if ($this->get_loader() !== false) {
+                $result = $this->get_loader()->get($key);
+            } else if ($this->get_datasource() !== null) {
+                $result = $this->get_datasource()->load_for_cache($key);
+            }
+            $has = ($result !== null);
+            if ($has) {
+                $this->set($key, $result);
+            }
+        }
+        return $has;
+    }
+
+    /**
+     * Test is a cache has all of the given keys.
+     *
+     * It is strongly recommended to avoid the use of this function if not absolutely required.
+     * In a high load environment the cache may well change between the test and any subsequent action (get, set, delete etc).
+     *
+     * Its also worth mentioning that not all stores support key tests.
+     * For stores that don't support key tests this functionality is mimicked by using the equivalent get method.
+     * Just one more reason you should not use these methods unless you have a very good reason to do so.
+     *
+     * @param array $keys
+     * @return bool True if the cache has all of the given keys, false otherwise.
+     */
+    public function has_all(array $keys) {
+        $this->check_tracked_user();
+        $session = $this->get_session_data();
+        foreach ($keys as $key) {
+            $has = false;
+            $parsedkey = $this->parse_key($key);
+            if ($this->has_a_ttl()) {
+                // The data has a TTL and the store doesn't support it natively.
+                // We must fetch the data and expect a ttl wrapper.
+                if (array_key_exists($parsedkey, $session)) {
+                    $data = $session[$parsedkey];
+                    $has = ($data instanceof cache_ttl_wrapper && !$data->has_expired());
+                }
+            } else {
+                $has = array_key_exists($parsedkey, $session);
+            }
+            if (!$has) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Test if a cache has at least one of the given keys.
+     *
+     * It is strongly recommended to avoid the use of this function if not absolutely required.
+     * In a high load environment the cache may well change between the test and any subsequent action (get, set, delete etc).
+     *
+     * Its also worth mentioning that not all stores support key tests.
+     * For stores that don't support key tests this functionality is mimicked by using the equivalent get method.
+     * Just one more reason you should not use these methods unless you have a very good reason to do so.
+     *
+     * @param array $keys
+     * @return bool True if the cache has at least one of the given keys
+     */
+    public function has_any(array $keys) {
+        $this->check_tracked_user();
+        $session = $this->get_session_data();
+        foreach ($keys as $key) {
+            $has = false;
+            $parsedkey = $this->parse_key($key);
+            if ($this->has_a_ttl()) {
+                // The data has a TTL and the store doesn't support it natively.
+                // We must fetch the data and expect a ttl wrapper.
+                if (array_key_exists($parsedkey, $session)) {
+                    $data = $session[$parsedkey];
+                    $has = ($data instanceof cache_ttl_wrapper && !$data->has_expired());
+                }
+            } else {
+                $has = array_key_exists($parsedkey, $session);
+            }
+            if ($has) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * The session loader never uses the persist cache.
+     * Instead it stores things in the static $session variable. Shared between all session loaders.
+     *
+     * @return bool
+     */
+    protected function is_using_persist_cache() {
+        return false;
     }
 }
 
index 5bb26e4..d757157 100644 (file)
@@ -110,6 +110,11 @@ abstract class cache_store implements cache_store_interface {
      */
     const SUPPORTS_NATIVE_TTL = 4;
 
+    /**
+     * The cache is searchable by key.
+     */
+    const IS_SEARCHABLE = 8;
+
     // Constants for the modes of a cache store
 
     /**
@@ -307,6 +312,15 @@ abstract class cache_store implements cache_store_interface {
         return $this::get_supported_features() & self::SUPPORTS_NATIVE_TTL;
     }
 
+    /**
+     * Returns true if the store instance is searchable.
+     *
+     * @return bool
+     */
+    public function is_searchable() {
+        return in_array('cache_is_searchable', class_implements($this));
+    }
+
     /**
      * Creates a clone of this store instance ready to be initialised.
      *
index 9708a01..2c12884 100644 (file)
@@ -57,19 +57,20 @@ class cachestore_addinstance_form extends moodleform {
             $form->addElement('text', 'name', get_string('storename', 'cache'));
             $form->addHelpButton('name', 'storename', 'cache');
             $form->addRule('name', get_string('required'), 'required');
-            $form->setType('name', PARAM_TEXT);
+            $form->setType('name', PARAM_NOTAGS);
         } else {
             $form->addElement('hidden', 'name', $store);
             $form->addElement('static', 'name-value', get_string('storename', 'cache'), $store);
-            $form->setType('name', PARAM_TEXT);
+            $form->setType('name', PARAM_NOTAGS);
         }
 
         if (is_array($locks)) {
             $form->addElement('select', 'lock', get_string('lockmethod', 'cache'), $locks);
             $form->addHelpButton('lock', 'lockmethod', 'cache');
-            $form->setType('lock', PARAM_TEXT);
+            $form->setType('lock', PARAM_PLUGIN);
         } else {
             $form->addElement('hidden', 'lock', '');
+            $form->setType('lock', PARAM_PLUGIN);
             $form->addElement('static', 'lock-value', get_string('lockmethod', 'cache'),
                     '<em>'.get_string('nativelocking', 'cache').'</em>');
         }
@@ -139,7 +140,9 @@ class cache_definition_mappings_form extends moodleform {
                 cache_administration_helper::get_definition_store_options($component, $area);
 
         $form->addElement('hidden', 'definition', $definition);
+        $form->setType('definition', PARAM_SAFEPATH);
         $form->addElement('hidden', 'action', 'editdefinitionmapping');
+        $form->setType('action', PARAM_ALPHA);
 
         $requiredoptions = max(3, count($currentstores)+1);
         $requiredoptions = min($requiredoptions, count($storeoptions));
@@ -200,7 +203,7 @@ class cache_mode_mappings_form extends moodleform {
         );
         foreach ($stores as $storename => $store) {
             foreach ($store['modes'] as $mode => $enabled) {
-                if ($enabled) {
+                if ($enabled && ($mode !== cache_store::MODE_SESSION || $store['supports']['searchable'])) {
                     if (empty($store['default'])) {
                         $options[$mode][$storename] = $store['name'];
                     } else {
@@ -211,6 +214,7 @@ class cache_mode_mappings_form extends moodleform {
         }
 
         $form->addElement('hidden', 'action', 'editmodemappings');
+        $form->setType('action', PARAM_ALPHA);
         foreach ($options as $mode => $optionset) {
             $form->addElement('select', 'mode_'.$mode, get_string('mode_'.$mode, 'cache'), $optionset);
         }
index e2b498e..f52570e 100644 (file)
@@ -340,32 +340,7 @@ class cache_config_writer extends cache_config {
         require_once($CFG->dirroot.'/cache/stores/static/lib.php');
 
         $writer = new self;
-        $writer->configstores = array(
-            'default_application' => array(
-                'name' => 'default_application',
-                'plugin' => 'file',
-                'configuration' => array(),
-                'features' => cachestore_file::get_supported_features(),
-                'modes' => cache_store::MODE_APPLICATION,
-                'default' => true,
-            ),
-            'default_session' => array(
-                'name' => 'default_session',
-                'plugin' => 'session',
-                'configuration' => array(),
-                'features' => cachestore_session::get_supported_features(),
-                'modes' => cache_store::MODE_SESSION,
-                'default' => true,
-            ),
-            'default_request' => array(
-                'name' => 'default_request',
-                'plugin' => 'static',
-                'configuration' => array(),
-                'features' => cachestore_static::get_supported_features(),
-                'modes' => cache_store::MODE_REQUEST,
-                'default' => true,
-            )
-        );
+        $writer->configstores = self::get_default_stores();
         $writer->configdefinitions = self::locate_definitions();
         $writer->configmodemappings = array(
             array(
@@ -404,6 +379,52 @@ class cache_config_writer extends cache_config {
         return true;
     }
 
+    /**
+     * Returns an array of default stores for use.
+     *
+     * @return array
+     */
+    protected static function get_default_stores() {
+        return array(
+            'default_application' => array(
+                'name' => 'default_application',
+                'plugin' => 'file',
+                'configuration' => array(),
+                'features' => cachestore_file::get_supported_features(),
+                'modes' => cachestore_file::get_supported_modes(),
+                'default' => true,
+            ),
+            'default_session' => array(
+                'name' => 'default_session',
+                'plugin' => 'session',
+                'configuration' => array(),
+                'features' => cachestore_session::get_supported_features(),
+                'modes' => cachestore_session::get_supported_modes(),
+                'default' => true,
+            ),
+            'default_request' => array(
+                'name' => 'default_request',
+                'plugin' => 'static',
+                'configuration' => array(),
+                'features' => cachestore_static::get_supported_features(),
+                'modes' => cachestore_static::get_supported_modes(),
+                'default' => true,
+            )
+        );
+    }
+
+    /**
+     * Updates the default stores within the MUC config file.
+     */
+    public static function update_default_config_stores() {
+        $factory = cache_factory::instance();
+        $factory->updating_started();
+        $config = $factory->create_config_instance(true);
+        $config->configstores = array_merge($config->configstores, self::get_default_stores());
+        $config->config_save();
+        $factory->updating_finished();
+    }
+
     /**
      * Updates the definition in the configuration from those found in the cache files.
      *
@@ -581,6 +602,7 @@ abstract class cache_administration_helper extends cache_helper {
                     'nativettl' => $store->supports_native_ttl(),
                     'nativelocking' => ($store instanceof cache_is_lockable),
                     'keyawareness' => ($store instanceof cache_is_key_aware),
+                    'searchable' => ($store instanceof cache_is_searchable)
                 )
             );
             if (empty($details['default'])) {
index 855a223..54dfe93 100644 (file)
@@ -37,7 +37,7 @@
  * @copyright  2012 Sam Hemelryk
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class cachestore_file extends cache_store implements cache_is_key_aware, cache_is_configurable  {
+class cachestore_file extends cache_store implements cache_is_key_aware, cache_is_configurable, cache_is_searchable  {
 
     /**
      * The name of the store.
@@ -190,7 +190,8 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
      */
     public static function get_supported_features(array $configuration = array()) {
         $supported = self::SUPPORTS_DATA_GUARANTEE +
-                     self::SUPPORTS_NATIVE_TTL;
+                     self::SUPPORTS_NATIVE_TTL +
+                     self::IS_SEARCHABLE;
         return $supported;
     }
 
@@ -257,13 +258,15 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
 
     /**
      * Gets a pattern suitable for use with glob to find all keys in the cache.
+     *
+     * @param string $prefix A prefix to use.
      * @return string The pattern.
      */
-    protected function glob_keys_pattern() {
+    protected function glob_keys_pattern($prefix = '') {
         if ($this->singledirectory) {
-            return $this->path . '/*.cache';
+            return $this->path . '/'.$prefix.'*.cache';
         } else {
-            return $this->path . '/*/*.cache';
+            return $this->path . '/*/'.$prefix.'*.cache';
         }
     }
 
@@ -365,7 +368,6 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
     public function delete($key) {
         $filename = $key.'.cache';
         $file = $this->file_path_for_key($key);
-
         if (@unlink($file)) {
             unset($this->keys[$filename]);
             return true;
@@ -687,4 +689,42 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
     public function my_name() {
         return $this->name;
     }
+
+    /**
+     * Finds all of the keys being used by this cache store instance.
+     *
+     * @return array
+     */
+    public function find_all() {
+        $this->ensure_path_exists();
+        $files = glob($this->glob_keys_pattern(), GLOB_MARK | GLOB_NOSORT);
+        $return = array();
+        if ($files === false) {
+            return $return;
+        }
+        foreach ($files as $file) {
+            $return[] = substr(basename($file), 0, -6);
+        }
+        return $return;
+    }
+
+    /**
+     * Finds all of the keys whose keys start with the given prefix.
+     *
+     * @param string $prefix
+     */
+    public function find_by_prefix($prefix) {
+        $this->ensure_path_exists();
+        $prefix = preg_replace('#(\*|\?|\[)#', '[$1]', $prefix);
+        $files = glob($this->glob_keys_pattern($prefix), GLOB_MARK | GLOB_NOSORT);
+        $return = array();
+        if ($files === false) {
+            return $return;
+        }
+        foreach ($files as $file) {
+            // Trim off ".cache" from the end.
+            $return[] = substr(basename($file), 0, -6);
+        }
+        return $return;
+    }
 }
index 441bd70..39ebbf3 100644 (file)
@@ -90,7 +90,7 @@ abstract class session_data_store extends cache_store {
  * @copyright  2012 Sam Hemelryk
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class cachestore_session extends session_data_store implements cache_is_key_aware {
+class cachestore_session extends session_data_store implements cache_is_key_aware, cache_is_searchable {
 
     /**
      * The name of the store
@@ -137,7 +137,8 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
      */
     public static function get_supported_features(array $configuration = array()) {
         return self::SUPPORTS_DATA_GUARANTEE +
-               self::SUPPORTS_NATIVE_TTL;
+               self::SUPPORTS_NATIVE_TTL +
+               self::IS_SEARCHABLE;
     }
 
     /**
@@ -403,4 +404,28 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
     public function my_name() {
         return $this->name;
     }
+
+    /**
+     * Finds all of the keys being stored in the cache store instance.
+     *
+     * @return array
+     */
+    public function find_all() {
+        return array_keys($this->store);
+    }
+
+    /**
+     * Finds all of the keys whose keys start with the given prefix.
+     *
+     * @param string $prefix
+     */
+    public function find_by_prefix($prefix) {
+        $return = array();
+        foreach ($this->find_all() as $key) {
+            if (strpos($key, $prefix) === 0) {
+                $return[] = $key;
+            }
+        }
+        return $return;
+    }
 }
\ No newline at end of file
index ba8115f..b13a4b5 100644 (file)
@@ -126,6 +126,18 @@ class cache_phpunit_tests extends advanced_testcase {
         $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'phpunit', 'applicationtest');
         $this->assertInstanceOf('cache_application', $cache);
         $this->run_on_cache($cache);
+
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_definition('phpunit/test_default_application_cache', array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'test_default_application_cache',
+            'persistent' => true,
+            'persistentmaxsize' => 1
+        ));
+        $cache = cache::make('phpunit', 'test_default_application_cache');
+        $this->assertInstanceOf('cache_application', $cache);
+        $this->run_on_cache($cache);
     }
 
     /**
@@ -231,7 +243,7 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertEquals('red_ptc_wfc', $result->property1);
         $this->assertEquals('blue_ptc_wfc', $result->property2);
 
-        // Test array of objects
+        // Test array of objects.
         $specobject = new cache_phpunit_dummy_object('red', 'blue');
         $data = new cacheable_object_array(array(
             clone($specobject),
@@ -255,6 +267,18 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertTrue($cache->delete('key1'));
         $this->assertTrue($cache->delete('key2'));
 
+        $cache->set_many(array(
+            'key1' => array(1, 2, 3),
+            'key2' => array(3, 2, 1),
+        ));
+        $this->assertInternalType('array', $cache->get('key1'));
+        $this->assertInternalType('array', $cache->get('key2'));
+        $this->assertCount(3, $cache->get('key1'));
+        $this->assertCount(3, $cache->get('key2'));
+        $this->assertInternalType('array', $cache->get_many(array('key1', 'key2')));
+        $this->assertCount(2, $cache->get_many(array('key1', 'key2')));
+        $this->assertEquals(2, $cache->delete_many(array('key1', 'key2')));
+
         // Test delete many.
         $this->assertTrue($cache->set('key1', 'data1'));
         $this->assertTrue($cache->set('key2', 'data2'));
@@ -333,6 +357,27 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertEquals('value', $var2->key);
 
         $this->assertTrue($cache->delete('obj'));
+
+        // Test strictness exceptions.
+        try {
+            $cache->get('exception', MUST_EXIST);
+            $this->fail('Exception expected from cache::get using MUST_EXIST');
+        } catch (Exception $e) {
+            $this->assertTrue(true);
+        }
+        try {
+            $cache->get_many(array('exception1', 'exception2'), MUST_EXIST);
+            $this->fail('Exception expected from cache::get_many using MUST_EXIST');
+        } catch (Exception $e) {
+            $this->assertTrue(true);
+        }
+        $cache->set('test', 'test');
+        try {
+            $cache->get_many(array('test', 'exception'), MUST_EXIST);
+            $this->fail('Exception expected from cache::get_many using MUST_EXIST');
+        } catch (Exception $e) {
+            $this->assertTrue(true);
+        }
     }
 
     /**
@@ -355,13 +400,25 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertTrue($cache->purge());
         // It won't be there yet.
         $this->assertFalse($cache->has('Test'));
-
         // It should load it ;).
         $this->assertTrue($cache->has('Test', true));
 
         // Purge it to be sure.
         $this->assertTrue($cache->purge());
         $this->assertEquals('Test has no value really.', $cache->get('Test'));
+
+        // Test multiple values.
+        $this->assertTrue($cache->purge());
+        $this->assertTrue($cache->set('b', 'B'));
+        $result = $cache->get_many(array('a', 'b', 'c'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('b', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertEquals('a has no value really.', $result['a']);
+        $this->assertEquals('B', $result['b']);
+        $this->assertEquals('c has no value really.', $result['c']);
     }
 
     /**
@@ -433,7 +490,10 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertEquals('test data 2', $cache->get('2'));
     }
 
-    public function test_definition_ttl() {
+    /**
+     * Test a negative TTL on an application cache.
+     */
+    public function test_application_ttl_negative() {
         $instance = cache_config_phpunittest::instance(true);
         $instance->phpunit_add_definition('phpunit/ttltest', array(
             'mode' => cache_store::MODE_APPLICATION,
@@ -454,6 +514,127 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertFalse($cache->has('Test'));
         // Double check by trying to get it.
         $this->assertFalse($cache->get('Test'));
+
+        // Test with multiple keys.
+        $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
+        $result = $cache->get_many(array('a', 'b', 'c'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('b', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertFalse($result['a']);
+        $this->assertFalse($result['b']);
+        $this->assertFalse($result['c']);
+
+        // Test with multiple keys including missing ones.
+        $result = $cache->get_many(array('a', 'c', 'e'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertArrayHasKey('e', $result);
+        $this->assertFalse($result['a']);
+        $this->assertFalse($result['c']);
+        $this->assertFalse($result['e']);
+    }
+
+    /**
+     * Test a positive TTL on an application cache.
+     */
+    public function test_application_ttl_positive() {
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_definition('phpunit/ttltest', array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'ttltest',
+            'ttl' => 86400 // Set to a day in the future to be extra sure.
+        ));
+        $cache = cache::make('phpunit', 'ttltest');
+        $this->assertInstanceOf('cache_application', $cache);
+
+        // Purge it to be sure.
+        $this->assertTrue($cache->purge());
+        // It won't be there yet.
+        $this->assertFalse($cache->has('Test'));
+        // Set it now.
+        $this->assertTrue($cache->set('Test', 'Test'));
+        // Check its there.
+        $this->assertTrue($cache->has('Test'));
+        // Double check by trying to get it.
+        $this->assertEquals('Test', $cache->get('Test'));
+
+        // Test with multiple keys.
+        $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
+        $result = $cache->get_many(array('a', 'b', 'c'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('b', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertEquals('A', $result['a']);
+        $this->assertEquals('B', $result['b']);
+        $this->assertEquals('C', $result['c']);
+
+        // Test with multiple keys including missing ones.
+        $result = $cache->get_many(array('a', 'c', 'e'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertArrayHasKey('e', $result);
+        $this->assertEquals('A', $result['a']);
+        $this->assertEquals('C', $result['c']);
+        $this->assertEquals(false, $result['e']);
+    }
+
+    /**
+     * Test a negative TTL on an session cache.
+     */
+    public function test_session_ttl_positive() {
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_definition('phpunit/ttltest', array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'ttltest',
+            'ttl' => 86400 // Set to a day in the future to be extra sure.
+        ));
+        $cache = cache::make('phpunit', 'ttltest');
+        $this->assertInstanceOf('cache_session', $cache);
+
+        // Purge it to be sure.
+        $this->assertTrue($cache->purge());
+        // It won't be there yet.
+        $this->assertFalse($cache->has('Test'));
+        // Set it now.
+        $this->assertTrue($cache->set('Test', 'Test'));
+        // Check its there.
+        $this->assertTrue($cache->has('Test'));
+        // Double check by trying to get it.
+        $this->assertEquals('Test', $cache->get('Test'));
+
+        // Test with multiple keys.
+        $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
+        $result = $cache->get_many(array('a', 'b', 'c'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('b', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertEquals('A', $result['a']);
+        $this->assertEquals('B', $result['b']);
+        $this->assertEquals('C', $result['c']);
+
+        // Test with multiple keys including missing ones.
+        $result = $cache->get_many(array('a', 'c', 'e'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertArrayHasKey('e', $result);
+        $this->assertEquals('A', $result['a']);
+        $this->assertEquals('C', $result['c']);
+        $this->assertEquals(false, $result['e']);
     }
 
     /**
@@ -520,6 +701,42 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertFalse($cache->get('testkey2'));
     }
 
+    /**
+     * Tests session cache event invalidation
+     */
+    public function test_session_event_invalidation() {
+        $instance = cache_config_phpunittest::instance();
+        $instance->phpunit_add_definition('phpunit/test_session_event_invalidation', array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'test_session_event_invalidation',
+            'invalidationevents' => array(
+                'crazyevent'
+            )
+        ));
+        $cache = cache::make('phpunit', 'test_session_event_invalidation');
+        $this->assertInstanceOf('cache_session', $cache);
+
+        $this->assertTrue($cache->set('testkey1', 'test data 1'));
+        $this->assertEquals('test data 1', $cache->get('testkey1'));
+        $this->assertTrue($cache->set('testkey2', 'test data 2'));
+        $this->assertEquals('test data 2', $cache->get('testkey2'));
+
+        // Test invalidating a single entry.
+        cache_helper::invalidate_by_event('crazyevent', array('testkey1'));
+
+        $this->assertFalse($cache->get('testkey1'));
+        $this->assertEquals('test data 2', $cache->get('testkey2'));
+
+        $this->assertTrue($cache->set('testkey1', 'test data 1'));
+
+        // Test invalidating both entries.
+        cache_helper::invalidate_by_event('crazyevent', array('testkey1', 'testkey2'));
+
+        $this->assertFalse($cache->get('testkey1'));
+        $this->assertFalse($cache->get('testkey2'));
+    }
+
     /**
      * Tests application cache definition invalidation
      */
@@ -556,6 +773,45 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertFalse($cache->get('testkey2'));
     }
 
+    /**
+     * Tests session cache definition invalidation
+     */
+    public function test_session_definition_invalidation() {
+        $instance = cache_config_phpunittest::instance();
+        $instance->phpunit_add_definition('phpunit/test_session_definition_invalidation', array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'test_session_definition_invalidation'
+        ));
+        $cache = cache::make('phpunit', 'test_session_definition_invalidation');
+        $this->assertInstanceOf('cache_session', $cache);
+        $this->assertTrue($cache->set('testkey1', 'test data 1'));
+        $this->assertEquals('test data 1', $cache->get('testkey1'));
+        $this->assertTrue($cache->set('testkey2', 'test data 2'));
+        $this->assertEquals('test data 2', $cache->get('testkey2'));
+
+        cache_helper::invalidate_by_definition('phpunit', 'test_session_definition_invalidation', array(), 'testkey1');
+
+        $this->assertFalse($cache->get('testkey1'));
+        $this->assertEquals('test data 2', $cache->get('testkey2'));
+
+        $this->assertTrue($cache->set('testkey1', 'test data 1'));
+
+        cache_helper::invalidate_by_definition('phpunit', 'test_session_definition_invalidation', array(),
+                array('testkey1'));
+
+        $this->assertFalse($cache->get('testkey1'));
+        $this->assertEquals('test data 2', $cache->get('testkey2'));
+
+        $this->assertTrue($cache->set('testkey1', 'test data 1'));
+
+        cache_helper::invalidate_by_definition('phpunit', 'test_session_definition_invalidation', array(),
+                array('testkey1', 'testkey2'));
+
+        $this->assertFalse($cache->get('testkey1'));
+        $this->assertFalse($cache->get('testkey2'));
+    }
+
     /**
      * Tests application cache event invalidation over a distributed setup.
      */
@@ -865,6 +1121,34 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertFalse($cache->get('test'));
         $this->assertTrue($cache->set('test', 'test'));
         $this->assertEquals('test', $cache->get('test'));
+        $this->assertTrue($cache->delete('test'));
+        $this->assertFalse($cache->get('test'));
+        $this->assertTrue($cache->set('test', 'test'));
+        $this->assertTrue($cache->purge());
+        $this->assertFalse($cache->get('test'));
+
+        // Test the many commands.
+        $this->assertEquals(3, $cache->set_many(array('a' => 'A', 'b' => 'B', 'c' => 'C')));
+        $result = $cache->get_many(array('a', 'b', 'c'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('b', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertEquals('A', $result['a']);
+        $this->assertEquals('B', $result['b']);
+        $this->assertEquals('C', $result['c']);
+        $this->assertEquals($result, $cache->get_many(array('a', 'b', 'c')));
+        $this->assertEquals(2, $cache->delete_many(array('a', 'c')));
+        $result = $cache->get_many(array('a', 'b', 'c'));
+        $this->assertInternalType('array', $result);
+        $this->assertCount(3, $result);
+        $this->assertArrayHasKey('a', $result);
+        $this->assertArrayHasKey('b', $result);
+        $this->assertArrayHasKey('c', $result);
+        $this->assertFalse($result['a']);
+        $this->assertEquals('B', $result['b']);
+        $this->assertFalse($result['c']);
     }
 
     /**
@@ -895,6 +1179,76 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertEquals(false, $cache->get('var'));
     }
 
+    /**
+     * Test switching users with session caches.
+     */
+    public function test_session_cache_switch_user_application_mapping() {
+        $this->resetAfterTest(true);
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_file_store('testfilestore');
+        $instance->phpunit_add_definition('phpunit/testappsession', array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'testappsession'
+        ));
+        $instance->phpunit_add_definition_mapping('phpunit/testappsession', 'testfilestore', 3);
+        $cache = cache::make('phpunit', 'testappsession');
+        $user1 = $this->getDataGenerator()->create_user();
+        $user2 = $this->getDataGenerator()->create_user();
+
+        // Log in as the first user.
+        $this->setUser($user1);
+        $sesskey1 = sesskey();
+
+        // Set a basic value in the cache.
+        $cache->set('var', 1);
+        $this->assertTrue($cache->has('var'));
+        $this->assertEquals(1, $cache->get('var'));
+
+        // Change to the second user.
+        $this->setUser($user2);
+        $sesskey2 = sesskey();
+
+        // Make sure the cache doesn't give us the data for the last user.
+        $this->assertNotEquals($sesskey1, $sesskey2);
+        $this->assertFalse($cache->has('var'));
+        $this->assertEquals(false, $cache->get('var'));
+    }
+
+    /**
+     * Test two session caches being used at once to confirm collisions don't occur.
+     */
+    public function test_dual_session_caches() {
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_definition('phpunit/testsess1', array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'testsess1'
+        ));
+        $instance->phpunit_add_definition('phpunit/testsess2', array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'testsess2'
+        ));
+        $cache1 = cache::make('phpunit', 'testsess1');
+        $cache2 = cache::make('phpunit', 'testsess2');
+
+        $this->assertFalse($cache1->has('test'));
+        $this->assertFalse($cache2->has('test'));
+
+        $this->assertTrue($cache1->set('test', '1'));
+
+        $this->assertTrue($cache1->has('test'));
+        $this->assertFalse($cache2->has('test'));
+
+        $this->assertTrue($cache2->set('test', '2'));
+
+        $this->assertEquals(1, $cache1->get('test'));
+        $this->assertEquals(2, $cache2->get('test'));
+
+        $this->assertTrue($cache1->delete('test'));
+    }
+
     /**
      * Test multiple session caches when switching user.
      */
@@ -925,4 +1279,30 @@ class cache_phpunit_tests extends advanced_testcase {
         $this->assertEquals(false, $cache1->get('var'));
         $this->assertEquals(false, $cache2->get('var'));
     }
+
+    /**
+     * Test application locking.
+     */
+    public function test_application_locking() {
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_definition('phpunit/test_application_locking', array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'test_application_locking',
+            'persistent' => true,
+            'persistentmaxsize' => 1,
+            'requirelockingread' => true,
+            'requirelockingwrite' => true
+        ));
+        $cache = cache::make('phpunit', 'test_application_locking');
+        $this->assertInstanceOf('cache_application', $cache);
+
+        $this->assertTrue($cache->set('a', 'A'));
+        $this->assertTrue($cache->set('b', 'B'));
+        $this->assertTrue($cache->set('c', 'C'));
+        $this->assertEquals('A', $cache->get('a'));
+        $this->assertEquals(array('b' => 'B', 'c' => 'C'), $cache->get_many(array('b', 'c')));
+        $this->assertTrue($cache->delete('a'));
+        $this->assertFalse($cache->has('a'));
+    }
 }
index 42ce92b..b4de9d0 100644 (file)
@@ -35,6 +35,7 @@ defined('MOODLE_INTERNAL') || die();
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 class cache_config_phpunittest extends cache_config_writer {
+
     /**
      * Adds a definition to the stack
      * @param string $area
index 7b28158..c158c97 100644 (file)
@@ -533,6 +533,7 @@ class comment {
             $c->time = userdate($c->timecreated, $c->strftimeformat);
             $c->content = format_text($c->content, $c->format, $formatoptions);
             $c->avatar = $OUTPUT->user_picture($u, array('size'=>18));
+            $c->userid = $u->id;
 
             $candelete = $this->can_delete($c->id);
             if (($USER->id == $u->id) || !empty($candelete)) {
index 7a8d7c9..2fc377d 100644 (file)
@@ -46,12 +46,30 @@ class course_edit_form extends moodleform {
         $mform->setType('returnto', PARAM_ALPHANUM);
         $mform->setConstant('returnto', $returnto);
 
-        // verify permissions to change course category or keep current
+        $mform->addElement('text','fullname', get_string('fullnamecourse'),'maxlength="254" size="50"');
+        $mform->addHelpButton('fullname', 'fullnamecourse');
+        $mform->addRule('fullname', get_string('missingfullname'), 'required', null, 'client');
+        $mform->setType('fullname', PARAM_TEXT);
+        if (!empty($course->id) and !has_capability('moodle/course:changefullname', $coursecontext)) {
+            $mform->hardFreeze('fullname');
+            $mform->setConstant('fullname', $course->fullname);
+        }
+
+        $mform->addElement('text', 'shortname', get_string('shortnamecourse'), 'maxlength="100" size="20"');
+        $mform->addHelpButton('shortname', 'shortnamecourse');
+        $mform->addRule('shortname', get_string('missingshortname'), 'required', null, 'client');
+        $mform->setType('shortname', PARAM_TEXT);
+        if (!empty($course->id) and !has_capability('moodle/course:changeshortname', $coursecontext)) {
+            $mform->hardFreeze('shortname');
+            $mform->setConstant('shortname', $course->shortname);
+        }
+
+        // Verify permissions to change course category or keep current.
         if (empty($course->id)) {
             if (has_capability('moodle/course:create', $categorycontext)) {
                 $displaylist = coursecat::make_categories_list('moodle/course:create');
-                $mform->addElement('select', 'category', get_string('category'), $displaylist);
-                $mform->addHelpButton('category', 'category');
+                $mform->addElement('select', 'category', get_string('coursecategory'), $displaylist);
+                $mform->addHelpButton('category', 'coursecategory');
                 $mform->setDefault('category', $category->id);
             } else {
                 $mform->addElement('hidden', 'category', null);
@@ -65,8 +83,8 @@ class course_edit_form extends moodleform {
                     //always keep current
                     $displaylist[$course->category] = coursecat::get($course->category)->get_formatted_name();
                 }
-                $mform->addElement('select', 'category', get_string('category'), $displaylist);
-                $mform->addHelpButton('category', 'category');
+                $mform->addElement('select', 'category', get_string('coursecategory'), $displaylist);
+                $mform->addHelpButton('category', 'coursecategory');
             } else {
                 //keep current
                 $mform->addElement('hidden', 'category', null);
@@ -75,23 +93,24 @@ class course_edit_form extends moodleform {
             }
         }
 
-        $mform->addElement('text','fullname', get_string('fullnamecourse'),'maxlength="254" size="50"');
-        $mform->addHelpButton('fullname', 'fullnamecourse');
-        $mform->addRule('fullname', get_string('missingfullname'), 'required', null, 'client');
-        $mform->setType('fullname', PARAM_TEXT);
-        if (!empty($course->id) and !has_capability('moodle/course:changefullname', $coursecontext)) {
-            $mform->hardFreeze('fullname');
-            $mform->setConstant('fullname', $course->fullname);
+        $choices = array();
+        $choices['0'] = get_string('hide');
+        $choices['1'] = get_string('show');
+        $mform->addElement('select', 'visible', get_string('visible'), $choices);
+        $mform->addHelpButton('visible', 'visible');
+        $mform->setDefault('visible', $courseconfig->visible);
+        if (!has_capability('moodle/course:visibility', $context)) {
+            $mform->hardFreeze('visible');
+            if (!empty($course->id)) {
+                $mform->setConstant('visible', $course->visible);
+            } else {
+                $mform->setConstant('visible', $courseconfig->visible);
+            }
         }
 
-        $mform->addElement('text', 'shortname', get_string('shortnamecourse'), 'maxlength="100" size="20"');
-        $mform->addHelpButton('shortname', 'shortnamecourse');
-        $mform->addRule('shortname', get_string('missingshortname'), 'required', null, 'client');
-        $mform->setType('shortname', PARAM_TEXT);
-        if (!empty($course->id) and !has_capability('moodle/course:changeshortname', $coursecontext)) {
-            $mform->hardFreeze('shortname');
-            $mform->setConstant('shortname', $course->shortname);
-        }
+        $mform->addElement('date_selector', 'startdate', get_string('startdate'));
+        $mform->addHelpButton('startdate', 'startdate');
+        $mform->setDefault('startdate', time() + 3600 * 24);
 
         $mform->addElement('text','idnumber', get_string('idnumbercourse'),'maxlength="100"  size="10"');
         $mform->addHelpButton('idnumber', 'idnumbercourse');
@@ -101,6 +120,9 @@ class course_edit_form extends moodleform {
             $mform->setConstants('idnumber', $course->idnumber);
         }
 
+        // Description.
+        $mform->addElement('header', 'descriptionhdr', get_string('description'));
+        $mform->setExpanded('descriptionhdr');
 
         $mform->addElement('editor','summary_editor', get_string('coursesummary'), null, $editoroptions);
         $mform->addHelpButton('summary_editor', 'coursesummary');
@@ -114,9 +136,14 @@ class course_edit_form extends moodleform {
         }
 
         if (!empty($course->id) and !has_capability('moodle/course:changesummary', $coursecontext)) {
+            // Remove the description header it does not contain anything any more.
+            $mform->removeElement('descriptionhdr');
             $mform->hardFreeze($summaryfields);
         }
 
+        // Course format.
+        $mform->addElement('header', 'courseformathdr', get_string('type_format', 'plugin'));
+
         $courseformats = get_sorted_course_formats(true);
         $formcourseformats = array();
         foreach ($courseformats as $courseformat) {
@@ -135,13 +162,34 @@ class course_edit_form extends moodleform {
         $mform->addHelpButton('format', 'format');
         $mform->setDefault('format', $courseconfig->format);
 
-        // button to update format-specific options on format change (will be hidden by JavaScript)
+        // Button to update format-specific options on format change (will be hidden by JavaScript).
         $mform->registerNoSubmitButton('updatecourseformat');
         $mform->addElement('submit', 'updatecourseformat', get_string('courseformatudpate'));
 
-        $mform->addElement('date_selector', 'startdate', get_string('startdate'));
-        $mform->addHelpButton('startdate', 'startdate');
-        $mform->setDefault('startdate', time() + 3600 * 24);
+        // Just a placeholder for the course format options.
+        $mform->addElement('hidden', 'addcourseformatoptionshere');
+        $mform->setType('addcourseformatoptionshere', PARAM_BOOL);
+
+        // Appearance.
+        $mform->addElement('header', 'appearancehdr', get_string('appearance'));
+
+        if (!empty($CFG->allowcoursethemes)) {
+            $themeobjects = get_list_of_themes();
+            $themes=array();
+            $themes[''] = get_string('forceno');
+            foreach ($themeobjects as $key=>$theme) {
+                if (empty($theme->hidefromselector)) {
+                    $themes[$key] = get_string('pluginname', 'theme_'.$theme->name);
+                }
+            }
+            $mform->addElement('select', 'theme', get_string('forcetheme'), $themes);
+        }
+
+        $languages=array();
+        $languages[''] = get_string('forceno');
+        $languages += get_string_manager()->get_list_of_translations();
+        $mform->addElement('select', 'lang', get_string('forcelanguage'), $languages);
+        $mform->setDefault('lang', $courseconfig->lang);
 
         $options = range(0, 10);
         $mform->addElement('select', 'newsitems', get_string('newsitemsnumber'), $options);
@@ -156,14 +204,8 @@ class course_edit_form extends moodleform {
         $mform->addHelpButton('showreports', 'showreports');
         $mform->setDefault('showreports', $courseconfig->showreports);
 
-        // Handle non-existing $course->maxbytes on course creation.
-        $coursemaxbytes = !isset($course->maxbytes) ? null : $course->maxbytes;
-
-        // Let's prepare the maxbytes popup.
-        $choices = get_max_upload_sizes($CFG->maxbytes, 0, 0, $coursemaxbytes);
-        $mform->addElement('select', 'maxbytes', get_string('maximumupload'), $choices);
-        $mform->addHelpButton('maxbytes', 'maximumupload');
-        $mform->setDefault('maxbytes', $courseconfig->maxbytes);
+        // Files and uploads.
+        $mform->addElement('header', 'filehdr', get_string('filesanduploads'));
 
         if (!empty($course->legacyfiles) or !empty($CFG->legacyfilesinnewcourses)) {
             if (empty($course->legacyfiles)) {
@@ -181,22 +223,26 @@ class course_edit_form extends moodleform {
             $mform->setDefault('legacyfiles', $courseconfig->legacyfiles);
         }
 
-        if (!empty($CFG->allowcoursethemes)) {
-            $themeobjects = get_list_of_themes();
-            $themes=array();
-            $themes[''] = get_string('forceno');
-            foreach ($themeobjects as $key=>$theme) {
-                if (empty($theme->hidefromselector)) {
-                    $themes[$key] = get_string('pluginname', 'theme_'.$theme->name);
-                }
-            }
-            $mform->addElement('select', 'theme', get_string('forcetheme'), $themes);
-        }
+        // Handle non-existing $course->maxbytes on course creation.
+        $coursemaxbytes = !isset($course->maxbytes) ? null : $course->maxbytes;
 
-//--------------------------------------------------------------------------------
-        // Just a placeholder..
-        $mform->addElement('hidden', 'addcourseformatoptionshere');
-        $mform->setType('addcourseformatoptionshere', PARAM_BOOL);
+        // Let's prepare the maxbytes popup.
+        $choices = get_max_upload_sizes($CFG->maxbytes, 0, 0, $coursemaxbytes);
+        $mform->addElement('select', 'maxbytes', get_string('maximumupload'), $choices);
+        $mform->addHelpButton('maxbytes', 'maximumupload');
+        $mform->setDefault('maxbytes', $courseconfig->maxbytes);
+
+        // Completion tracking.
+        if (completion_info::is_enabled_for_site()) {
+            $mform->addElement('header', 'completionhdr', get_string('completion', 'completion'));
+            $mform->addElement('selectyesno', 'enablecompletion', get_string('enablecompletion', 'completion'));
+            $mform->setDefault('enablecompletion', $courseconfig->enablecompletion);
+            $mform->addHelpButton('enablecompletion', 'enablecompletion', 'completion');
+        } else {
+            $mform->addElement('hidden', 'enablecompletion');
+            $mform->setType('enablecompletion', PARAM_INT);
+            $mform->setDefault('enablecompletion', 0);
+        }
 
 //--------------------------------------------------------------------------------
         enrol_course_edit_form($mform, $course, $context);
@@ -212,10 +258,7 @@ class course_edit_form extends moodleform {
         $mform->addHelpButton('groupmode', 'groupmode', 'group');
         $mform->setDefault('groupmode', $courseconfig->groupmode);
 
-        $choices = array();
-        $choices['0'] = get_string('no');
-        $choices['1'] = get_string('yes');
-        $mform->addElement('select', 'groupmodeforce', get_string('groupmodeforce', 'group'), $choices);
+        $mform->addElement('selectyesno', 'groupmodeforce', get_string('groupmodeforce', 'group'));
         $mform->addHelpButton('groupmodeforce', 'groupmodeforce', 'group');
         $mform->setDefault('groupmodeforce', $courseconfig->groupmodeforce);
 
@@ -225,43 +268,6 @@ class course_edit_form extends moodleform {
         $mform->addElement('select', 'defaultgroupingid', get_string('defaultgrouping', 'group'), $options);
 
 //--------------------------------------------------------------------------------
-        $mform->addElement('header','availability', get_string('availability'));
-
-        $choices = array();
-        $choices['0'] = get_string('courseavailablenot');
-        $choices['1'] = get_string('courseavailable');
-        $mform->addElement('select', 'visible', get_string('availability'), $choices);
-        $mform->addHelpButton('visible', 'availability');
-        $mform->setDefault('visible', $courseconfig->visible);
-        if (!has_capability('moodle/course:visibility', $context)) {
-            $mform->hardFreeze('visible');
-            if (!empty($course->id)) {
-                $mform->setConstant('visible', $course->visible);
-            } else {
-                $mform->setConstant('visible', $courseconfig->visible);
-            }
-        }
-
-//--------------------------------------------------------------------------------
-        $mform->addElement('header','language', get_string('language'));
-
-        $languages=array();
-        $languages[''] = get_string('forceno');
-        $languages += get_string_manager()->get_list_of_translations();
-        $mform->addElement('select', 'lang', get_string('forcelanguage'), $languages);
-        $mform->setDefault('lang', $courseconfig->lang);
-
-//--------------------------------------------------------------------------------
-        if (completion_info::is_enabled_for_site()) {
-            $mform->addElement('header','progress', get_string('progress','completion'));
-            $mform->addElement('select', 'enablecompletion', get_string('completion','completion'),
-                array(0=>get_string('completiondisabled','completion'), 1=>get_string('completionenabled','completion')));
-            $mform->setDefault('enablecompletion', $courseconfig->enablecompletion);
-        } else {
-            $mform->addElement('hidden', 'enablecompletion');
-            $mform->setType('enablecompletion', PARAM_INT);
-            $mform->setDefault('enablecompletion',0);
-        }
 
 /// customizable role names in this course
 //--------------------------------------------------------------------------------
@@ -309,9 +315,6 @@ class course_edit_form extends moodleform {
         $formatvalue = $mform->getElementValue('format');
         if (is_array($formatvalue) && !empty($formatvalue)) {
             $courseformat = course_get_format((object)array('format' => $formatvalue[0]));
-            $newel = $mform->createElement('header', 'courseformatoptions', get_string('courseformatoptions', 'moodle',
-                    $courseformat->get_format_name()));
-            $mform->insertElementBefore($newel, 'addcourseformatoptionshere');
 
             $elements = $courseformat->create_edit_form_elements($mform);
             for ($i = 0; $i < count($elements); $i++) {
index 94ae090..72d62dc 100644 (file)
@@ -1916,7 +1916,6 @@ class core_course_external extends external_api {
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.0
  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
- * @todo MDL-31194 This will be deleted in Moodle 2.5.
  * @see core_course_external
  */
 class moodle_course_external extends external_api {
@@ -1927,7 +1926,6 @@ class moodle_course_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_course_external::get_courses_parameters()
      */
     public static function get_courses_parameters() {
@@ -1941,7 +1939,6 @@ class moodle_course_external extends external_api {
      * @return array
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_course_external::get_courses()
      */
     public static function get_courses($options) {
@@ -1954,7 +1951,6 @@ class moodle_course_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_course_external::get_courses_returns()
      */
     public static function get_courses_returns() {
@@ -1967,7 +1963,6 @@ class moodle_course_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_course_external::create_courses_parameters()
      */
     public static function create_courses_parameters() {
@@ -1981,7 +1976,6 @@ class moodle_course_external extends external_api {
      * @return array courses (id and shortname only)
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_course_external::create_courses()
      */
     public static function create_courses($courses) {
@@ -1994,7 +1988,6 @@ class moodle_course_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_course_external::create_courses_returns()
      */
     public static function create_courses_returns() {
index c837896..dd5652a 100644 (file)
@@ -806,7 +806,8 @@ abstract class moodleform_mod extends moodleform {
         $mform = $this->_form;
         $label = is_null($customlabel) ? get_string('moduleintro') : $customlabel;
 
-        $mform->addElement('editor', 'introeditor', $label, null, array('maxfiles'=>EDITOR_UNLIMITED_FILES, 'noclean'=>true, 'context'=>$this->context));
+        $mform->addElement('editor', 'introeditor', $label, array('rows' => 3), array('maxfiles' => EDITOR_UNLIMITED_FILES,
+            'noclean' => true, 'context' => $this->context, 'collapsed' => true));
         $mform->setType('introeditor', PARAM_RAW); // no XSS prevention here, users must be trusted
         if ($required) {
             $mform->addRule('introeditor', get_string('required'), 'required', null, 'client');
index 3b5e8df..ceb6b10 100644 (file)
@@ -59,6 +59,7 @@ class hub_publish_selector_form extends moodleform {
 
             $hubname = $hub->hubname;
             $mform->addElement('hidden', clean_param($hub->huburl, PARAM_ALPHANUMEXT), $hubname);
+            $mform->setType(clean_param($hub->huburl, PARAM_ALPHANUMEXT), PARAM_ALPHANUMEXT);
             if (empty($hubname)) {
                 $hubname = $hub->huburl;
             }
@@ -69,13 +70,16 @@ class hub_publish_selector_form extends moodleform {
         }
 
         $mform->addElement('hidden', 'id', $this->_customdata['id']);
+        $mform->setType('id', PARAM_INT);
 
         if ($share) {
             $buttonlabel = get_string('shareonhub', 'hub');
             $mform->addElement('hidden', 'share', true);
+            $mform->setType('share', PARAM_BOOL);
         } else {
             $buttonlabel = get_string('advertiseonhub', 'hub');
             $mform->addElement('hidden', 'advertise', true);
+            $mform->setType('advertise', PARAM_BOOL);
         }
 
         $this->add_action_buttons(false, $buttonlabel);
@@ -104,7 +108,9 @@ class course_publication_form extends moodleform {
 
         //hidden parameters
         $mform->addElement('hidden', 'huburl', $huburl);
+        $mform->setType('huburl', PARAM_URL);
         $mform->addElement('hidden', 'hubname', $hubname);
+        $mform->setType('hubname', PARAM_TEXT);
 
         //check on the hub if the course has already been published
         $registrationmanager = new registration_manager();
@@ -200,12 +206,13 @@ class course_publication_form extends moodleform {
         $mform->addHelpButton('name', 'name', 'hub');
 
         $mform->addElement('hidden', 'id', $this->_customdata['id']);
+        $mform->setType('id', PARAM_INT);
 
         if ($share) {
             $buttonlabel = get_string('shareon', 'hub', !empty($hubname) ? $hubname : $huburl);
 
             $mform->addElement('hidden', 'share', $share);
-
+            $mform->setType('share', PARAM_BOOL);
             $mform->addElement('text', 'demourl', get_string('demourl', 'hub'),
                     array('class' => 'metadatatext'));
             $mform->setType('demourl', PARAM_URL);
@@ -220,7 +227,9 @@ class course_publication_form extends moodleform {
                 $buttonlabel = get_string('readvertiseon', 'hub', !empty($hubname) ? $hubname : $huburl);
             }
             $mform->addElement('hidden', 'advertise', $advertise);
+            $mform->setType('advertise', PARAM_BOOL);
             $mform->addElement('hidden', 'courseurl', $CFG->wwwroot . "/course/view.php?id=" . $course->id);
+            $mform->setType('courseurl', PARAM_URL);
             $mform->addElement('static', 'courseurlstring', get_string('courseurl', 'hub'));
             $mform->setDefault('courseurlstring', new moodle_url("/course/view.php?id=" . $course->id));
             $mform->addHelpButton('courseurlstring', 'courseurl', 'hub');
@@ -230,7 +239,7 @@ class course_publication_form extends moodleform {
                 array('class' => 'metadatatext'));
         $mform->setDefault('courseshortname', $defaultshortname);
         $mform->addHelpButton('courseshortname', 'courseshortname', 'hub');
-
+        $mform->setType('courseshortname', PARAM_TEXT);
         $mform->addElement('textarea', 'description', get_string('description'), array('rows' => 10,
             'cols' => 57));
         $mform->addRule('description', $strrequired, 'required', null, 'client');
@@ -250,17 +259,19 @@ class course_publication_form extends moodleform {
         $mform->setDefault('publishername', $defaultpublishername);
         $mform->addRule('publishername', $strrequired, 'required', null, 'client');
         $mform->addHelpButton('publishername', 'publishername', 'hub');
+        $mform->setType('publishername', PARAM_NOTAGS);
 
         $mform->addElement('text', 'publisheremail', get_string('publisheremail', 'hub'),
                 array('class' => 'metadatatext'));
         $mform->setDefault('publisheremail', $defaultpublisheremail);
         $mform->addRule('publisheremail', $strrequired, 'required', null, 'client');
         $mform->addHelpButton('publisheremail', 'publisheremail', 'hub');
+        $mform->setType('publisheremail', PARAM_EMAIL);
 
         $mform->addElement('text', 'creatorname', get_string('creatorname', 'hub'),
                 array('class' => 'metadatatext'));
         $mform->addRule('creatorname', $strrequired, 'required', null, 'client');
-        $mform->setType('creatorname', PARAM_TEXT);
+        $mform->setType('creatorname', PARAM_NOTAGS);
         $mform->setDefault('creatorname', $defaultcreatorname);
         $mform->addHelpButton('creatorname', 'creatorname', 'hub');
 
@@ -268,6 +279,7 @@ class course_publication_form extends moodleform {
                 array('class' => 'metadatatext'));
         $mform->setDefault('contributornames', $defaultcontributornames);
         $mform->addHelpButton('contributornames', 'contributornames', 'hub');
+        $mform->setType('contributornames', PARAM_NOTAGS);
 
         $mform->addElement('text', 'coverage', get_string('tags', 'hub'),
                 array('class' => 'metadatatext'));
@@ -357,6 +369,7 @@ class course_publication_form extends moodleform {
             }
 
             $mform->addElement('hidden', 'existingscreenshotnumber', $screenshotsnumber);
+            $mform->setType('existingscreenshotnumber', PARAM_INT);
         }
 
         $mform->addElement('filemanager', 'screenshots', get_string('addscreenshots', 'hub'), null,
index d401e5c..2e11f5b 100644 (file)
@@ -118,6 +118,7 @@ if (has_capability('moodle/course:publish', context_course::instance($id))) {
         $hubcourseid = optional_param('hubcourseid', 0, PARAM_INT);
         $publicationid = optional_param('publicationid', 0, PARAM_INT);
         $timepublished = optional_param('timepublished', 0, PARAM_INT);
+        $publication = new stdClass();
         $publication->courseshortname = $course->shortname;
         $publication->courseid = $course->id;
         $publication->hubname = $hubname;
index 896facb..f1206bb 100644 (file)
@@ -493,7 +493,7 @@ class core_course_renderer extends plugin_renderer_base {
 
         $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get'));
         $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset'));
-        $output .= html_writer::tag('lavel', $strsearchcourses.': ', array('for' => $inputid));
+        $output .= html_writer::tag('label', $strsearchcourses.': ', array('for' => $inputid));
         $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid,
             'size' => $inputsize, 'name' => 'search', 'value' => s($value)));
         $output .= html_writer::empty_tag('input', array('type' => 'submit',
@@ -674,8 +674,15 @@ class core_course_renderer extends plugin_renderer_base {
             $altname = get_accesshide(' '.$altname);
         }
 
+        // For items which are hidden but available to current user
+        // ($mod->uservisible), we show those as dimmed only if the user has
+        // viewhiddenactivities, so that teachers see 'items which might not
+        // be available to some students' dimmed but students do not see 'item
+        // which is actually available to current student' dimmed.
         $conditionalhidden = $this->is_cm_conditionally_hidden($mod);
-        $accessiblebutdim = !$mod->visible || $conditionalhidden;
+        $accessiblebutdim = (!$mod->visible || $conditionalhidden) &&
+                (!$mod->uservisible || has_capability('moodle/course:viewhiddenactivities',
+                        context_course::instance($mod->course)));
 
         $linkclasses = '';
         $accesstext = '';
@@ -1127,21 +1134,26 @@ class core_course_renderer extends plugin_renderer_base {
         }
 
         // display course overview files
+        $contentimages = $contentfiles = '';
         foreach ($course->get_course_overviewfiles() as $file) {
             $isimage = $file->is_valid_image();
             $url = file_encode_url("$CFG->wwwroot/pluginfile.php",
                     '/'. $file->get_contextid(). '/'. $file->get_component(). '/'.
                     $file->get_filearea(). $file->get_filepath(). $file->get_filename(), !$isimage);
             if ($isimage) {
-                $content .= html_writer::tag('div',
+                $contentimages .= html_writer::tag('div',
                         html_writer::empty_tag('img', array('src' => $url)),
                         array('class' => 'courseimage'));
             } else {
-                $content .= html_writer::tag('div',
-                        html_writer::link($url, $file->get_filename()),
-                        array('class' => 'coursefile'));
+                $image = $this->output->pix_icon(file_file_icon($file, 24), $file->get_filename(), 'moodle');
+                $filename = html_writer::tag('span', $image, array('class' => 'fp-icon')).
+                        html_writer::tag('span', $file->get_filename(), array('class' => 'fp-filename'));
+                $contentfiles .= html_writer::tag('span',
+                        html_writer::link($url, $filename),
+                        array('class' => 'coursefile fp-filename-icon'));
             }
         }
+        $content .= $contentimages. $contentfiles;
 
         // display course contacts. See course_in_list::get_course_contacts()
         if ($course->has_course_contacts()) {
@@ -1360,7 +1372,10 @@ class core_course_renderer extends plugin_renderer_base {
 
         // Courses
         if ($chelper->get_show_courses() > core_course_renderer::COURSECAT_SHOW_COURSES_COUNT) {
-            $courses = $coursecat->get_courses($chelper->get_courses_display_options());
+            $courses = array();
+            if (!$chelper->get_courses_display_option('nodisplay')) {
+                $courses = $coursecat->get_courses($chelper->get_courses_display_options());
+            }
             if ($viewmoreurl = $chelper->get_courses_display_option('viewmoreurl')) {
                 // the option for 'View more' link was specified, display more link (if it is link to category view page, add category id)
                 if ($viewmoreurl->compare(new moodle_url('/course/index.php'), URL_MATCH_BASE)) {
index 6a20279..0b11256 100644 (file)
@@ -709,7 +709,6 @@ class core_role_external extends external_api {
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.0
  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
- * @todo MDL-31194 This will be deleted in Moodle 2.5.
  * @see core_enrol_external
  * @see core_role_external
  */
@@ -722,7 +721,6 @@ class moodle_enrol_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_enrol_external::get_enrolled_users_parameters()
      */
     public static function get_enrolled_users_parameters() {
@@ -746,7 +744,6 @@ class moodle_enrol_external extends external_api {
      * @return array of course participants
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_enrol_external::get_enrolled_users()
      */
     public static function get_enrolled_users($courseid, $withcapability = null, $groupid = null, $onlyactive = false) {
@@ -837,7 +834,6 @@ class moodle_enrol_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_enrol_external::get_enrolled_users_returns()
      */
     public static function get_enrolled_users_returns() {
@@ -863,7 +859,6 @@ class moodle_enrol_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.1
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_enrol_external::get_users_courses_parameters()
      */
     public static function get_users_courses_parameters() {
@@ -878,7 +873,6 @@ class moodle_enrol_external extends external_api {
      * @return array of courses
      * @since Moodle 2.1
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see use core_enrol_external::get_users_courses()
      */
     public static function get_users_courses($userid) {
@@ -891,7 +885,6 @@ class moodle_enrol_external extends external_api {
      * @return external_description
      * @since Moodle 2.1
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_enrol_external::get_users_courses_returns()
      */
     public static function get_users_courses_returns() {
@@ -905,7 +898,6 @@ class moodle_enrol_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_role_external::assign_roles_parameters()
      */
     public static function role_assign_parameters() {
@@ -918,7 +910,6 @@ class moodle_enrol_external extends external_api {
      * @param array $assignments An array of manual role assignment
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_role_external::assign_roles()
      */
     public static function role_assign($assignments) {
@@ -931,7 +922,6 @@ class moodle_enrol_external extends external_api {
      * @return null
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_role_external::assign_roles_returns()
      */
     public static function role_assign_returns() {
@@ -945,7 +935,6 @@ class moodle_enrol_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_role_external::unassign_roles_parameters()
      */
     public static function role_unassign_parameters() {
@@ -958,7 +947,6 @@ class moodle_enrol_external extends external_api {
      * @param array $unassignments An array of unassignment
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_role_external::unassign_roles()
      */
     public static function role_unassign($unassignments) {
@@ -971,7 +959,6 @@ class moodle_enrol_external extends external_api {
      * @return null
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_role_external::unassign_roles_returns()
      */
     public static function role_unassign_returns() {
index 2edb2c8..34de18f 100644 (file)
@@ -165,7 +165,6 @@ class enrol_manual_external extends external_api {
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.0
  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
- * @todo MDL-31194 This will be deleted in Moodle 2.5.
  * @see enrol_manual_external
  */
 class moodle_enrol_manual_external extends external_api {
@@ -176,7 +175,6 @@ class moodle_enrol_manual_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see enrol_manual_external::enrol_users_parameters()
      */
     public static function manual_enrol_users_parameters() {
@@ -190,7 +188,6 @@ class moodle_enrol_manual_external extends external_api {
      * @param array $enrolments  An array of user enrolment
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see enrol_manual_external::enrol_users()
      */
     public static function manual_enrol_users($enrolments) {
@@ -203,7 +200,6 @@ class moodle_enrol_manual_external extends external_api {
      * @return nul
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see enrol_manual_external::enrol_users_returns()
      */
     public static function manual_enrol_users_returns() {
index 4d8e3ae..dd22138 100644 (file)
@@ -340,7 +340,6 @@ class core_files_external extends external_api {
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.0
  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
- * @todo MDL-31194 This will be deleted in Moodle 2.5.
  * @see core_files_external
  */
 class moodle_file_external extends external_api {
@@ -351,7 +350,6 @@ class moodle_file_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_files_external::get_files_parameters()
      */
     public static function get_files_parameters() {
@@ -370,7 +368,6 @@ class moodle_file_external extends external_api {
      * @return array
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_files_external::get_files()
      */
     public static function get_files($contextid, $component, $filearea, $itemid, $filepath, $filename) {
@@ -383,7 +380,6 @@ class moodle_file_external extends external_api {
      * @return external_single_structure
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_files_external::get_files_returns()
      */
     public static function get_files_returns() {
@@ -396,7 +392,6 @@ class moodle_file_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_files_external::upload_parameters()
      */
     public static function upload_parameters() {
@@ -416,7 +411,6 @@ class moodle_file_external extends external_api {
      * @return array
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_files_external::upload()
      */
     public static function upload($contextid, $component, $filearea, $itemid, $filepath, $filename, $filecontent) {
@@ -429,7 +423,6 @@ class moodle_file_external extends external_api {
      * @return external_single_structure
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_files_external::upload_returns()
      */
     public static function upload_returns() {
index d4611f7..06e5162 100644 (file)
@@ -58,6 +58,7 @@ class edit_grade_form extends moodleform {
         if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
             // numeric grade
             $mform->addElement('text', 'finalgrade', get_string('finalgrade', 'grades'));
+            $mform->setType('finalgrade', PARAM_RAW);
             $mform->addHelpButton('finalgrade', 'finalgrade', 'grades');
             $mform->disabledIf('finalgrade', 'overridden', 'notchecked');
 
index 5fe1d31..b1802e2 100644 (file)
@@ -2490,7 +2490,7 @@ abstract class grade_helper {
             return self::$managesetting;
         }
         $context = context_course::instance($courseid);
-        if (has_capability('moodle/course:update', $context)) {
+        if (has_capability('moodle/grade:manage', $context)) {
             self::$managesetting = new grade_plugin_info('coursesettings', new moodle_url('/grade/edit/settings/index.php', array('id'=>$courseid)), get_string('course'));
         } else {
             self::$managesetting = false;
index 48d656f..a316b51 100644 (file)
@@ -1164,7 +1164,6 @@ class core_group_external extends external_api {
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.0
  * @deprecated Moodle 2.2 MDL-29106 - Please do not use this class any more.
- * @todo MDL-31194 This will be deleted in Moodle 2.5.
  * @see core_group_external
  */
 class moodle_group_external extends external_api {
@@ -1175,7 +1174,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::create_groups_parameters()
      */
     public static function create_groups_parameters() {
@@ -1189,7 +1187,6 @@ class moodle_group_external extends external_api {
      * @return array of newly created groups
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see use core_group_external::create_groups()
      */
     public static function create_groups($groups) {
@@ -1202,7 +1199,6 @@ class moodle_group_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::create_groups_returns()
      */
     public static function create_groups_returns() {
@@ -1215,7 +1211,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_groups_parameters()
      */
     public static function get_groups_parameters() {
@@ -1229,7 +1224,6 @@ class moodle_group_external extends external_api {
      * @return array of group objects (id, courseid, name, enrolmentkey)
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_groups()
      */
     public static function get_groups($groupids) {
@@ -1242,7 +1236,6 @@ class moodle_group_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_groups_returns()
      */
     public static function get_groups_returns() {
@@ -1255,7 +1248,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_course_groups_parameters()
      */
     public static function get_course_groups_parameters() {
@@ -1269,7 +1261,6 @@ class moodle_group_external extends external_api {
      * @return array of group objects (id, courseid, name, enrolmentkey)
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_course_groups()
      */
     public static function get_course_groups($courseid) {
@@ -1282,7 +1273,6 @@ class moodle_group_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_course_groups_returns()
      */
     public static function get_course_groups_returns() {
@@ -1295,7 +1285,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::delete_group_members_parameters()
      */
     public static function delete_groups_parameters() {
@@ -1308,7 +1297,6 @@ class moodle_group_external extends external_api {
      * @param array $groupids array of group ids
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::delete_groups()
      */
     public static function delete_groups($groupids) {
@@ -1321,7 +1309,6 @@ class moodle_group_external extends external_api {
      * @return null
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::delete_group_members_returns()
      */
     public static function delete_groups_returns() {
@@ -1335,7 +1322,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_group_members_parameters()
      */
     public static function get_groupmembers_parameters() {
@@ -1349,7 +1335,6 @@ class moodle_group_external extends external_api {
      * @return array with  group id keys containing arrays of user ids
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_group_members()
      */
     public static function get_groupmembers($groupids) {
@@ -1362,7 +1347,6 @@ class moodle_group_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::get_group_members_returns()
      */
     public static function get_groupmembers_returns() {
@@ -1376,7 +1360,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::add_group_members_parameters()
      */
     public static function add_groupmembers_parameters() {
@@ -1389,7 +1372,6 @@ class moodle_group_external extends external_api {
      * @param array $members of arrays with keys userid, groupid
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see use core_group_external::add_group_members()
      */
     public static function add_groupmembers($members) {
@@ -1402,7 +1384,6 @@ class moodle_group_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::add_group_members_returns()
      */
     public static function add_groupmembers_returns() {
@@ -1416,7 +1397,6 @@ class moodle_group_external extends external_api {
      * @return external_function_parameters
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::delete_group_members_parameters()
      */
     public static function delete_groupmembers_parameters() {
@@ -1429,7 +1409,6 @@ class moodle_group_external extends external_api {
      * @param array $members of arrays with keys userid, groupid
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::delete_group_members()
      */
     public static function delete_groupmembers($members) {
@@ -1442,7 +1421,6 @@ class moodle_group_external extends external_api {
      * @return external_description
      * @since Moodle 2.0
      * @deprecated Moodle 2.2 MDL-29106 - Please do not call this function any more.
-     * @todo MDL-31194 This will be deleted in Moodle 2.5.
      * @see core_group_external::delete_group_members_returns()
      */
     public static function delete_groupmembers_returns() {
index 6021c44..abd8c72 100644 (file)
@@ -54,6 +54,7 @@ class groups_import_form extends moodleform {
         $mform->addElement('filepicker', 'userfile', get_string('import'), null, $filepickeroptions);
 
         $mform->addElement('hidden', 'id');
+        $mform->setType('id', PARAM_INT);
 
         $this->add_action_buttons(true, get_string('importgroups', 'core_group'));
 
index e16259e..db41839 100644 (file)
@@ -34,6 +34,7 @@ $string['admindirname'] = 'Каталог администратора';
 $string['availablelangs'] = 'Доступные языковые пакеты';
 $string['chooselanguagehead'] = 'Выберите язык';
 $string['chooselanguagesub'] = 'Сейчас необходимо выбрать язык ТОЛЬКО для сообщений во время установки. Язык сайта и пользовательских интерфейсов можно будет указать далее в процессе установки.';
+$string['clialreadyconfigured'] = 'Файл config.php уже существует. Если Вы хотите установить этот сайт, используйте admin/cli/install_database.php.';
 $string['clialreadyinstalled'] = 'Файл config.php уже существует. Если Вы хотите обновить сайт, то используйте скрипт admin/cli/upgrade.php.';
 $string['cliinstallheader'] = 'Программа установки Moodle {$a} в режиме командной строки';
 $string['databasehost'] = 'Сервер баз данных';
index 6a243d6..ac1d9e2 100644 (file)
@@ -45,8 +45,8 @@ $string['datarootpermission'] = 'Овлашћења над директориј
 $string['dbprefix'] = 'Префикс табеле';
 $string['dirroot'] = 'Moodle директоријум';
 $string['environmenthead'] = 'Проверавање Вашег окружења...';
-$string['environmentsub2'] = 'Свака Ð²ÐµÑ\80зиÑ\98а Moodlea има минимум захтева по питању одговарајуће PHP верзије и неколико обавезних PHP екстензија.
\9fÑ\83на Ð¿Ñ\80овеÑ\80а Ð¾ÐºÑ\80Ñ\83жеÑ\9aа Ñ\81е Ð²Ñ\80Ñ\88и Ð¿Ñ\80е Ñ\81ваке Ð¸Ð½Ñ\81Ñ\82алаÑ\86иÑ\98е Ð¸Ð»Ð¸ Ð°Ð¶Ñ\83Ñ\80иÑ\80аÑ\9aа Ð¿Ð¾Ñ\81Ñ\82оÑ\98еÑ\9bе Ð²ÐµÑ\80зиÑ\98е. Ð£ÐºÐ¾Ð»Ð¸ÐºÐ¾ Ð½Ðµ Ð·Ð½Ð°Ñ\82е ÐºÐ°ÐºÐ¾ Ð´Ð° Ð¸Ð½Ñ\81Ñ\82алиÑ\80аÑ\82е Ð½Ð¾Ð²Ñ\83 Ð²ÐµÑ\80зиÑ\98Ñ\83 Ð¸Ð»Ð¸ Ð¾Ð¼Ð¾Ð³Ñ\83Ñ\9bиÑ\82е PHP ÐµÐºÑ\82ензиÑ\98е ÐºÐ¾Ð½Ñ\82акÑ\82иÑ\80аÑ\98Ñ\82е Ð\92аÑ\88ег Ñ\81еÑ\80веÑ\80 Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñ\81Ñ\82Ñ\80аÑ\82ора.';
+$string['environmentsub2'] = 'Свако Ð¸Ð·Ð´Ð°Ñ\9aе Moodlea има минимум захтева по питању одговарајуће PHP верзије и неколико обавезних PHP екстензија.
\9aомплеÑ\82на Ð¿Ñ\80овеÑ\80а Ð¾ÐºÑ\80Ñ\83жеÑ\9aа Ñ\81е Ð²Ñ\80Ñ\88и Ð¿Ñ\80е Ñ\81ваке Ð¸Ð½Ñ\81Ñ\82алаÑ\86иÑ\98е Ð¸ Ð½Ð°Ð´Ð¾Ð³Ñ\80адÑ\9aе Ð¿Ð¾Ñ\81Ñ\82оÑ\98еÑ\9bе Ð²ÐµÑ\80зиÑ\98е. Ð£ÐºÐ¾Ð»Ð¸ÐºÐ¾ Ð½Ðµ Ð·Ð½Ð°Ñ\82е ÐºÐ°ÐºÐ¾ Ð´Ð° Ð¸Ð½Ñ\81Ñ\82алиÑ\80аÑ\82е Ð½Ð¾Ð²Ñ\83 Ð²ÐµÑ\80зиÑ\98Ñ\83 Ð¸Ð»Ð¸ Ð¾Ð¼Ð¾Ð³Ñ\83Ñ\9bиÑ\82е PHP ÐµÐºÑ\81Ñ\82ензиÑ\98е ÐºÐ¾Ð½Ñ\82акÑ\82иÑ\80аÑ\98Ñ\82е Ñ\81вог Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñ\81Ñ\82Ñ\80аÑ\82оÑ\80а Ñ\81еÑ\80вера.';
 $string['errorsinenvironment'] = 'Провера окружења није прошла!';
 $string['installation'] = 'Инсталација';
 $string['langdownloaderror'] = 'Нажалост, језик "{$a}" се не може преузети. Процес инсталације биће настављен на енглеском језику.';
index 817b854..a7509c3 100644 (file)
@@ -45,8 +45,8 @@ $string['datarootpermission'] = 'Ovlašćenja nad direktorijumom podataka';
 $string['dbprefix'] = 'Prefiks tabele';
 $string['dirroot'] = 'Moodle direktorijum';
 $string['environmenthead'] = 'Proveravanje Vašeg okruženja...';
-$string['environmentsub2'] = 'Svaka verzija Moodlea ima minimum zahteva po pitanju odgovarajuće PHP verѕije i nekoliko obaveznih PHP ekstenzija.
-Puna provera okruženja se vrši pre svake instalacije ili ažuriranja postojeće verzije. Ukoliko ne znate kako da instalirate novu verziju ili omogućite PHP ektenzije kontaktirajte Vašeg server administratora.';
+$string['environmentsub2'] = 'Svako izdanje Moodlea ima minimum zahteva po pitanju odgovarajuće PHP verzije i nekoliko obaveznih PHP ekstenzija.
+Kompletna provera okruženja se vrši pre svake instalacije i nadogradnje postojeće verzije. Ukoliko ne znate kako da instalirate novu verziju ili omogućite PHP ekstenzije kontaktirajte svog administratora servera.';
 $string['errorsinenvironment'] = 'Provera okruženja nije prošla!';
 $string['installation'] = 'Instalacija';
 $string['langdownloaderror'] = 'Nažalost, jezik "{$a}" se ne može preuzeti. Proces instalacije biće nastavljen na engleskom jeziku.';
index 96a8a08..ab04fa3 100644 (file)
@@ -1055,9 +1055,9 @@ $string['updateminmaturity_desc'] = 'Notify about available updates only if the
 $string['updatenotifybuilds'] = 'Notify about new builds';
 $string['updatenotifybuilds_desc'] = 'If enabled, the available update for Moodle code is also reported when a new build for the current version is available. Builds are continuous improvements of a given Moodle version. They are generally released every week. If disabled, the available update will be reported only when there is a higher version of Moodle released. Checks for plugins are not affected by this setting.';
 $string['upgradestart'] = 'Upgrade Moodle database now';
-$string['upgradepluginsfirst'] = 'You have to download and install available updates manually';
+$string['upgradepluginsfirst'] = 'It is recommended to install all available updates first';
 $string['upgradepluginsinfo'] = 'Updating plugins';
-$string['upgradepluginsinfo_help'] = 'There are available updates for some of your plugins. Moodle does not update them automatically yet. You have to download the update and install it at your server manually.';
+$string['upgradepluginsinfo_help'] = 'There are available updates for some of your plugins. You should install them all prior to upgrading Moodle database. If your site does not support automatic updates deployment, you have to download and install new plugin versions at your server manually.';
 $string['upgradepluginsinfo_link'] = 'admin/upgradepluginsinfo';
 $string['upgradeerror'] = 'Unknown error upgrading {$a->plugin} to version {$a->version}, can not continue.';
 $string['upgradeforumread'] = 'A new feature has been added in Moodle 1.5 to track read/unread forum posts.<br />To use this functionality you need to <a href="{$a}">update your tables</a>.';
index 066fb30..00527cd 100644 (file)
@@ -43,6 +43,7 @@ $string['deletecheck'] = 'Delete {$a} block?';
 $string['deleteblock'] = 'Delete {$a} block';
 $string['deleteblockcheck'] = 'Are you sure that you want to delete this block titled {$a}?';
 $string['deleteblockwarning'] = '<p>You are about to delete a block that appears elsewhere.</p><p>Original block location: {$a->location}<br />Display on page types: {$a->pagetype}</p><p>Are you sure you want to continue?</p>';
+$string['dockblock'] = 'Dock {$a} block';
 $string['hideblock'] = 'Hide {$a} block';
 $string['hidedockpanel'] = 'Hide the dock panel';
 $string['hidepanel'] = 'Hide panel';
index 689e6ae..cc49dab 100644 (file)
@@ -135,6 +135,7 @@ $string['supports_dataguarantee'] = 'data guarantee';
 $string['supports_nativettl'] = 'ttl';
 $string['supports_nativelocking'] = 'locking';
 $string['supports_keyawareness'] = 'key awareness';
+$string['supports_searchable'] = 'searching by key';
 $string['tested'] = 'Tested';
 $string['testperformance'] = 'Test performance';
 $string['unsupportedmode'] = 'Unsupported mode';
index 8979fa0..8607b8a 100644 (file)
@@ -72,6 +72,7 @@ $string['configenablecompletion'] = 'When enabled, this lets you turn on complet
 $string['csvdownload'] = 'Download in spreadsheet format (UTF-8 .csv)';
 $string['deletecompletiondata'] = 'Delete completion data';
 $string['enablecompletion'] = 'Enable completion tracking';
+$string['enablecompletion_help'] = 'Once enabled, the completion tracking settings are displayed in the completion tracking page, and in the activity settings.';
 $string['err_noactivities'] = 'Completion information is not enabled for any activity, so none can be displayed. You can enable completion information by editing the settings for an activity.';
 $string['err_nousers'] = 'There are no students on this course or group for whom completion information is displayed. (By default, completion information is displayed only for students, so if there are no students, you will see this error. Administrators can alter this option via the admin screens.)';
 $string['err_system'] = 'An internal error occurred in the completion system. (System administrators can enable debugging information to see more detail.)';
index 66fc80a..d98425b 100644 (file)
@@ -472,6 +472,7 @@ $string['sslonlyaccess'] = 'For security reasons only https connections are allo
 $string['statscatchupmode'] = 'Statistics is currently in catchup mode. So far {$a->daysdone} day(s) have been processed and {$a->dayspending} are pending. Check back soon!';
 $string['statsdisable'] = 'Statistics are not enabled.';
 $string['statsnodata'] = 'There is no available data for that combination of course and time period';
+$string['storedfilecannotcreatefile'] = 'Can not create local file pool file, please verify permissions in dataroot and available disk space.';
 $string['storedfilecannotcreatefiledirs'] = 'Can not create local file pool directories, please verify permissions in dataroot.';
 $string['storedfilecannotread'] = 'Can not read file, either file does not exist or there are permission problems';
 $string['storedfilenotcreated'] = 'Can not create file "{$a->contextid}/{$a->component}/{$a->filearea}/{$a->itemid}/{$a->filepath}/{$a->filename}"';
index 7ad3e7f..66a9f00 100644 (file)
@@ -156,7 +156,6 @@ $string['autosubscribe'] = 'Forum auto-subscribe';
 $string['autosubscribeno'] = 'No: don\'t automatically subscribe me to forums';
 $string['autosubscribeyes'] = 'Yes: when I post, subscribe me to that forum';
 $string['availability'] = 'Availability';
-$string['availability_help'] = 'This setting determines whether the course appears in the list of courses. Apart from teachers and administrators, users are not allowed to enter the course.';
 $string['availablecourses'] = 'Available courses';
 $string['back'] = 'Back';
 $string['backto'] = 'Back to {$a}';
@@ -215,7 +214,6 @@ $string['cancel'] = 'Cancel';
 $string['cancelled'] = 'Cancelled';
 $string['categories'] = 'Course categories';
 $string['category'] = 'Category';
-$string['category_help'] = 'This setting determines the category in which the course will appear in the list of courses.';
 $string['categoryadded'] = 'The category \'{$a}\' was added';
 $string['categorycontents'] = 'Subcategories and courses';
 $string['categorycurrentcontents'] = 'Contents of {$a}';
@@ -293,6 +291,7 @@ $string['courseavailablenot'] = 'This course is not available to students';
 $string['coursebackup'] = 'Course backup';
 $string['coursecategories'] = 'Course categories';
 $string['coursecategory'] = 'Course category';
+$string['coursecategory_help'] = 'This setting determines the category in which the course will appear in the list of courses.';
 $string['coursecategorydeleted'] = 'Deleted course category {$a}';
 $string['coursecompletion'] = 'Course completion';
 $string['coursecompletions'] = 'Course completions';
@@ -322,10 +321,10 @@ $string['coursehelpnewsitemsnumber'] = 'Number of recent items appearing on the
 $string['coursehelpnumberweeks'] = 'Number of sections in the course (applies to certain course formats only).';
 $string['coursehelpshowgrades'] = 'Enable the display of the gradebook. It does not prevent grades from being displayed within the individual activities.';
 $string['coursehidden'] = 'This course is currently unavailable to students';
-$string['courseoverviewfiles'] = 'Course overview files';
-$string['courseoverviewfilesext'] = 'Course overview files extensions';
-$string['courseoverviewfileslimit'] = 'Course overview files limit';
-$string['courseoverviewfiles_help'] = 'Course overview files (usually images) are displayed in the list of courses together with summary';
+$string['courseoverviewfiles'] = 'Course summary files';
+$string['courseoverviewfilesext'] = 'Course summary files extensions';
+$string['courseoverviewfileslimit'] = 'Course summary files limit';
+$string['courseoverviewfiles_help'] = 'Course summary files (usually images) are displayed in the list of courses together with summary';
 $string['courseinfo'] = 'Course info';
 $string['coursemessage'] = 'Message course users';
 $string['coursenotaccessible'] = 'This course does not allow public access';
@@ -677,6 +676,7 @@ $string['fileexists'] = 'There is already a file called {$a}';
 $string['filemissing'] = '{$a} is missing';
 $string['filetoolarge'] = 'is too large to upload';
 $string['files'] = 'Files';
+$string['filesanduploads'] = 'Files and uploads';
 $string['filesfolders'] = 'Files/folders';
 $string['fileuploadwithcontent'] = 'File uploads should not include the content parameter';
 $string['filloutallfields'] = 'Please fill out all fields in this form';
@@ -1798,6 +1798,7 @@ $string['virusfoundsubject'] = '{$a}: Virus found!';
 $string['virusfounduser'] = 'The file you have uploaded, {$a->filename}, has been scanned by a virus checker and found to be infected! Your file upload was NOT successful.';
 $string['virusplaceholder'] = 'This file that has been uploaded was found to contain a virus and has been moved or deleted and the user notified.';
 $string['visible'] = 'Visible';
+$string['visible_help'] = 'This setting determines whether the course appears in the list of courses. Apart from teachers and administrators, users are not allowed to enter the course.';
 $string['visibletostudents'] = 'Visible to {$a}';
 $string['warning'] = 'Warning';
 $string['warningdeleteresource'] = 'Warning: {$a} is referred in a resource. Would you like to update the resource?';
index 69754cd..8977fea 100644 (file)
@@ -59,7 +59,7 @@ $string['numupdatable'] = 'Updates available: {$a}';
 $string['otherplugin'] = '{$a->component}';
 $string['otherpluginversion'] = '{$a->component} ({$a->version})';
 $string['showall'] = 'Reload and show all plugins';
-$string['pluginchecknotice'] = 'This page displays plugins that may require your attention during the upgrade. Highlighted items include new plugins that are about to be installed, updated plugins that are about to be upgraded and any missing plugins. Add-ons are also highlighted. It is recommended that you check whether there are more recent versions of add-ons available and update their source code before continuing with this Moodle upgrade.';
+$string['pluginchecknotice'] = 'This page displays plugins that may require your attention during the upgrade. Highlighted items include new plugins that are about to be installed, updated plugins that are about to be upgraded and any missing plugins. Add-ons are highlighted if there is an available update for them. It is recommended that you check whether there are more recent versions of add-ons available and update their source code before continuing with this Moodle upgrade.';
 $string['plugindisable'] = 'Disable';
 $string['plugindisabled'] = 'Disabled';
 $string['pluginenable'] = 'Enable';
index 443eece..a99a4c6 100644 (file)
@@ -38,7 +38,7 @@ $string['sectionbackup'] = 'Section backups';
 $string['activitybackup'] = 'Activity backup';
 $string['areacategoryintro'] = 'Category introduction';
 $string['areacourseintro'] = 'Course introduction';
-$string['areacourseoverviewfiles'] = 'Course overview files';
+$string['areacourseoverviewfiles'] = 'Course summary files';
 $string['arearoot'] = 'System';
 $string['areauserdraft'] = 'Drafts';
 $string['areauserbackup'] = 'User backup';
index 4d87115..f7ab795 100644 (file)
@@ -1025,25 +1025,29 @@ class block_manager {
 
         $controls = array();
         $actionurl = $this->page->url->out(false, array('sesskey'=> sesskey()));
+        $blocktitle = $block->title;
+        if (empty($blocktitle)) {
+            $blocktitle = $block->arialabel;
+        }
 
         if ($this->page->user_can_edit_blocks()) {
             // Move icon.
             $controls[] = array('url' => $actionurl . '&bui_moveid=' . $block->instance->id,
-                    'icon' => 't/move', 'caption' => get_string('moveblock', 'block', $block->title),
+                    'icon' => 't/move', 'caption' => get_string('moveblock', 'block', $blocktitle),
                     'class' => 'editing_move');
         }
 
         if ($this->page->user_can_edit_blocks() || $block->user_can_edit()) {
             // Edit config icon - always show - needed for positioning UI.
             $controls[] = array('url' => $actionurl . '&bui_editid=' . $block->instance->id,
-                    'icon' => 't/edit', 'caption' => get_string('configureblock', 'block', $block->title),
+                    'icon' => 't/edit', 'caption' => get_string('configureblock', 'block', $blocktitle),
                     'class' => 'editing_edit');
         }
 
         if ($this->user_can_delete_block($block)) {
             // Delete icon.
             $controls[] = array('url' => $actionurl . '&bui_deleteid=' . $block->instance->id,
-                    'icon' => 't/delete', 'caption' => get_string('deleteblock', 'block', $block->title),
+                    'icon' => 't/delete', 'caption' => get_string('deleteblock', 'block', $blocktitle),
                     'class' => 'editing_delete');
         }
 
@@ -1051,11 +1055,11 @@ class block_manager {
             // Show/hide icon.
             if ($block->instance->visible) {
                 $controls[] = array('url' => $actionurl . '&bui_hideid=' . $block->instance->id,
-                        'icon' => 't/hide', 'caption' => get_string('hideblock', 'block', $block->title),
+                        'icon' => 't/hide', 'caption' => get_string('hideblock', 'block', $blocktitle),
                         'class' => 'editing_hide');
             } else {
                 $controls[] = array('url' => $actionurl . '&bui_showid=' . $block->instance->id,
-                        'icon' => 't/show', 'caption' => get_string('showblock', 'block', $block->title),
+                        'icon' => 't/show', 'caption' => get_string('showblock', 'block', $blocktitle),
                         'class' => 'editing_show');
             }
         }
@@ -1070,7 +1074,7 @@ class block_manager {
 
             $controls[] = array('url' => $CFG->wwwroot . '/' . $CFG->admin .
                     '/roles/assign.php?contextid=' . $block->context->id . '&returnurl=' . urlencode($return),
-                    'icon' => 't/assignroles', 'caption' => get_string('assignrolesinblock', 'block', $block->title),
+                    'icon' => 't/assignroles', 'caption' => get_string('assignrolesinblock', 'block', $blocktitle),
                     'class' => 'editing_roles');
         }
 
index 874f2ac..7112c47 100644 (file)
@@ -2085,6 +2085,7 @@ class course_in_list implements IteratorAggregate {
             return array();
         }
         require_once($CFG->libdir. '/filestorage/file_storage.php');
+        require_once($CFG->dirroot. '/course/lib.php');
         $fs = get_file_storage();
         $context = context_course::instance($this->id);
         $files = $fs->get_area_files($context->id, 'course', 'overviewfiles', false, 'filename', false);
index 0f33af8..8762e44 100644 (file)
@@ -453,6 +453,9 @@ function cron_run() {
         mtrace('done.');
     }
 
+    mtrace('Running cache cron routines');
+    cache_helper::cron();
+    mtrace('done.');
 
     // Run automated backups if required - these may take a long time to execute
     require_once($CFG->dirroot.'/backup/util/includes/backup_includes.php');
index 0d4a626..8551999 100644 (file)
  * @param theme_config $theme The theme that the CSS belongs to.
  * @param string $csspath The path to store the CSS at.
  * @param array $cssfiles The CSS files to store.
+ * @param bool $chunk If set to true these files will be chunked to ensure
+ *      that no one file contains more than 4095 selectors.
+ * @param string $chunkurl If the CSS is be chunked then we need to know the URL
+ *      to use for the chunked files.
  */
-function css_store_css(theme_config $theme, $csspath, array $cssfiles) {
+function css_store_css(theme_config $theme, $csspath, array $cssfiles, $chunk = false, $chunkurl = null) {
     global $CFG;
 
     // Check if both the CSS optimiser is enabled and the theme supports it.
@@ -72,6 +76,13 @@ function css_store_css(theme_config $theme, $csspath, array $cssfiles) {
         $css = $theme->post_process(css_minify_css($cssfiles));
     }
 
+    if ($chunk) {
+        // Chunk the CSS if requried.
+        $css = css_chunk_by_selector_count($css, $chunkurl);
+    } else {
+        $css = array($css);
+    }
+
     clearstatcache();
     if (!file_exists(dirname($csspath))) {
         @mkdir(dirname($csspath), $CFG->directorypermissions, true);
@@ -80,19 +91,112 @@ function css_store_css(theme_config $theme, $csspath, array $cssfiles) {
     // Prevent serving of incomplete file from concurrent request,
     // the rename() should be more atomic than fwrite().
     ignore_user_abort(true);
-    if ($fp = fopen($csspath.'.tmp', 'xb')) {
-        fwrite($fp, $css);
-        fclose($fp);
-        rename($csspath.'.tmp', $csspath);
-        @chmod($csspath, $CFG->filepermissions);
-        @unlink($csspath.'.tmp'); // just in case anything fails
+
+    $files = count($css);
+    $count = 0;
+    foreach ($css as $content) {
+        if ($files > 1 && ($count+1) !== $files) {
+            // If there is more than one file and this is not the last file.
+            $filename = preg_replace('#\.css$#', '.'.$count.'.css', $csspath);
+            $count++;
+        } else {
+            $filename = $csspath;
+        }
+        if ($fp = fopen($filename.'.tmp', 'xb')) {
+            fwrite($fp, $content);
+            fclose($fp);
+            rename($filename.'.tmp', $filename);
+            @chmod($filename, $CFG->filepermissions);
+            @unlink($filename.'.tmp'); // just in case anything fails
+        }
     }
+
     ignore_user_abort(false);
     if (connection_aborted()) {
         die;
     }
 }
 
+/**
+ * Takes CSS and chunks it if the number of selectors within it exceeds $maxselectors.
+ *
+ * @param string $css The CSS to chunk.
+ * @param string $importurl The URL to use for import statements.
+ * @param int $maxselectors The number of selectors to limit a chunk to.
+ * @param int $buffer The buffer size to use when chunking. You shouldn't need to reduce this
+ *      unless you are lowering the maximum selectors.
+ * @return array An array of CSS chunks.
+ */
+function css_chunk_by_selector_count($css, $importurl, $maxselectors = 4095, $buffer = 50) {
+    // Check if we need to chunk this CSS file.
+    $count = substr_count($css, ',') + substr_count($css, '{');
+    if ($count < $maxselectors) {
+        // The number of selectors is less then the max - we're fine.
+        return array($css);
+    }
+
+    // Chunk time ?!
+    // Split the CSS by array, making sure to save the delimiter in the process.
+    $parts = preg_split('#([,\}])#', $css, null, PREG_SPLIT_DELIM_CAPTURE + PREG_SPLIT_NO_EMPTY);
+    // We need to chunk the array. Each delimiter is stored separately so we multiple by 2.
+    // We also subtract 100 to give us a small buffer just in case.
+    $parts = array_chunk($parts, $maxselectors * 2 - $buffer * 2);
+    $css = array();
+    $partcount = count($parts);
+    foreach ($parts as $key => $chunk) {
+        if (end($chunk) === ',') {
+       &