Merge branch 'MDL-19171' of https://github.com/bostelm/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 13 Aug 2013 01:57:52 +0000 (09:57 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 13 Aug 2013 01:57:52 +0000 (09:57 +0800)
565 files changed:
admin/blocks.php
admin/cli/install.php
admin/environment.xml
admin/localplugins.php
admin/mnet/access_control.php
admin/purgecaches.php
admin/registration/forms.php
admin/reports.php
admin/roles/allow.php
admin/roles/assign.php
admin/roles/classes/define_role_table_advanced.php
admin/roles/define.php
admin/roles/manage.php
admin/roles/override.php
admin/settings/appearance.php
admin/settings/server.php
admin/tool/behat/tests/behat/data_generators.feature
admin/tool/uploadcourse/classes/course.php
admin/tool/uploadcourse/classes/helper.php
admin/tool/uploadcourse/classes/step1_form.php
admin/tool/uploadcourse/cli/uploadcourse.php
admin/tool/uploadcourse/lang/en/tool_uploadcourse.php
admin/tool/uploadcourse/tests/course_test.php
admin/tool/uploadcourse/tests/helper_test.php
admin/tool/uploaduser/locallib.php
admin/tool/uploaduser/user_form.php
admin/tool/xmldb/actions/check_oracle_semantics/check_oracle_semantics.class.php
admin/tools.php
admin/webservice/forms.php
auth/cas/auth.php
auth/db/auth.php
auth/email/auth.php
auth/ldap/auth.php
auth/manual/auth.php
auth/nologin/auth.php
auth/none/auth.php
auth/tests/auth_test.php [deleted file]
auth/upgrade.txt
backup/backup.php
backup/controller/tests/controller_test.php
backup/converter/moodle1/handlerlib.php
backup/converter/moodle1/lib.php
backup/converter/moodle1/tests/moodle1_converter_test.php [moved from backup/converter/moodle1/tests/lib_test.php with 99% similarity]
backup/moodle2/restore_stepslib.php
backup/restore.php
backup/upgrade.txt
backup/util/dbops/backup_controller_dbops.class.php
backup/util/dbops/backup_plan_dbops.class.php
backup/util/dbops/restore_dbops.class.php
backup/util/dbops/tests/backup_dbops_test.php
backup/util/helper/backup_cron_helper.class.php
backup/util/ui/tests/behat/duplicate_activities.feature
badges/lib/backpacklib.php
badges/tests/badgeslib_test.php
blocks/activity_modules/block_activity_modules.php
blocks/comments/tests/behat/behat_block_comments.php
blocks/community/forms.php
blocks/completionstatus/details.php
blocks/course_overview/db/access.php
blocks/course_overview/lang/en/block_course_overview.php
blocks/course_overview/locallib.php
blocks/course_overview/version.php
blocks/navigation/block_navigation.php
blocks/navigation/tests/behat/view_my_courses.feature
blocks/rss_client/block_rss_client.php
blocks/site_main_menu/block_site_main_menu.php
blocks/social_activities/block_social_activities.php
blog/lib.php
blog/locallib.php
blog/tests/behat/comment.feature
blog/tests/bloglib_test.php
cache/locallib.php
cache/stores/file/lib.php
cache/testperformance.php
cache/tests/administration_helper_test.php [new file with mode: 0644]
cache/tests/cache_test.php
cache/tests/config_writer_test.php [moved from cache/tests/locallib_test.php with 57% similarity]
calendar/tests/externallib_test.php
calendar/tests/ical_test.php [moved from calendar/tests/calendarical_test.php with 100% similarity]
cohort/tests/cohortlib_test.php
cohort/tests/externallib_test.php
comment/comment.js
config-dist.php
course/dndupload.js
course/dnduploadlib.php
course/format/upgrade.txt
course/lib.php
course/manage.php
course/publish/forms.php
course/renderer.php
course/tests/behat/activities_indentation.feature
course/tests/behat/behat_course.php
course/tests/behat/course_controls.feature
course/tests/courselib_test.php
course/tests/courserequest_test.php
course/tests/externallib_test.php
course/yui/dragdrop/dragdrop.js
course/yui/toolboxes/toolboxes.js
enrol/database/lib.php
enrol/externallib.php
enrol/flatfile/lib.php
enrol/flatfile/settings.php
enrol/flatfile/tests/flatfile_test.php
enrol/guest/locallib.php
enrol/ldap/lib.php
enrol/ldap/settingslib.php
enrol/locallib.php
enrol/meta/locallib.php
enrol/meta/settings.php
enrol/meta/tests/plugin_test.php [new file with mode: 0644]
enrol/paypal/ipn.php
enrol/self/db/services.php [new file with mode: 0644]
enrol/self/externallib.php [new file with mode: 0644]
enrol/self/lib.php
enrol/self/locallib.php
enrol/self/tests/externallib_test.php [new file with mode: 0644]
enrol/self/version.php
enrol/tests/enrollib_test.php
enrol/tests/externallib_test.php
enrol/tests/role_external_test.php [moved from enrol/tests/externallib_role_test.php with 98% similarity]
files/externallib.php
files/renderer.php
files/tests/externallib_test.php
grade/edit/scale/edit_form.php
grade/edit/tree/action.php
grade/edit/tree/lib.php
grade/export/grade_export_form.php
grade/export/key_form.php
grade/grading/tests/grading_manager_test.php [moved from grade/grading/tests/lib_test.php with 98% similarity]
grade/import/grade_import_form.php
grade/import/key_form.php
grade/lib.php
grade/report/user/lang/en/gradereport_user.php
grade/report/user/lib.php
grade/report/user/styles.css
grade/tests/edittreelib_test.php [moved from grade/tests/edittree_test.php with 96% similarity]
grade/tests/externallib_test.php
grade/tests/querylib_test.php
grade/tests/report_graderlib_test.php [moved from grade/tests/reportgrader_test.php with 98% similarity]
grade/tests/reportlib_test.php
grade/tests/reportuserlib_test.php [moved from grade/tests/reportuser_test.php with 99% similarity]
group/group_form.php
group/grouping_form.php
group/tests/externallib_test.php
index.php
install.php
install/lang/ca/error.php
install/lang/de/error.php
install/lang/fa/admin.php
install/lang/fa/moodle.php
install/lang/hu/error.php
install/lang/it/install.php
install/lang/pl/install.php
install/lang/ru/error.php
install/lang/ru/install.php
iplookup/lib.php
iplookup/tests/geoip_test.php
iplookup/tests/geoplugin_test.php
lang/en/admin.php
lang/en/auth.php
lang/en/blog.php
lang/en/cache.php
lang/en/error.php
lang/en/message.php
lang/en/moodle.php
lang/en/question.php
lang/en/role.php
lang/en/webservice.php
lib/accesslib.php
lib/adminlib.php
lib/ajax/tests/ajaxlib_test.php
lib/authlib.php
lib/behat/lib.php
lib/bennu/iCalendar_rfc2445.php
lib/bennu/readme_moodle.txt
lib/blocklib.php
lib/classes/collator.php
lib/classes/component.php
lib/classes/event/base.php
lib/classes/event/blog_entry_created.php [new file with mode: 0644]
lib/classes/event/blog_entry_deleted.php [new file with mode: 0644]
lib/classes/event/manager.php
lib/classes/event/role_allow_assign_updated.php [new file with mode: 0644]
lib/classes/event/role_allow_override_updated.php [new file with mode: 0644]
lib/classes/event/role_allow_switch_updated.php [new file with mode: 0644]
lib/classes/event/role_assigned.php
lib/classes/event/role_capabilities_updated.php [new file with mode: 0644]
lib/classes/event/role_deleted.php [new file with mode: 0644]
lib/classes/event/role_unassigned.php
lib/classes/event/user_loggedin.php [moved from auth/classes/event/user_loggedin.php with 87% similarity]
lib/classes/minify.php [new file with mode: 0644]
lib/classes/string_manager.php [new file with mode: 0644]
lib/classes/string_manager_install.php [new file with mode: 0644]
lib/classes/string_manager_standard.php [new file with mode: 0644]
lib/conditionlib.php
lib/coursecatlib.php
lib/csslib.php
lib/csvlib.class.php
lib/datalib.php
lib/db/caches.php
lib/db/install.xml
lib/db/services.php
lib/db/upgrade.php
lib/db/upgradelib.php
lib/ddl/mssql_sql_generator.php
lib/ddl/tests/ddl_test.php
lib/deprecatedlib.php
lib/dml/mssql_native_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/dml/tests/dml_test.php
lib/editor/tinymce/adminlib.php
lib/editor/tinymce/plugins/loader.php
lib/editor/tinymce/plugins/managefiles/tinymce/editor_plugin.js
lib/editor/tinymce/plugins/pdw/readme_moodle.txt
lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin.js
lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin_src.js [deleted file]
lib/editor/tinymce/plugins/spellchecker/classes/GoogleSpell.php
lib/eventslib.php
lib/excellib.class.php
lib/external/tests/external_test.php [moved from lib/external/tests/externallib_test.php with 100% similarity]
lib/filebrowser/file_info.php
lib/filebrowser/file_info_context_course.php
lib/filebrowser/file_info_stored.php
lib/filestorage/file_archive.php
lib/filestorage/file_storage.php
lib/filestorage/tests/file_storage_test.php
lib/filestorage/tests/zip_packer_test.php
lib/filestorage/zip_archive.php
lib/filterlib.php
lib/form/filemanager.js
lib/formslib.php
lib/grade/grade_category.php
lib/grade/grade_item.php
lib/grade/grade_object.php
lib/grade/tests/fixtures/lib.php
lib/grade/tests/grade_category_test.php
lib/grade/tests/grade_grade_test.php
lib/grade/tests/grade_item_test.php
lib/grade/tests/grade_outcome_test.php
lib/grade/tests/grade_scale_test.php
lib/gradelib.php
lib/graphlib.php
lib/grouplib.php
lib/html2text.php
lib/html2text_readme.txt
lib/javascript.php
lib/jslib.php
lib/medialib.php
lib/minify/config.php
lib/minify/lib/CSSmin.php [new file with mode: 0644]
lib/minify/lib/DooDigestAuth.php [new file with mode: 0644]
lib/minify/lib/Minify.php
lib/minify/lib/Minify/Build.php
lib/minify/lib/Minify/CSS.php
lib/minify/lib/Minify/Cache/File.php
lib/minify/lib/Minify/Cache/XCache.php [new file with mode: 0644]
lib/minify/lib/Minify/ClosureCompiler.php [new file with mode: 0644]
lib/minify/lib/Minify/Controller/Base.php
lib/minify/lib/Minify/Controller/Files.php
lib/minify/lib/Minify/Controller/Groups.php
lib/minify/lib/Minify/Controller/MinApp.php
lib/minify/lib/Minify/Controller/Page.php
lib/minify/lib/Minify/Controller/Version1.php
lib/minify/lib/Minify/HTML.php
lib/minify/lib/Minify/HTML/Helper.php
lib/minify/lib/Minify/JS/ClosureCompiler.php
lib/minify/lib/Minify/Lines.php
lib/minify/lib/Minify/Loader.php [new file with mode: 0644]
lib/minify/lib/Minify/YUICompressor.php
lib/minify/lib/MrClay/Cli.php
lib/minify/lib/MrClay/Cli/Arg.php
lib/minify/readme_moodle.txt
lib/minify/utils.php
lib/modinfolib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/phpmailer/moodle_phpmailer.php
lib/phpunit/classes/advanced_testcase.php
lib/phpunit/classes/autoloader.php
lib/phpunit/classes/event_mock.php [new file with mode: 0644]
lib/phpunit/classes/util.php
lib/phpunit/lib.php
lib/portfoliolib.php
lib/questionlib.php
lib/setuplib.php
lib/simplepie/moodle_simplepie.php
lib/tablelib.php
lib/testing/classes/util.php
lib/tests/accesslib_test.php
lib/tests/admintree_test.php
lib/tests/authlib_test.php
lib/tests/behat/behat_data_generators.php
lib/tests/behat/behat_hooks.php
lib/tests/blocklib_test.php
lib/tests/code_test.php
lib/tests/collator_test.php
lib/tests/completionlib_advanced_test.php [deleted file]
lib/tests/completionlib_test.php
lib/tests/component_test.php
lib/tests/componentlib_test.php
lib/tests/conditionlib_test.php
lib/tests/configonlylib_test.php
lib/tests/coursecatlib_test.php
lib/tests/csslib_test.php
lib/tests/csvclass_test.php
lib/tests/datalib_test.php
lib/tests/environment_test.php
lib/tests/event_test.php
lib/tests/eventslib_test.php
lib/tests/externallib_test.php
lib/tests/filelib_test.php
lib/tests/filterlib_test.php [moved from lib/tests/filter_test.php with 74% similarity]
lib/tests/fixtures/event_fixtures.php
lib/tests/formslib_test.php
lib/tests/gradelib_test.php
lib/tests/grouplib_test.php
lib/tests/html2text_test.php
lib/tests/html_writer_test.php [moved from lib/tests/htmlwriter_test.php with 69% similarity]
lib/tests/htmlpurifier_test.php
lib/tests/markdown_test.php
lib/tests/mathslib_test.php
lib/tests/medialib_test.php
lib/tests/messagelib_test.php
lib/tests/minify_test.php [new file with mode: 0644]
lib/tests/modinfolib_test.php
lib/tests/moodle_page_test.php [moved from lib/tests/pagelib_test.php with 71% similarity]
lib/tests/moodlelib_test.php
lib/tests/navigationlib_test.php
lib/tests/outputcomponents_test.php
lib/tests/outputrequirementslib_test.php
lib/tests/pluginlib_test.php
lib/tests/questionlib_test.php
lib/tests/rsslib_test.php
lib/tests/setuplib_test.php
lib/tests/statslib_test.php
lib/tests/string_manager_standard_test.php [moved from lib/tests/string_test.php with 92% similarity]
lib/tests/text_test.php
lib/tests/theme_config_test.php [moved from lib/tests/outputlib_test.php with 53% similarity]
lib/tests/upgradelib_test.php
lib/tests/weblib_test.php
lib/tests/xhtml_container_stack_test.php [new file with mode: 0644]
lib/thirdpartylibs.xml
lib/tokeniserlib.php
lib/upgrade.txt
lib/upgradelib.php
lib/weblib.php
lib/xhprof/xhprof_moodle.php
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu.js [new file with mode: 0644]
lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-debug.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-min.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception.js [new file with mode: 0644]
lib/yui/build/moodle-core-notification/moodle-core-notification-debug.js
lib/yui/build/moodle-core-notification/moodle-core-notification-min.js
lib/yui/build/moodle-core-notification/moodle-core-notification.js
lib/yui/dragdrop/dragdrop.js
lib/yui/src/actionmenu/build.json [new file with mode: 0644]
lib/yui/src/actionmenu/js/actionmenu.js [new file with mode: 0644]
lib/yui/src/actionmenu/meta/actionmenu.json [new file with mode: 0644]
lib/yui/src/blocks/js/blocks.js
lib/yui/src/notification/build.json
lib/yui/src/notification/js/ajaxexception.js [new file with mode: 0644]
lib/yui/src/notification/js/alert.js [new file with mode: 0644]
lib/yui/src/notification/js/confirm.js [new file with mode: 0644]
lib/yui/src/notification/js/dialogue.js [new file with mode: 0644]
lib/yui/src/notification/js/exception.js [new file with mode: 0644]
lib/yui/src/notification/js/notification.js
lib/yui/src/notification/js/shared.js [new file with mode: 0644]
lib/yui/src/notification/meta/notification.json
login/forgot_password.php
login/index.php
login/signup_form.php
login/token.php
message/bell.mp3 [new file with mode: 0644]
message/bell.ogg [new file with mode: 0644]
message/edit.php
message/lib.php
message/renderer.php
message/tests/externallib_test.php
mod/assign/adminlib.php
mod/assign/db/services.php
mod/assign/externallib.php
mod/assign/feedback/file/importziplib.php
mod/assign/lang/en/assign.php
mod/assign/locallib.php
mod/assign/tests/externallib_test.php
mod/assign/version.php
mod/assign/yui/history/history.js
mod/assignment/lib.php
mod/book/db/upgradelib.php
mod/book/tool/importhtml/locallib.php
mod/chat/gui_basic/index.php
mod/chat/lib.php
mod/choice/styles.css
mod/data/field/file/field.class.php
mod/data/field/picture/field.class.php
mod/data/import_form.php
mod/data/lang/en/data.php
mod/data/lib.php
mod/data/module.js [new file with mode: 0644]
mod/data/templates.php
mod/data/tests/lib_test.php [new file with mode: 0644]
mod/data/view.php
mod/feedback/import.php
mod/feedback/import_form.php
mod/feedback/lib.php
mod/feedback/styles.css
mod/forum/backup/moodle2/restore_forum_stepslib.php
mod/forum/lib.php
mod/forum/mod_form.php
mod/glossary/edit_form.php
mod/glossary/editcategories.php
mod/glossary/exportentry.php
mod/glossary/import.php
mod/glossary/lib.php
mod/glossary/print.php
mod/glossary/sql.php
mod/glossary/view.php
mod/label/lib.php
mod/lesson/essay.php
mod/lesson/format.php
mod/lesson/locallib.php
mod/lesson/pagetypes/endofbranch.php
mod/lesson/pagetypes/endofcluster.php
mod/lesson/pagetypes/essay.php
mod/lesson/pagetypes/matching.php
mod/lesson/pagetypes/truefalse.php
mod/lti/db/access.php
mod/lti/lang/en/lti.php
mod/lti/lib.php
mod/lti/locallib.php
mod/lti/mod_form.php
mod/lti/service.php
mod/page/lib.php
mod/quiz/editlib.php
mod/quiz/lib.php
mod/quiz/renderer.php
mod/quiz/report/statistics/lib.php
mod/quiz/report/statistics/report.php
mod/quiz/report/statistics/tests/fixtures/qstats00.csv [new file with mode: 0644]
mod/quiz/report/statistics/tests/fixtures/questions00.csv [new file with mode: 0644]
mod/quiz/report/statistics/tests/fixtures/results00.csv [new file with mode: 0644]
mod/quiz/report/statistics/tests/fixtures/steps00.csv [new file with mode: 0644]
mod/quiz/report/statistics/tests/stats_from_steps_walkthrough_test.php [new file with mode: 0644]
mod/quiz/settings.php
mod/quiz/styles.css
mod/quiz/tests/attempt_walkthrough_from_csv_test.php
mod/resource/lib.php
mod/resource/tests/generator/lib.php [new file with mode: 0644]
mod/resource/tests/generator_test.php [new file with mode: 0644]
mod/scorm/datamodels/aicc.js.php
mod/scorm/datamodels/scorm_12.js.php
mod/scorm/datamodels/scorm_13.js.php
mod/survey/download.php
mod/upgrade.txt
mod/url/lib.php
mod/wiki/locallib.php
mod/wiki/pagelib.php
mod/workshop/locallib.php
notes/tests/externallib_test.php
phpunit.xml.dist
question/behaviour/behaviourbase.php
question/behaviour/deferredcbm/tests/walkthrough_test.php
question/behaviour/deferredfeedback/tests/walkthrough_test.php
question/editlib.php
question/engine/bank.php
question/engine/datalib.php
question/engine/lib.php
question/engine/questionattempt.php
question/engine/tests/helpers.php
question/engine/tests/questionattempt_test.php
question/engine/upgrade/upgradelib.php
question/format.php
question/format/aiken/format.php
question/format/aiken/lang/en/qformat_aiken.php
question/format/aiken/version.php
question/format/blackboard_six/format.php
question/format/blackboard_six/formatqti.php
question/format/examview/format.php
question/format/gift/format.php
question/format/gift/lang/en/qformat_gift.php
question/format/gift/tests/giftformat_test.php
question/format/gift/version.php
question/format/learnwise/format.php
question/format/learnwise/lang/en/qformat_learnwise.php
question/format/learnwise/version.php
question/format/missingword/format.php
question/format/missingword/lang/en/qformat_missingword.php
question/format/missingword/version.php
question/format/multianswer/lang/en/qformat_multianswer.php
question/format/multianswer/version.php
question/format/upgrade.txt
question/format/webct/TODO.txt [deleted file]
question/format/webct/format.php
question/format/webct/lang/en/qformat_webct.php
question/format/webct/tests/fixtures/sample_webct.txt [new file with mode: 0644]
question/format/webct/tests/webctformat_test.php [new file with mode: 0644]
question/format/webct/version.php
question/format/xhtml/format.php
question/format/xhtml/lang/en/qformat_xhtml.php
question/format/xhtml/lib.php [new file with mode: 0644]
question/format/xhtml/version.php
question/format/xhtml/xhtml.css
question/format/xml/format.php
question/format/xml/lang/en/qformat_xml.php
question/format/xml/tests/xmlformat_test.php
question/format/xml/version.php
question/type/essay/question.php
question/type/multianswer/renderer.php
question/type/multichoice/questiontype.php
question/type/questionbase.php
question/upgrade.txt [new file with mode: 0644]
report/completion/index.php
report/log/locallib.php
report/progress/index.php
repository/filepicker.js
repository/filesystem/lib.php
repository/googledocs/lib.php
repository/lib.php
repository/local/lib.php
repository/s3/README_MOODLE.txt
repository/s3/S3.php
repository/tests/generator_test.php
repository/tests/repositorylib_test.php [moved from repository/tests/repository_test.php with 99% similarity]
tag/coursetagslib.php
tag/lib.php
tag/locallib.php
theme/base/style/core.css
theme/base/style/course.css
theme/bootstrapbase/less/moodle/blocks.less
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/course.less
theme/bootstrapbase/less/moodle/forms.less
theme/bootstrapbase/style/moodle.css
theme/javascript.php
theme/upgrade.txt
user/editadvanced_form.php
user/externallib.php
user/filters/date.php
user/lib.php
user/tests/externallib_test.php
version.php
webservice/externallib.php
webservice/tests/externallib_test.php
webservice/upgrade.txt [new file with mode: 0644]
webservice/upload.php

index 2ad0a0e..6a2d31e 100644 (file)
             $blocknames[$blockid] = $blockname;
         }
     }
-    collatorlib::asort($blocknames);
+    core_collator::asort($blocknames);
 
     foreach ($blocknames as $blockid=>$strblockname) {
         $block = $blocks[$blockid];
index e8cffe0..21617cf 100644 (file)
@@ -172,6 +172,9 @@ ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include
 
 require_once($CFG->libdir.'/classes/component.php');
 require_once($CFG->libdir.'/classes/text.php');
+require_once($CFG->libdir.'/classes/string_manager.php');
+require_once($CFG->libdir.'/classes/string_manager_install.php');
+require_once($CFG->libdir.'/classes/string_manager_standard.php');
 require_once($CFG->libdir.'/installlib.php');
 require_once($CFG->libdir.'/clilib.php');
 require_once($CFG->libdir.'/setuplib.php');
@@ -309,6 +312,8 @@ if ($interactive) {
     }
 }
 $CFG->directorypermissions = $chmod;
+$CFG->filepermissions      = ($CFG->directorypermissions & 0666);
+$CFG->umaskpermissions     = (($CFG->directorypermissions & 0777) ^ 0777);
 
 //We need wwwroot before we test dataroot
 $wwwroot = clean_param($options['wwwroot'], PARAM_URL);
index 5fac54c..1e937cd 100644 (file)
           <ON_CHECK message="settingfileuploads" />
         </FEEDBACK>
       </PHP_SETTING>
+      <PHP_SETTING name="opcache.enable" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="opcacherecommended" />
+        </FEEDBACK>
+      </PHP_SETTING>
     </PHP_SETTINGS>
   </MOODLE>
 </COMPATIBILITY_MATRIX>
index 145f65a..be09151 100644 (file)
@@ -55,7 +55,7 @@ foreach (core_component::get_plugin_list('local') as $plugin => $plugindir) {
     }
     $plugins[$plugin] = $strpluginname;
 }
-collatorlib::asort($plugins);
+core_collator::asort($plugins);
 
 foreach ($plugins as $plugin => $name) {
     $uninstall = '';
index 1c0470e..79c744c 100644 (file)
@@ -103,7 +103,7 @@ if ($form = data_submitted() and confirm_sesskey()) {
         $usernames = explode(',', $form->username);
 
         foreach ($usernames as $username) {
-            $username = trim(textlib::strtolower($username));
+            $username = trim(core_text::strtolower($username));
             if (!empty($username)) {
                 if (mnet_update_sso_access_control($username, $form->mnet_host_id, $form->accessctrl)) {
                     if ($form->accessctrl == 'allow') {
index 006bb0d..c2247dc 100644 (file)
@@ -27,37 +27,37 @@ require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 
 $confirm = optional_param('confirm', 0, PARAM_BOOL);
+$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
 
-admin_externalpage_setup('purgecaches');
-
-require_login();
-require_capability('moodle/site:config', context_system::instance());
-
-if ($confirm) {
-    require_sesskey();
+// If we have got here as a confirmed aciton, do it.
+if ($confirm && isloggedin() && confirm_sesskey()) {
+    require_capability('moodle/site:config', context_system::instance());
 
-    // Valid request. Purge, and redisplay the form so it is easy to purge again
-    // in the near future.
+    // Valid request. Purge, and redirect the user back to where they came from.
     purge_all_caches();
-    redirect(new moodle_url('/admin/purgecaches.php'), get_string('purgecachesfinished', 'admin'));
-
-} else {
-    // Show a confirm form.
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('purgecaches', 'admin'));
-
-    $url = new moodle_url('/admin/purgecaches.php', array('sesskey'=>sesskey(), 'confirm'=>1));
-    $button = new single_button($url, get_string('purgecaches','admin'), 'post');
-
-    // Cancel button takes them back to the page the were on, if possible,
-    // otherwise to the site home page.
-    $return = new moodle_url('/');
-    if (isset($_SERVER['HTTP_REFERER']) and !empty($_SERVER['HTTP_REFERER'])) {
-        if ($_SERVER['HTTP_REFERER'] !== "$CFG->wwwroot/$CFG->admin/purgecaches.php") {
-            $return = $_SERVER['HTTP_REFERER'];
-        }
+
+    if ($returnurl) {
+        $returnurl = $CFG->wwwroot . $returnurl;
+    } else {
+        $returnurl = new moodle_url('/admin/purgecaches.php');
     }
+    redirect($returnurl, get_string('purgecachesfinished', 'admin'));
+}
 
-    echo $OUTPUT->confirm(get_string('purgecachesconfirm', 'admin'), $button, $return);
-    echo $OUTPUT->footer();
+// Otherwise, show a button to actually purge the caches.
+admin_externalpage_setup('purgecaches');
+
+$actionurl = new moodle_url('/admin/purgecaches.php', array('sesskey'=>sesskey(), 'confirm'=>1));
+if ($returnurl) {
+    $actionurl->param('returnurl', $returnurl);
 }
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('purgecaches', 'admin'));
+
+echo $OUTPUT->box_start('generalbox', 'notice');
+echo html_writer::tag('p', get_string('purgecachesconfirm', 'admin'));
+echo $OUTPUT->single_button($actionurl, get_string('purgecaches', 'admin'), 'post');
+echo $OUTPUT->box_end();
+
+echo $OUTPUT->footer();
index 1f868d0..8eff841 100644 (file)
@@ -137,8 +137,8 @@ class hub_selector_form extends moodleform {
         $options = array();
         foreach ($hubs as $hub) {
             //to not display a name longer than 100 character (too big)
-            if (textlib::strlen($hub['name']) > 100) {
-                $hubname = textlib::substr($hub['name'], 0, 100);
+            if (core_text::strlen($hub['name']) > 100) {
+                $hubname = core_text::substr($hub['name'], 0, 100);
                 $hubname = $hubname . "...";
             } else {
                 $hubname = $hub['name'];
@@ -287,7 +287,7 @@ class site_registration_form extends moodleform {
         $mform->addHelpButton('description', 'sitedesc', 'hub');
 
         $languages = get_string_manager()->get_list_of_languages();
-        collatorlib::asort($languages);
+        core_collator::asort($languages);
         $mform->addElement('select', 'language', get_string('sitelang', 'hub'),
                 $languages);
         $mform->setType('language', PARAM_ALPHANUMEXT);
index 70ec952..0a73d22 100644 (file)
@@ -57,7 +57,7 @@ foreach (core_component::get_plugin_list('report') as $plugin => $plugindir) {
     }
     $plugins[$plugin] = $strpluginname;
 }
-collatorlib::asort($plugins);
+core_collator::asort($plugins);
 
 $like = $DB->sql_like('plugin', '?', true, true, false, '|');
 $params = array('report|_%');
index 9b7e709..8ffd54d 100644 (file)
@@ -46,7 +46,22 @@ $controller = new $classformode[$mode]();
 if (optional_param('submit', false, PARAM_BOOL) && data_submitted() && confirm_sesskey()) {
     $controller->process_submission();
     $syscontext->mark_dirty();
-    add_to_log(SITEID, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot . '/', '', $baseurl), '', '', $USER->id);
+    $event = null;
+    // Create event depending on mode.
+    switch ($mode) {
+        case 'assign':
+            $event = \core\event\role_allow_assign_updated::create(array('context' => $syscontext));
+            break;
+        case 'override':
+            $event = \core\event\role_allow_override_updated::create(array('context' => $syscontext));
+            break;
+        case 'switch':
+            $event = \core\event\role_allow_switch_updated::create(array('context' => $syscontext));
+            break;
+    }
+    if ($event) {
+        $event->trigger();
+    }
     redirect($baseurl);
 }
 
index 8346640..cce2334 100644 (file)
@@ -110,8 +110,6 @@ if ($roleid) {
             $potentialuserselector->invalidate_selected_users();
             $currentuserselector->invalidate_selected_users();
 
-            $rolename = $assignableroles[$roleid];
-            add_to_log($course->id, 'role', 'assign', 'admin/roles/assign.php?contextid='.$context->id.'&roleid='.$roleid, $rolename, '', $USER->id);
             // Counts have changed, so reload.
             list($assignableroles, $assigncounts, $nameswithcounts) = get_assignable_roles($context, ROLENAME_BOTH, true);
         }
@@ -130,8 +128,6 @@ if ($roleid) {
             $potentialuserselector->invalidate_selected_users();
             $currentuserselector->invalidate_selected_users();
 
-            $rolename = $assignableroles[$roleid];
-            add_to_log($course->id, 'role', 'unassign', 'admin/roles/assign.php?contextid='.$context->id.'&roleid='.$roleid, $rolename, '', $USER->id);
             // Counts have changed, so reload.
             list($assignableroles, $assigncounts, $nameswithcounts) = get_assignable_roles($context, ROLENAME_BOTH, true);
         }
index 496df3e..cd7741c 100644 (file)
@@ -99,8 +99,8 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
         $shortname = optional_param('shortname', null, PARAM_RAW);
         if (!is_null($shortname)) {
             $this->role->shortname = $shortname;
-            $this->role->shortname = textlib::specialtoascii($this->role->shortname);
-            $this->role->shortname = textlib::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
+            $this->role->shortname = core_text::specialtoascii($this->role->shortname);
+            $this->role->shortname = core_text::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
             if (empty($this->role->shortname)) {
                 $this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role');
             }
index f588d1a..265b100 100644 (file)
@@ -196,8 +196,22 @@ if (optional_param('cancel', false, PARAM_BOOL)) {
 // Process submission in necessary.
 if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $definitiontable->is_submission_valid()) {
     $definitiontable->save_changes();
-    add_to_log(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' .
-            $definitiontable->get_role_id(), $definitiontable->get_role_name(), '', $USER->id);
+    $tableroleid = $definitiontable->get_role_id();
+    // Trigger event.
+    $event = \core\event\role_capabilities_updated::create(
+        array(
+            'context' => $systemcontext,
+            'objectid' => $roleid,
+            'other' => array('name' => $definitiontable->get_role_name())
+        )
+    );
+    $event->set_legacy_logdata(array(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' . $tableroleid,
+        $definitiontable->get_role_name(), '', $USER->id));
+    if (!empty($role)) {
+        $event->add_record_snapshot('role', $role);
+    }
+    $event->trigger();
+
     if ($action === 'add') {
         redirect(new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$definitiontable->get_role_id())));
     } else {
index ec02517..e3e094a 100644 (file)
@@ -90,7 +90,6 @@ switch ($action) {
         }
         // Deleted a role sitewide...
         $systemcontext->mark_dirty();
-        add_to_log(SITEID, 'role', 'delete', 'admin/roles/manage.php', $roles[$roleid]->localname, '', $USER->id);
         redirect($baseurl);
         break;
 
index 7d27dc2..bc506f1 100644 (file)
@@ -125,7 +125,25 @@ $overridestable->read_submitted_permissions();
 if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
     $overridestable->save_changes();
     $rolename = $overridableroles[$roleid];
-    add_to_log($course->id, 'role', 'override', 'admin/roles/override.php?contextid='.$context->id.'&roleid='.$roleid, $rolename, '', $USER->id);
+    // Trigger event.
+    $event = \core\event\role_capabilities_updated::create(
+        array(
+            'context' => $context,
+            'objectid' => $roleid,
+            'courseid' => $courseid,
+            'other' => array('name' => $rolename)
+        )
+    );
+
+    $event->set_legacy_logdata(
+        array(
+            $course->id, 'role', 'override', 'admin/roles/override.php?contextid=' . $context->id . '&roleid=' . $roleid,
+            $rolename, '', $USER->id
+        )
+    );
+    $event->add_record_snapshot('role', $role);
+    $event->trigger();
+
     redirect($returnurl);
 }
 
index 1367452..1ee3a7a 100644 (file)
@@ -214,6 +214,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $setting->set_updatedcallback('js_reset_all_caches');
     $temp->add($setting);
     $temp->add(new admin_setting_configcheckbox('modchooserdefault', new lang_string('modchooserdefault', 'admin'), new lang_string('configmodchooserdefault', 'admin'), 1));
+    $temp->add(new admin_setting_configcheckbox('modeditingmenu', new lang_string('modeditingmenu', 'admin'), new lang_string('modeditingmenu_desc', 'admin'), 1));
+    $temp->add(new admin_setting_configcheckbox('blockeditingmenu', new lang_string('blockeditingmenu', 'admin'), new lang_string('blockeditingmenu_desc', 'admin'), 1));
     $ADMIN->add('appearance', $temp);
 
     // link to tag management interface
index 85e3f2d..3a58d34 100644 (file)
@@ -175,16 +175,25 @@ $ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo
 // "performance" settingpage
 $temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
 
+// Memory limit options for large administration tasks.
+$memoryoptions = array(
+    '64M' => '64M',
+    '128M' => '128M',
+    '256M' => '256M',
+    '512M' => '512M',
+    '1024M' => '1024M',
+    '2048M' => '2048M');
+
+// Allow larger memory usage for 64-bit sites only.
+if (PHP_INT_SIZE === 8) {
+    $memoryoptions['3072M'] = '3072M';
+    $memoryoptions['4096M'] = '4096M';
+}
+
 $temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
                                           new lang_string('configextramemorylimit', 'admin'), '512M',
-                                          // if this option is set to 0, default 128M will be used
-                                          array( '64M' => '64M',
-                                                 '128M' => '128M',
-                                                 '256M' => '256M',
-                                                 '512M' => '512M',
-                                                 '1024M' => '1024M',
-                                                 '2048M' => '2048M',
-                                             )));
+                                          $memoryoptions));
+
 $temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
                                         new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
 
index e37f9bc..c0d3665 100644 (file)
@@ -65,6 +65,37 @@ Feature: Set up contextual data for tests
     And I should see "Grouping 1"
     And I should see "Grouping 2"
 
+  @javascript
+  Scenario: Role overrides
+    Given the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | 1 | teacher1@asd.com |
+      | student1 | Student | 1 | student1@asd.com |
+    And the following "categories" exists:
+      | name | category | idnumber |
+      | Cat 1 | 0 | CAT1 |
+    And the following "courses" exists:
+      | fullname | shortname |
+      | Course 1 | C1 |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | student1 | C1 | student |
+      | teacher1 | C1 | editingteacher |
+    And the following "permission overrides" exists:
+      | capability | permission | role | contextlevel | reference |
+      | mod/forum:editanypost | Allow | student | Course | C1 |
+      | mod/forum:replynews | Prevent | editingteacher | Course | C1 |
+    When I log in as "admin"
+    And I follow "Course 1"
+    And I expand "Users" node
+    And I follow "Permissions"
+    And I select "Student (1)" from "Advanced role override"
+    Then the "mod/forum:editanypost" field should match "1" value
+    And I press "Cancel"
+    And I select "Teacher (1)" from "Advanced role override"
+    And the "mod/forum:replynews" field should match "-1" value
+    And I press "Cancel"
+
   Scenario: Add course enrolments
     Given the following "users" exists:
       | username | firstname | lastname | email |
index 629e498..782e1e8 100644 (file)
@@ -399,7 +399,7 @@ class tool_uploadcourse_course {
      * @return bool false is any error occured.
      */
     public function prepare() {
-        global $DB;
+        global $DB, $SITE;
         $this->prepared = true;
 
         // Validate the shortname.
@@ -432,6 +432,12 @@ class tool_uploadcourse_course {
                 $this->error('courseexistsanduploadnotallowed',
                     new lang_string('courseexistsanduploadnotallowed', 'tool_uploadcourse'));
                 return false;
+            } else if ($this->can_update()) {
+                // We can never allow for any front page changes!
+                if ($this->shortname == $SITE->shortname) {
+                    $this->error('cannotupdatefrontpage', new lang_string('cannotupdatefrontpage', 'tool_uploadcourse'));
+                    return false;
+                }
             }
         } else {
             if (!$this->can_create()) {
@@ -608,6 +614,13 @@ class tool_uploadcourse_course {
         if ($exists) {
             $missingonly = ($updatemode === tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS);
             $coursedata = $this->get_final_update_data($coursedata, $usedefaults, $missingonly);
+
+            // Make sure we are not trying to mess with the front page, though we should never get here!
+            if ($coursedata['id'] == $SITE->id) {
+                $this->error('cannotupdatefrontpage', new lang_string('cannotupdatefrontpage', 'tool_uploadcourse'));
+                return false;
+            }
+
             $this->do = self::DO_UPDATE;
         } else {
             $coursedata = $this->get_final_create_data($coursedata);
@@ -715,6 +728,7 @@ class tool_uploadcourse_course {
                 $this->error('errorwhilerestoringcourse', new lang_string('errorwhilerestoringthecourse', 'tool_uploadcourse'));
             }
             $rc->destroy();
+            unset($rc); // File logging is a mess, we can only try to rely on gc to close handles.
         }
 
         // Proceed with enrolment data.
index b328a42..ebd0b75 100644 (file)
@@ -44,6 +44,13 @@ class tool_uploadcourse_helper {
      */
     public static function clean_restore_content() {
         global $CFG;
+
+        // There are some sloppy unclosed file handles in backup/restore code,
+        // let's hope somebody unset all controllers before calling this
+        // and destroy magic will close all remaining open file handles,
+        // otherwise Windows will fail deleting the directory.
+        gc_collect_cycles();
+
         if (!empty($CFG->keeptempdirectoriesonbackup)) {
             $cache = cache::make('tool_uploadcourse', 'helper');
             $backupids = (array) $cache->get('backupids');
@@ -110,18 +117,18 @@ class tool_uploadcourse_helper {
 
         switch ($block[1]) {
             case '+':
-                $repl = textlib::strtoupper($repl);
+                $repl = core_text::strtoupper($repl);
                 break;
             case '-':
-                $repl = textlib::strtolower($repl);
+                $repl = core_text::strtolower($repl);
                 break;
             case '~':
-                $repl = textlib::strtotitle($repl);
+                $repl = core_text::strtotitle($repl);
                 break;
         }
 
         if (!empty($block[2])) {
-            $repl = textlib::substr($repl, 0, $block[2]);
+            $repl = core_text::substr($repl, 0, $block[2]);
         }
 
         return $repl;
index cd0abc0..189ff9e 100644 (file)
@@ -57,7 +57,7 @@ class tool_uploadcourse_step1_form extends tool_uploadcourse_base_form {
             $mform->setDefault('delimiter_name', 'comma');
         }
 
-        $choices = textlib::get_encodings();
+        $choices = core_text::get_encodings();
         $mform->addElement('select', 'encoding', get_string('encoding', 'tool_uploadcourse'), $choices);
         $mform->setDefault('encoding', 'UTF-8');
 
index 1aa4613..511d602 100644 (file)
@@ -145,7 +145,7 @@ if (!file_exists($options['file'])) {
 }
 
 // Encoding.
-$encodings = textlib::get_encodings();
+$encodings = core_text::get_encodings();
 if (!isset($encodings[$options['encoding']])) {
     echo get_string('invalidencoding', 'tool_uploadcourse')."\n";
     echo $help;
index 83138d3..3be7ec4 100644 (file)
@@ -32,6 +32,7 @@ $string['cannotreadbackupfile'] = 'Cannot read the backup file';
 $string['cannotrenamecoursenotexist'] = 'Cannot rename a course that does not exist';
 $string['cannotrenameidnumberconflict'] = 'Cannot rename the course, the ID number conflicts with an existing course';
 $string['cannotrenameshortnamealreadyinuse'] = 'Cannot rename the course, the shortname is already used';
+$string['cannotupdatefrontpage'] = 'It is forbidden to modify the front page';
 $string['canonlyrenameinupdatemode'] = 'Can only rename a course when update is allowed';
 $string['canonlyresetcourseinupdatemode'] = 'Can only reset a course in update mode';
 $string['couldnotresolvecatgorybyid'] = 'Could not resolve category by ID';
index f04a2ea..ee979b4 100644 (file)
@@ -768,6 +768,7 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
     }
 
     public function test_create_bad_category() {
+        global $DB;
         $this->resetAfterTest(true);
 
         // Ensure fails when category cannot be resolved upon creation.
@@ -778,6 +779,14 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
         $this->assertFalse($co->prepare());
         $this->assertArrayHasKey('couldnotresolvecatgorybyid', $co->get_errors());
 
+        // Ensure fails when category is 0 on create.
+        $mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
+        $data = array('shortname' => 'c1', 'summary' => 'summary', 'fullname' => 'FN', 'category' => '0');
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data);
+        $this->assertFalse($co->prepare());
+        $this->assertArrayHasKey('missingmandatoryfields', $co->get_errors());
+
         // Ensure fails when category cannot be resolved upon update.
         $c1 = $this->getDataGenerator()->create_course();
         $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
@@ -786,6 +795,31 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
         $co = new tool_uploadcourse_course($mode, $updatemode, $data);
         $this->assertFalse($co->prepare());
         $this->assertArrayHasKey('couldnotresolvecatgorybyid', $co->get_errors());
+
+        // Ensure does not update the category when it is 0.
+        $c1 = $this->getDataGenerator()->create_course();
+        $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
+        $data = array('shortname' => $c1->shortname, 'category' => '0');
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data);
+        $this->assertTrue($co->prepare());
+        $this->assertEmpty($co->get_errors());
+        $this->assertEmpty($co->get_statuses());
+        $co->proceed();
+        $this->assertEquals($c1->category, $DB->get_field('course', 'category', array('id' => $c1->id)));
+
+        // Ensure does not update the category when it is set to 0 in the defaults.
+        $c1 = $this->getDataGenerator()->create_course();
+        $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS;
+        $data = array('shortname' => $c1->shortname);
+        $defaults = array('category' => '0');
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults);
+        $this->assertTrue($co->prepare());
+        $this->assertEmpty($co->get_errors());
+        $this->assertEmpty($co->get_statuses());
+        $co->proceed();
+        $this->assertEquals($c1->category, $DB->get_field('course', 'category', array('id' => $c1->id)));
     }
 
     public function test_enrolment_data() {
@@ -920,4 +954,47 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
         $this->assertArrayHasKey('courseshortnameincremented', $co->get_statuses());
     }
 
+    public function test_mess_with_frontpage() {
+        global $SITE;
+        $this->resetAfterTest(true);
+
+        // Updating the front page.
+        $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
+        $data = array('shortname' => $SITE->shortname, 'idnumber' => 'NewIDN');
+        $importoptions = array();
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions);
+        $this->assertFalse($co->prepare());
+        $this->assertArrayHasKey('cannotupdatefrontpage', $co->get_errors());
+
+        // Updating the front page.
+        $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
+        $data = array('shortname' => $SITE->shortname, 'idnumber' => 'NewIDN');
+        $importoptions = array();
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions);
+        $this->assertFalse($co->prepare());
+        $this->assertArrayHasKey('cannotupdatefrontpage', $co->get_errors());
+
+        // Generating a shortname should not be allowed in update mode, and so we cannot update the front page.
+        $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
+        $data = array('idnumber' => 'NewIDN', 'fullname' => 'FN', 'category' => 1);
+        $importoptions = array('shortnametemplate' => $SITE->shortname);
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions);
+        $this->assertFalse($co->prepare());
+        $this->assertArrayHasKey('cannotgenerateshortnameupdatemode', $co->get_errors());
+
+        // Renaming to the front page should not be allowed.
+        $c1 = $this->getDataGenerator()->create_course();
+        $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE;
+        $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
+        $data = array('shortname' => $c1->shortname, 'fullname' => 'FN', 'idnumber' => 'NewIDN', 'rename' => $SITE->shortname);
+        $importoptions = array('canrename' => true);
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions);
+        $this->assertFalse($co->prepare());
+        $this->assertArrayHasKey('cannotrenameshortnamealreadyinuse', $co->get_errors());
+
+    }
+
 }
index 873e221..31e53e0 100644 (file)
@@ -129,6 +129,7 @@ class tool_uploadcourse_helper_testcase extends advanced_testcase {
         $this->assertTrue(isset($result['backup_destination']));
         $c1backupfile = $result['backup_destination']->copy_content_to_temp();
         $bc->destroy();
+        unset($bc); // File logging is a mess, we can only try to rely on gc to close handles.
 
         // Creating backup file.
         $bc = new backup_controller(backup::TYPE_1COURSE, $c2->id, backup::FORMAT_MOODLE,
@@ -138,6 +139,7 @@ class tool_uploadcourse_helper_testcase extends advanced_testcase {
         $this->assertTrue(isset($result['backup_destination']));
         $c2backupfile = $result['backup_destination']->copy_content_to_temp();
         $bc->destroy();
+        unset($bc); // File logging is a mess, we can only try to rely on gc to close handles.
 
         // Checking restore dir.
         $dir = tool_uploadcourse_helper::get_restore_content_dir($c1backupfile, null);
index 928b13e..01863f9 100644 (file)
@@ -183,7 +183,7 @@ function uu_validate_user_upload_columns(csv_import_reader $cir, $stdfields, $pr
     $processed = array();
     foreach ($columns as $key=>$unused) {
         $field = $columns[$key];
-        $lcfield = textlib::strtolower($field);
+        $lcfield = core_text::strtolower($field);
         if (in_array($field, $stdfields) or in_array($lcfield, $stdfields)) {
             // standard fields are only lowercase
             $newfield = $lcfield;
@@ -295,18 +295,18 @@ function uu_process_template_callback($username, $firstname, $lastname, $block)
 
     switch ($block[1]) {
         case '+':
-            $repl = textlib::strtoupper($repl);
+            $repl = core_text::strtoupper($repl);
             break;
         case '-':
-            $repl = textlib::strtolower($repl);
+            $repl = core_text::strtolower($repl);
             break;
         case '~':
-            $repl = textlib::strtotitle($repl);
+            $repl = core_text::strtotitle($repl);
             break;
     }
 
     if (!empty($block[2])) {
-        $repl = textlib::substr($repl, 0 , $block[2]);
+        $repl = core_text::substr($repl, 0 , $block[2]);
     }
 
     return $repl;
@@ -321,12 +321,13 @@ function uu_process_template_callback($username, $firstname, $lastname, $block)
  * @return array type=>name
  */
 function uu_supported_auths() {
-    // only following plugins are guaranteed to work properly
-    $whitelist = array('manual', 'nologin', 'none', 'email');
+    // Get all the enabled plugins.
     $plugins = get_enabled_auth_plugins();
     $choices = array();
     foreach ($plugins as $plugin) {
-        if (!in_array($plugin, $whitelist)) {
+        $objplugin = get_auth_plugin($plugin);
+        // If the plugin can not be manually set skip it.
+        if (!$objplugin->can_be_manually_set()) {
             continue;
         }
         $choices[$plugin] = get_string('pluginname', "auth_{$plugin}");
index b377a9b..ce32ea2 100644 (file)
@@ -53,7 +53,7 @@ class admin_uploaduser_form1 extends moodleform {
             $mform->setDefault('delimiter_name', 'comma');
         }
 
-        $choices = textlib::get_encodings();
+        $choices = core_text::get_encodings();
         $mform->addElement('select', 'encoding', get_string('encoding', 'tool_uploaduser'), $choices);
         $mform->setDefault('encoding', 'UTF-8');
 
index 8041672..f2128b1 100644 (file)
@@ -75,8 +75,8 @@ class check_oracle_semantics extends XMLDBCheckAction {
                 // Get current semantic from dictionary, we only will process B (BYTE) ones
                 // suplying the SQL code to change them to C (CHAR) semantic
                 $params = array(
-                    'table_name' => textlib::strtoupper($DB->get_prefix() . $xmldb_table->getName()),
-                    'column_name' => textlib::strtoupper($xmldb_field->getName()),
+                    'table_name' => core_text::strtoupper($DB->get_prefix() . $xmldb_table->getName()),
+                    'column_name' => core_text::strtoupper($xmldb_field->getName()),
                     'data_type' => 'VARCHAR2');
                 $currentsemantic = $DB->get_field_sql('
                     SELECT char_used
index 491e451..5f6a468 100644 (file)
@@ -57,7 +57,7 @@ foreach (core_component::get_plugin_list('tool') as $plugin => $plugindir) {
     }
     $plugins[$plugin] = $strpluginname;
 }
-collatorlib::asort($plugins);
+core_collator::asort($plugins);
 
 $like = $DB->sql_like('plugin', '?', true, true, false, '|');
 $params = array('tool|_%');
index b1c09ae..3aef57c 100644 (file)
@@ -73,12 +73,17 @@ class external_service_form extends moodleform {
         $mform->addHelpButton('restrictedusers', 'restrictedusers', 'webservice');
         $mform->setType('restrictedusers', PARAM_BOOL);
 
-        //can users download files
+        // 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);
 
+        // Can users upload files?
+        $mform->addElement('advcheckbox', 'uploadfiles', get_string('uploadfiles', 'webservice'));
+        $mform->setAdvanced('uploadfiles');
+        $mform->addHelpButton('uploadfiles', 'uploadfiles', 'webservice');
+
         /// needed to select automatically the 'No required capability" option
         $currentcapabilityexist = false;
         if (empty($service->requiredcapability)) {
@@ -297,4 +302,4 @@ class web_service_token_form extends moodleform {
         return $errors;
     }
 
-}
\ No newline at end of file
+}
index 95ab725..6d1d582 100644 (file)
@@ -61,7 +61,7 @@ class auth_plugin_cas extends auth_plugin_ldap {
      */
     function user_login ($username, $password) {
         $this->connectCAS();
-        return phpCAS::isAuthenticated() && (trim(textlib::strtolower(phpCAS::getUser())) == $username);
+        return phpCAS::isAuthenticated() && (trim(core_text::strtolower(phpCAS::getUser())) == $username);
     }
 
     /**
@@ -381,15 +381,15 @@ class auth_plugin_cas extends auth_plugin_ldap {
         set_config('ldapencoding', trim($config->ldapencoding), $this->pluginconfig);
         set_config('pagesize', (int)trim($config->pagesize), $this->pluginconfig);
         set_config('contexts', trim($config->contexts), $this->pluginconfig);
-        set_config('user_type', textlib::strtolower(trim($config->user_type)), $this->pluginconfig);
-        set_config('user_attribute', textlib::strtolower(trim($config->user_attribute)), $this->pluginconfig);
+        set_config('user_type', core_text::strtolower(trim($config->user_type)), $this->pluginconfig);
+        set_config('user_attribute', core_text::strtolower(trim($config->user_attribute)), $this->pluginconfig);
         set_config('search_sub', $config->search_sub, $this->pluginconfig);
         set_config('opt_deref', $config->opt_deref, $this->pluginconfig);
         set_config('bind_dn', trim($config->bind_dn), $this->pluginconfig);
         set_config('bind_pw', $config->bind_pw, $this->pluginconfig);
         set_config('ldap_version', $config->ldap_version, $this->pluginconfig);
         set_config('objectclass', trim($config->objectclass), $this->pluginconfig);
-        set_config('memberattribute', textlib::strtolower(trim($config->memberattribute)), $this->pluginconfig);
+        set_config('memberattribute', core_text::strtolower(trim($config->memberattribute)), $this->pluginconfig);
         set_config('memberattribute_isdn', $config->memberattribute_isdn, $this->pluginconfig);
         set_config('attrcreators', trim($config->attrcreators), $this->pluginconfig);
         set_config('groupecreators', trim($config->groupecreators), $this->pluginconfig);
@@ -409,7 +409,7 @@ class auth_plugin_cas extends auth_plugin_ldap {
             return false;
         }
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
 
         // Test for group creator
         if (!empty($this->config->groupecreators)) {
index f245d60..de5061d 100644 (file)
@@ -58,8 +58,8 @@ class auth_plugin_db extends auth_plugin_base {
     function user_login($username, $password) {
         global $CFG, $DB;
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->extencoding);
-        $extpassword = textlib::convert($password, 'utf-8', $this->config->extencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->extencoding);
+        $extpassword = core_text::convert($password, 'utf-8', $this->config->extencoding);
 
         if ($this->is_internal()) {
             // Lookup username externally, but resolve
@@ -176,7 +176,7 @@ class auth_plugin_db extends auth_plugin_base {
     function get_userinfo($username) {
         global $CFG;
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->extencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->extencoding);
 
         $authdb = $this->db_init();
 
@@ -199,7 +199,7 @@ class auth_plugin_db extends auth_plugin_base {
                     $fields_obj = $rs->FetchObj();
                     $fields_obj = (object)array_change_key_case((array)$fields_obj , CASE_LOWER);
                     foreach ($selectfields as $localname=>$externalname) {
-                        $result[$localname] = textlib::convert($fields_obj->{$localname}, $this->config->extencoding, 'utf-8');
+                        $result[$localname] = core_text::convert($fields_obj->{$localname}, $this->config->extencoding, 'utf-8');
                      }
                  }
                  $rs->Close();
@@ -426,7 +426,7 @@ class auth_plugin_db extends auth_plugin_base {
         // Init result value.
         $result = false;
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->extencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->extencoding);
 
         $authdb = $this->db_init();
 
@@ -501,7 +501,7 @@ class auth_plugin_db extends auth_plugin_base {
         global $CFG, $DB;
 
         //just in case check text case
-        $username = trim(textlib::strtolower($username));
+        $username = trim(core_text::strtolower($username));
 
         // get the current user record
         $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id));
@@ -569,7 +569,7 @@ class auth_plugin_db extends auth_plugin_base {
             return false;
         }
 
-        $extusername = textlib::convert($olduser->username, 'utf-8', $this->config->extencoding);
+        $extusername = core_text::convert($olduser->username, 'utf-8', $this->config->extencoding);
 
         $authdb = $this->db_init();
 
@@ -586,7 +586,7 @@ class auth_plugin_db extends auth_plugin_base {
             }
             $nuvalue = $newuser->$key;
             if ($nuvalue != $value) {
-                $update[] = $this->config->{"field_map_$key"}."='".$this->ext_addslashes(textlib::convert($nuvalue, 'utf-8', $this->config->extencoding))."'";
+                $update[] = $this->config->{"field_map_$key"}."='".$this->ext_addslashes(core_text::convert($nuvalue, 'utf-8', $this->config->extencoding))."'";
             }
         }
         if (!empty($update)) {
index 9ac59bd..e459004 100644 (file)
@@ -195,6 +195,15 @@ class auth_plugin_email extends auth_plugin_base {
         return true;
     }
 
+    /**
+     * Returns true if plugin can be manually set.
+     *
+     * @return bool
+     */
+    function can_be_manually_set() {
+        return true;
+    }
+
     /**
      * Prints a form for configuring this authentication plugin.
      *
index e9d82b7..a1a9645 100644 (file)
@@ -168,8 +168,8 @@ class auth_plugin_ldap extends auth_plugin_base {
             return false;
         }
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
-        $extpassword = textlib::convert($password, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extpassword = core_text::convert($password, 'utf-8', $this->config->ldapencoding);
 
         // Before we connect to LDAP, check if this is an AD SSO login
         // if we succeed in this block, we'll return success early.
@@ -250,7 +250,7 @@ class auth_plugin_ldap extends auth_plugin_base {
      * @return mixed array with no magic quotes or false on error
      */
     function get_userinfo($username) {
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
 
         $ldapconnection = $this->ldap_connect();
         if(!($user_dn = $this->ldap_find_userdn($ldapconnection, $extusername))) {
@@ -298,9 +298,9 @@ class auth_plugin_ldap extends auth_plugin_base {
                     continue; // wrong data mapping!
                 }
                 if (is_array($entry[$value])) {
-                    $newval = textlib::convert($entry[$value][0], $this->config->ldapencoding, 'utf-8');
+                    $newval = core_text::convert($entry[$value][0], $this->config->ldapencoding, 'utf-8');
                 } else {
-                    $newval = textlib::convert($entry[$value], $this->config->ldapencoding, 'utf-8');
+                    $newval = core_text::convert($entry[$value], $this->config->ldapencoding, 'utf-8');
                 }
                 if (!empty($newval)) { // favour ldap entries that are set
                     $ldapval = $newval;
@@ -351,7 +351,7 @@ class auth_plugin_ldap extends auth_plugin_base {
      * @param string $username
      */
     function user_exists($username) {
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
 
         // Returns true if given username exists on ldap
         $users = $this->ldap_get_userlist('('.$this->config->user_attribute.'='.ldap_filter_addslashes($extusername).')');
@@ -367,8 +367,8 @@ class auth_plugin_ldap extends auth_plugin_base {
      * @param mixed $plainpass   Plaintext password
      */
     function user_create($userobject, $plainpass) {
-        $extusername = textlib::convert($userobject->username, 'utf-8', $this->config->ldapencoding);
-        $extpassword = textlib::convert($plainpass, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($userobject->username, 'utf-8', $this->config->ldapencoding);
+        $extpassword = core_text::convert($plainpass, 'utf-8', $this->config->ldapencoding);
 
         switch ($this->config->passtype) {
             case 'md5':
@@ -393,7 +393,7 @@ class auth_plugin_ldap extends auth_plugin_base {
             }
             foreach ($values as $value) {
                 if (!empty($userobject->$key) ) {
-                    $newuser[$value] = textlib::convert($userobject->$key, 'utf-8', $this->config->ldapencoding);
+                    $newuser[$value] = core_text::convert($userobject->$key, 'utf-8', $this->config->ldapencoding);
                 }
             }
         }
@@ -509,6 +509,15 @@ class auth_plugin_ldap extends auth_plugin_base {
         return !empty($this->config->stdchangepassword);
     }
 
+    /**
+     * Returns true if plugin can be manually set.
+     *
+     * @return bool
+     */
+    function can_be_manually_set() {
+        return true;
+    }
+
     /**
      * Returns true if plugin allows signup and user creation.
      *
@@ -628,7 +637,7 @@ class auth_plugin_ldap extends auth_plugin_base {
     function password_expire($username) {
         $result = 0;
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
 
         $ldapconnection = $this->ldap_connect();
         $user_dn = $this->ldap_find_userdn($ldapconnection, $extusername);
@@ -726,7 +735,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                 if ($entry = @ldap_first_entry($ldapconnection, $ldap_result)) {
                     do {
                         $value = ldap_get_values_len($ldapconnection, $entry, $this->config->user_attribute);
-                        $value = textlib::convert($value[0], $this->config->ldapencoding, 'utf-8');
+                        $value = core_text::convert($value[0], $this->config->ldapencoding, 'utf-8');
                         $this->ldap_bulk_insert($value);
                     } while ($entry = ldap_next_entry($ldapconnection, $entry));
                 }
@@ -936,7 +945,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                 $user->mnethostid = $CFG->mnet_localhost_id;
                 // get_userinfo_asobj() might have replaced $user->username with the value
                 // from the LDAP server (which can be mixed-case). Make sure it's lowercase
-                $user->username = trim(textlib::strtolower($user->username));
+                $user->username = trim(core_text::strtolower($user->username));
                 if (empty($user->lang)) {
                     $user->lang = $CFG->lang;
                 }
@@ -982,7 +991,7 @@ class auth_plugin_ldap extends auth_plugin_base {
         global $CFG, $DB;
 
         // Just in case check text case
-        $username = trim(textlib::strtolower($username));
+        $username = trim(core_text::strtolower($username));
 
         // Get the current user record
         $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id));
@@ -1031,7 +1040,7 @@ class auth_plugin_ldap extends auth_plugin_base {
     function ldap_bulk_insert($username) {
         global $DB, $CFG;
 
-        $username = textlib::strtolower($username); // usernames are __always__ lowercase.
+        $username = core_text::strtolower($username); // usernames are __always__ lowercase.
         $DB->insert_record_raw('tmp_extuser', array('username'=>$username,
                                                     'mnethostid'=>$CFG->mnet_localhost_id), false, true);
         echo '.';
@@ -1044,7 +1053,7 @@ class auth_plugin_ldap extends auth_plugin_base {
      * @return boolean result
      */
     function user_activate($username) {
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
 
         $ldapconnection = $this->ldap_connect();
 
@@ -1094,7 +1103,7 @@ class auth_plugin_ldap extends auth_plugin_base {
             return null;
         }
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
 
         $ldapconnection = $this->ldap_connect();
 
@@ -1152,7 +1161,7 @@ class auth_plugin_ldap extends auth_plugin_base {
             return true;
         }
 
-        $extoldusername = textlib::convert($olduser->username, 'utf-8', $this->config->ldapencoding);
+        $extoldusername = core_text::convert($olduser->username, 'utf-8', $this->config->ldapencoding);
 
         $ldapconnection = $this->ldap_connect();
 
@@ -1214,9 +1223,9 @@ class auth_plugin_ldap extends auth_plugin_base {
                         $ambiguous = false;
                     }
 
-                    $nuvalue = textlib::convert($newuser->$profilefield, 'utf-8', $this->config->ldapencoding);
+                    $nuvalue = core_text::convert($newuser->$profilefield, 'utf-8', $this->config->ldapencoding);
                     empty($nuvalue) ? $nuvalue = array() : $nuvalue;
-                    $ouvalue = textlib::convert($olduser->$profilefield, 'utf-8', $this->config->ldapencoding);
+                    $ouvalue = core_text::convert($olduser->$profilefield, 'utf-8', $this->config->ldapencoding);
 
                     foreach ($ldapkeys as $ldapkey) {
                         $ldapkey   = $ldapkey;
@@ -1312,8 +1321,8 @@ class auth_plugin_ldap extends auth_plugin_base {
         $result = false;
         $username = $user->username;
 
-        $extusername = textlib::convert($username, 'utf-8', $this->config->ldapencoding);
-        $extpassword = textlib::convert($newpassword, 'utf-8', $this->config->ldapencoding);
+        $extusername = core_text::convert($username, 'utf-8', $this->config->ldapencoding);
+        $extpassword = core_text::convert($newpassword, 'utf-8', $this->config->ldapencoding);
 
         switch ($this->config->passtype) {
             case 'md5':
@@ -1489,13 +1498,13 @@ class auth_plugin_ldap extends auth_plugin_base {
 
         foreach ($userfields as $field) {
             if (!empty($this->config->{"field_map_$field"})) {
-                $moodleattributes[$field] = textlib::strtolower(trim($this->config->{"field_map_$field"}));
+                $moodleattributes[$field] = core_text::strtolower(trim($this->config->{"field_map_$field"}));
                 if (preg_match('/,/', $moodleattributes[$field])) {
                     $moodleattributes[$field] = explode(',', $moodleattributes[$field]); // split ?
                 }
             }
         }
-        $moodleattributes['username'] = textlib::strtolower(trim($this->config->user_attribute));
+        $moodleattributes['username'] = core_text::strtolower(trim($this->config->user_attribute));
         return $moodleattributes;
     }
 
@@ -1546,7 +1555,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                 $users = ldap_get_entries_moodle($ldapconnection, $ldap_result);
                 // Add found users to list.
                 for ($i = 0; $i < count($users); $i++) {
-                    $extuser = textlib::convert($users[$i][$this->config->user_attribute][0],
+                    $extuser = core_text::convert($users[$i][$this->config->user_attribute][0],
                                                 $this->config->ldapencoding, 'utf-8');
                     array_push($fresult, $extuser);
                 }
@@ -1687,7 +1696,7 @@ class auth_plugin_ldap extends auth_plugin_base {
             // (according to my reading of RFC-1945, RFC-2616 and RFC-2617 and
             // my local tests), so we need to convert the REMOTE_USER value
             // (i.e., what we got from the HTTP WWW-Authenticate header) into UTF-8
-            $username = textlib::convert($_SERVER['REMOTE_USER'], 'iso-8859-1', 'utf-8');
+            $username = core_text::convert($_SERVER['REMOTE_USER'], 'iso-8859-1', 'utf-8');
 
             switch ($this->config->ntlmsso_type) {
                 case 'ntlm':
@@ -1706,7 +1715,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                     return false; // Should never happen!
             }
 
-            $username = textlib::strtolower($username); // Compatibility hack
+            $username = core_text::strtolower($username); // Compatibility hack
             set_cache_flag($this->pluginconfig.'/ntlmsess', $sesskey, $username, AUTH_NTLMTIMEOUT);
             return true;
         }
@@ -1915,7 +1924,7 @@ class auth_plugin_ldap extends auth_plugin_base {
 
         // Try to remove duplicates before storing the contexts (to avoid problems in sync_users()).
         $config->contexts = explode(';', $config->contexts);
-        $config->contexts = array_map(create_function('$x', 'return textlib::strtolower(trim($x));'),
+        $config->contexts = array_map(create_function('$x', 'return core_text::strtolower(trim($x));'),
                                       $config->contexts);
         $config->contexts = implode(';', array_unique($config->contexts));
 
@@ -1925,8 +1934,8 @@ class auth_plugin_ldap extends auth_plugin_base {
         set_config('ldapencoding', trim($config->ldapencoding), $this->pluginconfig);
         set_config('pagesize', (int)trim($config->pagesize), $this->pluginconfig);
         set_config('contexts', $config->contexts, $this->pluginconfig);
-        set_config('user_type', textlib::strtolower(trim($config->user_type)), $this->pluginconfig);
-        set_config('user_attribute', textlib::strtolower(trim($config->user_attribute)), $this->pluginconfig);
+        set_config('user_type', core_text::strtolower(trim($config->user_type)), $this->pluginconfig);
+        set_config('user_attribute', core_text::strtolower(trim($config->user_attribute)), $this->pluginconfig);
         set_config('search_sub', $config->search_sub, $this->pluginconfig);
         set_config('opt_deref', $config->opt_deref, $this->pluginconfig);
         set_config('preventpassindb', $config->preventpassindb, $this->pluginconfig);
@@ -1934,15 +1943,15 @@ class auth_plugin_ldap extends auth_plugin_base {
         set_config('bind_pw', $config->bind_pw, $this->pluginconfig);
         set_config('ldap_version', $config->ldap_version, $this->pluginconfig);
         set_config('objectclass', trim($config->objectclass), $this->pluginconfig);
-        set_config('memberattribute', textlib::strtolower(trim($config->memberattribute)), $this->pluginconfig);
+        set_config('memberattribute', core_text::strtolower(trim($config->memberattribute)), $this->pluginconfig);
         set_config('memberattribute_isdn', $config->memberattribute_isdn, $this->pluginconfig);
         set_config('creators', trim($config->creators), $this->pluginconfig);
         set_config('create_context', trim($config->create_context), $this->pluginconfig);
         set_config('expiration', $config->expiration, $this->pluginconfig);
         set_config('expiration_warning', trim($config->expiration_warning), $this->pluginconfig);
-        set_config('expireattr', textlib::strtolower(trim($config->expireattr)), $this->pluginconfig);
+        set_config('expireattr', core_text::strtolower(trim($config->expireattr)), $this->pluginconfig);
         set_config('gracelogins', $config->gracelogins, $this->pluginconfig);
-        set_config('graceattr', textlib::strtolower(trim($config->graceattr)), $this->pluginconfig);
+        set_config('graceattr', core_text::strtolower(trim($config->graceattr)), $this->pluginconfig);
         set_config('auth_user_create', $config->auth_user_create, $this->pluginconfig);
         set_config('forcechangepassword', $config->forcechangepassword, $this->pluginconfig);
         set_config('stdchangepassword', $config->stdchangepassword, $this->pluginconfig);
index 3b4fdae..1c7ff9e 100644 (file)
@@ -129,6 +129,15 @@ class auth_plugin_manual extends auth_plugin_base {
         return true;
     }
 
+    /**
+     * Returns true if plugin can be manually set.
+     *
+     * @return bool
+     */
+    function can_be_manually_set() {
+        return true;
+    }
+
     /**
      * Prints a form for configuring this authentication plugin.
      *
index 29f018e..c3ed391 100644 (file)
@@ -85,6 +85,14 @@ class auth_plugin_nologin extends auth_plugin_base {
         return false;
     }
 
+    /**
+     * Returns true if plugin can be manually set.
+     *
+     * @return bool
+     */
+    function can_be_manually_set() {
+        return true;
+    }
 }
 
 
index 9d3bfc2..fcfce4c 100644 (file)
@@ -115,6 +115,15 @@ class auth_plugin_none extends auth_plugin_base {
         return true;
     }
 
+    /**
+     * Returns true if plugin can be manually set.
+     *
+     * @return bool
+     */
+    function can_be_manually_set() {
+        return true;
+    }
+
     /**
      * Prints a form for configuring this authentication plugin.
      *
diff --git a/auth/tests/auth_test.php b/auth/tests/auth_test.php
deleted file mode 100644 (file)
index 0b2b8ae..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Tests for auth.
- *
- * @package    core_auth
- * @copyright  2013 Frédéric Massart
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-global $CFG;
-require_once($CFG->libdir . '/authlib.php');
-
-/**
- * Auth testcase class.
- *
- * @package    core_auth
- * @copyright  2013 Frédéric Massart
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class auth_testcase extends advanced_testcase {
-
-    public function test_user_loggedin_event() {
-        global $USER;
-        $this->resetAfterTest(true);
-        $this->setAdminUser();
-
-        $sink = $this->redirectEvents();
-        $user = clone($USER);
-        login_attempt_valid($user);
-        $events = $sink->get_events();
-        $sink->close();
-
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertInstanceOf('\core_auth\event\user_loggedin', $event);
-        $this->assertEquals('user', $event->objecttable);
-        $this->assertEquals('2', $event->objectid);
-        $this->assertEquals(context_system::instance()->id, $event->contextid);
-        $this->assertEquals($user, $event->get_record_snapshot('user', 2));
-    }
-
-    public function test_user_loggedin_event_exceptions() {
-        try {
-            $event = \core_auth\event\user_loggedin::create(array('objectid' => 1));
-            $this->fail('\core_auth\event\user_loggedin requires other[\'username\']');
-        } catch(Exception $e) {
-            $this->assertInstanceOf('coding_exception', $e);
-        }
-
-        try {
-            $event = \core_auth\event\user_loggedin::create(array('other' => array('username' => 'test')));
-            $this->fail('\core_auth\event\user_loggedin requires objectid');
-        } catch(Exception $e) {
-            $this->assertInstanceOf('coding_exception', $e);
-        }
-    }
-
-}
index 4618dd5..6085397 100644 (file)
@@ -1,6 +1,11 @@
 This files describes API changes in /auth/* - plugins,
 information provided here is intended especially for developers.
 
+=== 2.6 ===
+
+* can_be_manually_set() - This function was introduced in the base class and returns false by default. If overriden by
+  an authentication plugin to return true, the authentication plugin will be able to be manually set for users. For example,
+  when bulk uploading users you will be able to select it as the authentication method they use.
 
 === 2.4 ===
 
index 2847665..cfe16ef 100644 (file)
@@ -79,6 +79,10 @@ switch ($type) {
         print_error('unknownbackuptype');
 }
 
+// Backup of large courses requires extra memory. Use the amount configured
+// in admin settings.
+raise_memory_limit(MEMORY_EXTRA);
+
 if (!($bc = backup_ui::load_controller($backupid))) {
     $bc = new backup_controller($type, $id, backup::FORMAT_MOODLE,
                             backup::INTERACTIVE_YES, backup::MODE_GENERAL, $USER->id);
index 6b44703..a485145 100644 (file)
@@ -30,7 +30,7 @@ require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
 /*
  * controller tests (all)
  */
-class backup_controller_testcase extends advanced_testcase {
+class core_backup_controller_testcase extends advanced_testcase {
 
     protected $moduleid;  // course_modules id used for testing
     protected $sectionid; // course_sections id used for testing
index 539d804..c3df06b 100644 (file)
@@ -1222,7 +1222,7 @@ class moodle1_question_bank_handler extends moodle1_xml_handler {
 
         // replay the upgrade step 2010080901 - updating question image
         if (!empty($data['image'])) {
-            if (textlib::substr(textlib::strtolower($data['image']), 0, 7) == 'http://') {
+            if (core_text::substr(core_text::strtolower($data['image']), 0, 7) == 'http://') {
                 // it is a link, appending to existing question text
                 $data['questiontext'] .= ' <img src="' . $data['image'] . '" />';
 
index 8f7ec30..fb9b9e1 100644 (file)
@@ -1233,7 +1233,7 @@ class moodle1_file_manager implements loggable {
         }
         $filepath = clean_param($filepath, PARAM_PATH);
 
-        if (textlib::strlen($filepath) > 255) {
+        if (core_text::strlen($filepath) > 255) {
             throw new moodle1_convert_exception('file_path_longer_than_255_chars');
         }
 
@@ -30,7 +30,7 @@ global $CFG;
 require_once($CFG->dirroot . '/backup/converter/moodle1/lib.php');
 
 
-class moodle1_converter_testcase extends advanced_testcase {
+class core_backup_moodle1_converter_testcase extends advanced_testcase {
 
     /** @var string the name of the directory containing the unpacked Moodle 1.9 backup */
     protected $tempdir;
index ed36b0a..2b6cdab 100644 (file)
@@ -510,11 +510,11 @@ class restore_review_pending_block_positions extends restore_execution_step {
 
         // Get all the block_position objects pending to match
         $params = array('backupid' => $this->get_restoreid(), 'itemname' => 'block_position');
-        $rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid');
+        $rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid, info');
         // Process block positions, creating them or accumulating for final step
         foreach($rs as $posrec) {
-            // Get the complete position object (stored as info)
-            $position = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'block_position', $posrec->itemid)->info;
+            // Get the complete position object out of the info field.
+            $position = backup_controller_dbops::decode_backup_temp_info($posrec->info);
             // If position is for one already mapped (known) contextid
             // process it now, creating the position, else nothing to
             // do, position finally discarded
@@ -546,12 +546,12 @@ class restore_process_course_modules_availability extends restore_execution_step
 
         // Get all the module_availability objects to process
         $params = array('backupid' => $this->get_restoreid(), 'itemname' => 'module_availability');
-        $rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid');
+        $rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid, info');
         // Process availabilities, creating them if everything matches ok
         foreach($rs as $availrec) {
             $allmatchesok = true;
             // Get the complete availabilityobject
-            $availability = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'module_availability', $availrec->itemid)->info;
+            $availability = backup_controller_dbops::decode_backup_temp_info($availrec->info);
             // Map the sourcecmid if needed and possible
             if (!empty($availability->sourcecmid)) {
                 $newcm = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'course_module', $availability->sourcecmid);
@@ -3624,7 +3624,7 @@ class restore_process_file_aliases_queue extends restore_execution_step {
 
         // Iterate over aliases in the queue.
         foreach ($rs as $record) {
-            $info = unserialize(base64_decode($record->info));
+            $info = restore_dbops::decode_backup_temp_info($record->info);
 
             // Try to pick a repository instance that should serve the alias.
             $repository = $this->choose_repository($info);
@@ -3657,7 +3657,7 @@ class restore_process_file_aliases_queue extends restore_execution_step {
                 $source = null;
 
                 foreach ($candidates as $candidate) {
-                    $candidateinfo = unserialize(base64_decode($candidate->info));
+                    $candidateinfo = backup_controller_dbops::decode_backup_temp_info($candidate->info);
                     if ($candidateinfo->filename === $reference['filename']
                             and $candidateinfo->filepath === $reference['filepath']
                             and !is_null($candidate->newcontextid)
index 6091c09..cd51cae 100644 (file)
@@ -17,6 +17,10 @@ $PAGE->set_pagelayout('standard');
 require_login($course, null, $cm);
 require_capability('moodle/restore:restorecourse', $context);
 
+// Restore of large courses requires extra memory. Use the amount configured
+// in admin settings.
+raise_memory_limit(MEMORY_EXTRA);
+
 if ($stage & restore_ui::STAGE_CONFIRM + restore_ui::STAGE_DESTINATION) {
     $restore = restore_ui::engage_independent_stage($stage, $contextid);
 } else {
index 586ee70..26e2e00 100644 (file)
@@ -7,6 +7,12 @@ information provided here is intended especially for developers.
   method is not available anymore. Temp tables must be created
   inline always.
 
+* Using the info field from backup_ids_temp or backup_files_temp
+  must now go via backup_controller_dbops::decode_backup_temp_info() and
+  backup_controller_dbops::encode_backup_temp_info(). The implementation
+  of the encoding has changed.  These new functions encapsulate any future
+  changes to the encoding.
+
 === 2.5 ===
 
 * New optional param $sortby in backup set_source_table() allows to
index 085fe22..668ff61 100644 (file)
@@ -154,6 +154,44 @@ abstract class backup_controller_dbops extends backup_dbops {
         $dbman->drop_table($table); // And drop it
     }
 
+    /**
+     * Decode the info field from backup_ids_temp or backup_files_temp.
+     *
+     * @param mixed $info The info field data to decode, may be an object or a simple integer.
+     * @return mixed The decoded information.  For simple types it returns, for complex ones we decode.
+     */
+    public static function decode_backup_temp_info($info) {
+        // We encode all data except null.
+        if ($info != null) {
+            if (extension_loaded('zlib')) {
+                return unserialize(gzuncompress(base64_decode($info)));
+            } else {
+                return unserialize(base64_decode($info));
+            }
+        }
+        return $info;
+    }
+
+    /**
+     * Encode the info field for backup_ids_temp or backup_files_temp.
+     *
+     * @param mixed $info string The info field data to encode.
+     * @return string An encoded string of data or null if the input is null.
+     */
+    public static function encode_backup_temp_info($info) {
+        // We encode if there is any information to keep the translations simpler.
+        if ($info != null) {
+            // We compress if possible. It reduces db, network and memory storage. The saving is greater than CPU compression cost.
+            // Compression level 1 is chosen has it produces good compression with the smallest possible overhead, see MDL-40618.
+            if (extension_loaded('zlib')) {
+                return base64_encode(gzcompress(serialize($info), 1));
+            } else {
+                return base64_encode(serialize($info));
+            }
+        }
+        return $info;
+    }
+
     /**
      * Given one type and id from controller, return the corresponding courseid
      */
index 2e2faae..5307637 100644 (file)
@@ -204,7 +204,7 @@ abstract class backup_plan_dbops extends backup_dbops {
         global $DB;
 
         // Calculate backup word
-        $backupword = str_replace(' ', '_', textlib::strtolower(get_string('backupfilename')));
+        $backupword = str_replace(' ', '_', core_text::strtolower(get_string('backupfilename')));
         $backupword = trim(clean_filename($backupword), '_');
 
         // Not $useidonly, lets fetch the name
@@ -228,7 +228,7 @@ abstract class backup_plan_dbops extends backup_dbops {
                     break;
             }
             $shortname = str_replace(' ', '_', $shortname);
-            $shortname = textlib::strtolower(trim(clean_filename($shortname), '_'));
+            $shortname = core_text::strtolower(trim(clean_filename($shortname), '_'));
         }
 
         // The name will always contain the ID, but we append the course short name if requested.
@@ -240,7 +240,7 @@ abstract class backup_plan_dbops extends backup_dbops {
         // Calculate date
         $backupdateformat = str_replace(' ', '_', get_string('backupnameformat', 'langconfig'));
         $date = userdate(time(), $backupdateformat, 99, false);
-        $date = textlib::strtolower(trim(clean_filename($date), '_'));
+        $date = core_text::strtolower(trim(clean_filename($date), '_'));
 
         // Calculate info
         $info = '';
index 12f2601..0e5fabc 100644 (file)
@@ -152,7 +152,7 @@ abstract class restore_dbops {
         $problems = array(); // To store warnings/errors
 
         // Get loaded roles from backup_ids
-        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'role'), '', 'itemid');
+        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'role'), '', 'itemid, info');
         foreach ($rs as $recrole) {
             // If the rolemappings->modified flag is set, that means that we are coming from
             // manually modified mappings (by UI), so accept those mappings an put them to backup_ids
@@ -163,14 +163,13 @@ abstract class restore_dbops {
             // Else, we haven't any info coming from UI, let's calculate the mappings, matching
             // in multiple ways and checking permissions. Note mapping to 0 means "skip"
             } else {
-                $role = (object)self::get_backup_ids_record($restoreid, 'role', $recrole->itemid)->info;
+                $role = (object)backup_controller_dbops::decode_backup_temp_info($recrole->info);
                 $match = self::get_best_assignable_role($role, $courseid, $userid, $samesite);
                 // Send match to backup_ids
                 self::set_backup_ids_record($restoreid, 'role', $recrole->itemid, $match);
                 // Build the rolemappings element for controller
                 unset($role->id);
                 unset($role->nameincourse);
-                unset($role->nameincourse);
                 $role->targetroleid = $match;
                 $rolemappings->mappings[$recrole->itemid] = $role;
                 // Prepare warning if no match found
@@ -673,20 +672,21 @@ abstract class restore_dbops {
         global $DB;
 
         $results = array();
-        $qcats = $DB->get_records_sql("SELECT itemid, parentitemid AS contextid
+        $qcats = $DB->get_recordset_sql("SELECT itemid, parentitemid AS contextid, info
                                          FROM {backup_ids_temp}
                                        WHERE backupid = ?
                                          AND itemname = 'question_category'", array($restoreid));
         foreach ($qcats as $qcat) {
             // If this qcat context haven't been acummulated yet, do that
             if (!isset($results[$qcat->contextid])) {
-                $temprec = self::get_backup_ids_record($restoreid, 'question_category', $qcat->itemid);
+                $info = backup_controller_dbops::decode_backup_temp_info($qcat->info);
                 // Filter by contextlevel if necessary
-                if (is_null($contextlevel) || $contextlevel == $temprec->info->contextlevel) {
-                    $results[$qcat->contextid] = $temprec->info->contextlevel;
+                if (is_null($contextlevel) || $contextlevel == $info->contextlevel) {
+                    $results[$qcat->contextid] = $info->contextlevel;
                 }
             }
         }
+        $qcats->close();
         // Sort by value (contextlevel from CONTEXT_SYSTEM downto CONTEXT_MODULE)
         asort($results);
         return $results;
@@ -700,15 +700,16 @@ abstract class restore_dbops {
         global $DB;
 
         $results = array();
-        $qcats = $DB->get_records_sql("SELECT itemid
+        $qcats = $DB->get_recordset_sql("SELECT itemid, info
                                          FROM {backup_ids_temp}
                                         WHERE backupid = ?
                                           AND itemname = 'question_category'
                                           AND parentitemid = ?", array($restoreid, $contextid));
         foreach ($qcats as $qcat) {
-            $temprec = self::get_backup_ids_record($restoreid, 'question_category', $qcat->itemid);
-            $results[$qcat->itemid] = $temprec->info;
+            $results[$qcat->itemid] = backup_controller_dbops::decode_backup_temp_info($qcat->info);
         }
+        $qcats->close();
+
         return $results;
     }
 
@@ -798,15 +799,15 @@ abstract class restore_dbops {
         global $DB;
 
         $results = array();
-        $qs = $DB->get_records_sql("SELECT itemid
+        $qs = $DB->get_recordset_sql("SELECT itemid, info
                                       FROM {backup_ids_temp}
                                      WHERE backupid = ?
                                        AND itemname = 'question'
                                        AND parentitemid = ?", array($restoreid, $qcatid));
         foreach ($qs as $q) {
-            $temprec = self::get_backup_ids_record($restoreid, 'question', $q->itemid);
-            $results[$q->itemid] = $temprec->info;
+            $results[$q->itemid] = backup_controller_dbops::decode_backup_temp_info($q->info);
         }
+        $qs->close();
         return $results;
     }
 
@@ -893,7 +894,7 @@ abstract class restore_dbops {
         $basepath = $basepath . '/files/';// Get backup file pool base
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $rec) {
-            $file = (object)unserialize(base64_decode($rec->info));
+            $file = (object)backup_controller_dbops::decode_backup_temp_info($rec->info);
 
             // ignore root dirs (they are created automatically)
             if ($file->filepath == '/' && $file->filename == '.') {
@@ -1018,9 +1019,9 @@ abstract class restore_dbops {
         $themes    = get_list_of_themes(); // Get themes for quick search later
 
         // Iterate over all the included users with newitemid = 0, have to create them
-        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'user', 'newitemid' => 0), '', 'itemid, parentitemid');
+        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'user', 'newitemid' => 0), '', 'itemid, parentitemid, info');
         foreach ($rs as $recuser) {
-            $user = (object)self::get_backup_ids_record($restoreid, 'user', $recuser->itemid)->info;
+            $user = (object)backup_controller_dbops::decode_backup_temp_info($recuser->info);
 
             // if user lang doesn't exist here, use site default
             if (!array_key_exists($user->lang, $languages)) {
@@ -1409,9 +1410,9 @@ abstract class restore_dbops {
         }
 
         // Iterate over all the included users
-        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'user'), '', 'itemid');
+        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'user'), '', 'itemid, info');
         foreach ($rs as $recuser) {
-            $user = (object)self::get_backup_ids_record($restoreid, 'user', $recuser->itemid)->info;
+            $user = (object)backup_controller_dbops::decode_backup_temp_info($recuser->info);
 
             // Find the correct mnethostid for user before performing any further check
             if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) {
@@ -1496,7 +1497,7 @@ abstract class restore_dbops {
         global $DB;
 
         // Store external files info in `info` field
-        $filerec->info     = base64_encode(serialize($filerec)); // Serialize the whole rec in info
+        $filerec->info     = backup_controller_dbops::encode_backup_temp_info($filerec); // Encode the whole record into info.
         $filerec->backupid = $restoreid;
         $DB->insert_record('backup_files_temp', $filerec);
     }
@@ -1511,7 +1512,7 @@ abstract class restore_dbops {
             $extrarecord['parentitemid'] = $parentitemid;
         }
         if ($info != null) {
-            $extrarecord['info'] = base64_encode(serialize($info));
+            $extrarecord['info'] = backup_controller_dbops::encode_backup_temp_info($info);
         }
 
         self::set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord);
@@ -1520,8 +1521,9 @@ abstract class restore_dbops {
     public static function get_backup_ids_record($restoreid, $itemname, $itemid) {
         $dbrec = self::get_backup_ids_cached($restoreid, $itemname, $itemid);
 
+        // We must test if info is a string, as the cache stores info in object form.
         if ($dbrec && isset($dbrec->info) && is_string($dbrec->info)) {
-            $dbrec->info = unserialize(base64_decode($dbrec->info));
+            $dbrec->info = backup_controller_dbops::decode_backup_temp_info($dbrec->info);
         }
 
         return $dbrec;
@@ -1566,18 +1568,17 @@ abstract class restore_dbops {
         // Get the course context
         $coursectx = context_course::instance($courseid);
         // Get all the mapped roles we have
-        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'role'), '', 'itemid');
+        $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'role'), '', 'itemid, info, newitemid');
         foreach ($rs as $recrole) {
-            // Get the complete temp_ids record
-            $role = (object)self::get_backup_ids_record($restoreid, 'role', $recrole->itemid);
+            $info = backup_controller_dbops::decode_backup_temp_info($recrole->info);
             // If it's one mapped role and we have one name for it
-            if (!empty($role->newitemid) && !empty($role->info['nameincourse'])) {
+            if (!empty($recrole->newitemid) && !empty($info['nameincourse'])) {
                 // If role name doesn't exist, add it
                 $rolename = new stdclass();
-                $rolename->roleid = $role->newitemid;
+                $rolename->roleid = $recrole->newitemid;
                 $rolename->contextid = $coursectx->id;
                 if (!$DB->record_exists('role_names', (array)$rolename)) {
-                    $rolename->name = $role->info['nameincourse'];
+                    $rolename->name = $info['nameincourse'];
                     $DB->insert_record('role_names', $rolename);
                 }
             }
index 55d57ba..e57dc7e 100644 (file)
@@ -147,6 +147,18 @@ class backup_dbops_testcase extends advanced_testcase {
         // Drop and check it doesn't exists anymore
         backup_controller_dbops::drop_backup_ids_temp_table('testingid');
         $this->assertFalse($dbman->table_exists('backup_ids_temp'));
+
+        // Test encoding/decoding of backup_ids_temp,backup_files_temp encode/decode functions.
+        // We need to handle both objects and data elements.
+        $object = new stdClass();
+        $object->item1 = 10;
+        $object->item2 = 'a String';
+        $testarray = array($object, 10, null, 'string', array('a' => 'b', 1 => 1));
+        foreach ($testarray as $item) {
+            $encoded = backup_controller_dbops::encode_backup_temp_info($item);
+            $decoded = backup_controller_dbops::decode_backup_temp_info($encoded);
+            $this->assertEquals($item, $decoded);
+        }
     }
 
     /**
index e90125d..5913324 100644 (file)
@@ -554,7 +554,7 @@ abstract class backup_cron_automated_helper {
             return true;
         }
 
-        $backupword = str_replace(' ', '_', textlib::strtolower(get_string('backupfilename')));
+        $backupword = str_replace(' ', '_', core_text::strtolower(get_string('backupfilename')));
         $backupword = trim(clean_filename($backupword), '_');
 
         if (!file_exists($dir) || !is_dir($dir) || !is_writable($dir)) {
index 3af2839..099a498 100644 (file)
@@ -21,7 +21,8 @@ Feature: Duplicate activities
     And I add a "Database" to section "1" and I fill the form with:
       | Name | Test database name |
       | Description | Test database description |
-    When I click on "Duplicate" "link" in the "#section-1" "css_element"
+    And I click on "Actions" "link" in the "Test database name" activity
+    When I click on "Duplicate" "link" in the "Test database name" activity
     And I press "Continue"
     And I press "Edit the new copy"
     And I fill the moodle form with:
index 58a9b74..4ecf084 100644 (file)
@@ -60,10 +60,11 @@ class OpenBadgesBackpackHandler {
         }
 
         $options = array(
-            'FRESH_CONNECT' => true,
+            'FRESH_CONNECT'  => true,
             'RETURNTRANSFER' => true,
-            'FORBID_REUSE' => true,
-            'HEADER' => 0,
+            'FORBID_REUSE'   => true,
+            'HEADER'         => 0,
+            'HTTPHEADER'     => array('Expect:'),
             'CONNECTTIMEOUT' => 3,
         );
 
index b51d155..9ccafc1 100644 (file)
@@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die();
 global $CFG;
 require_once($CFG->libdir . '/badgeslib.php');
 
-class badges_testcase extends advanced_testcase {
+class core_badgeslib_testcase extends advanced_testcase {
     protected $badgeid;
 
     protected function setUp() {
index 7383658..6dc2f9b 100644 (file)
@@ -49,7 +49,7 @@ class block_activity_modules extends block_list {
             }
         }
 
-        collatorlib::asort($modfullnames);
+        core_collator::asort($modfullnames);
 
         foreach ($modfullnames as $modname => $modfullname) {
             if ($modname === 'resources') {
index 3cac07a..e7eaf88 100644 (file)
@@ -103,10 +103,6 @@ class behat_block_comments extends behat_base {
         $deleteicon = $this->find('css', '.comment-delete a img', $deleteexception, $commentnode);
         $deleteicon->click();
 
-        // Yes confirm.
-        $confirmnode = $this->find('xpath', "//div[@class='comment-delete-confirm']/descendant::a[contains(., '" . get_string('yes') . "')]");
-        $confirmnode->click();
-
         // Wait for the AJAX request.
         $this->getSession()->wait(4 * 1000, false);
     }
index cb8d7d3..3a01716 100644 (file)
@@ -272,7 +272,7 @@ class community_hub_search_form extends moodleform {
             $mform->setDefault('licence', $licence);
 
             $languages = get_string_manager()->get_list_of_languages();
-            collatorlib::asort($languages);
+            core_collator::asort($languages);
             $languages = array_merge(array('all' => get_string('any')), $languages);
             $mform->addElement('select', 'language', get_string('language'), $languages);
 
index b842fb4..be4cd2f 100644 (file)
@@ -210,12 +210,12 @@ if (empty($completions)) {
                 $agg = $info->get_aggregation_method($row['type']);
                 echo '('. html_writer::start_tag('i');
                 if ($agg == COMPLETION_AGGREGATION_ALL) {
-                    echo textlib::strtolower(get_string('all', 'completion'));
+                    echo core_text::strtolower(get_string('all', 'completion'));
                 } else {
-                    echo textlib::strtolower(get_string('any', 'completion'));
+                    echo core_text::strtolower(get_string('any', 'completion'));
                 }
 
-                echo html_writer::end_tag('i') .textlib::strtolower(get_string('required')).')';
+                echo html_writer::end_tag('i') .core_text::strtolower(get_string('required')).')';
                 $agg_type = false;
             }
         }
index 00752d3..95abb63 100644 (file)
@@ -34,5 +34,17 @@ $capabilities = array(
         ),
 
         'clonepermissionsfrom' => 'moodle/my:manageblocks'
+    ),
+
+    'block/course_overview:addinstance' => array(
+        'riskbitmask' => RISK_SPAM | RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_BLOCK,
+        'archetypes' => array(
+            'manager' => CAP_ALLOW
+        ),
+
+        'clonepermissionsfrom' => 'moodle/site:manageblocks'
     )
 );
index b7f0ec6..01a6091 100644 (file)
@@ -27,6 +27,7 @@ $string['alwaysshowall'] = 'Always Show All';
 $string['collapseall'] = 'Collapse All Course Lists';
 $string['configotherexpanded'] = 'If enabled, Other Courses will be expanded by default unless overriden by user preferences.';
 $string['configpreservestates'] = 'If enabled, the collapsed/expanded states set by the user are stored and used on each load.';
+$string['course_overview:addinstance'] = 'Add a new course overview block';
 $string['course_overview:myaddinstance'] = 'Add a new course overview block to My home';
 $string['defaultmaxcourses'] = 'Default maximum courses';
 $string['defaultmaxcoursesdesc'] = 'Maximum courses which should be displayed on course overview block, 0 will show all courses';
index bc159de..71267b6 100644 (file)
 function block_course_overview_get_overviews($courses) {
     $htmlarray = array();
     if ($modules = get_plugin_list_with_function('mod', 'print_overview')) {
-        foreach ($modules as $fname) {
-            $fname($courses,$htmlarray);
+        // Split courses list into batches with no more than MAX_MODINFO_CACHE_SIZE courses in one batch.
+        // Otherwise we exceed the cache limit in get_fast_modinfo() and rebuild it too often.
+        if (defined('MAX_MODINFO_CACHE_SIZE') && MAX_MODINFO_CACHE_SIZE > 0 && count($courses) > MAX_MODINFO_CACHE_SIZE) {
+            $batches = array_chunk($courses, MAX_MODINFO_CACHE_SIZE, true);
+        } else {
+            $batches = array($courses);
+        }
+        foreach ($batches as $courses) {
+            foreach ($modules as $fname) {
+                $fname($courses, $htmlarray);
+            }
         }
     }
     return $htmlarray;
index 3a6878d..8607737 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013073000;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'block_course_overview'; // Full name of the plugin (used for diagnostics)
index 2252e85..9b2613b 100644 (file)
@@ -255,31 +255,31 @@ class block_navigation extends block_base {
     public function trim(navigation_node $node, $mode=1, $long=50, $short=25, $recurse=true) {
         switch ($mode) {
             case self::TRIM_RIGHT :
-                if (textlib::strlen($node->text)>($long+3)) {
+                if (core_text::strlen($node->text)>($long+3)) {
                     // Truncate the text to $long characters
                     $node->text = $this->trim_right($node->text, $long);
                 }
-                if (is_string($node->shorttext) && textlib::strlen($node->shorttext)>($short+3)) {
+                if (is_string($node->shorttext) && core_text::strlen($node->shorttext)>($short+3)) {
                     // Truncate the shorttext
                     $node->shorttext = $this->trim_right($node->shorttext, $short);
                 }
                 break;
             case self::TRIM_LEFT :
-                if (textlib::strlen($node->text)>($long+3)) {
+                if (core_text::strlen($node->text)>($long+3)) {
                     // Truncate the text to $long characters
                     $node->text = $this->trim_left($node->text, $long);
                 }
-                if (is_string($node->shorttext) && textlib::strlen($node->shorttext)>($short+3)) {
+                if (is_string($node->shorttext) && core_text::strlen($node->shorttext)>($short+3)) {
                     // Truncate the shorttext
                     $node->shorttext = $this->trim_left($node->shorttext, $short);
                 }
                 break;
             case self::TRIM_CENTER :
-                if (textlib::strlen($node->text)>($long+3)) {
+                if (core_text::strlen($node->text)>($long+3)) {
                     // Truncate the text to $long characters
                     $node->text = $this->trim_center($node->text, $long);
                 }
-                if (is_string($node->shorttext) && textlib::strlen($node->shorttext)>($short+3)) {
+                if (is_string($node->shorttext) && core_text::strlen($node->shorttext)>($short+3)) {
                     // Truncate the shorttext
                     $node->shorttext = $this->trim_center($node->shorttext, $short);
                 }
@@ -298,7 +298,7 @@ class block_navigation extends block_base {
      * @return string The truncated string
      */
     protected function trim_left($string, $length) {
-        return '...'.textlib::substr($string, textlib::strlen($string)-$length, $length);
+        return '...'.core_text::substr($string, core_text::strlen($string)-$length, $length);
     }
     /**
      * Truncate a string from the right
@@ -307,7 +307,7 @@ class block_navigation extends block_base {
      * @return string The truncated string
      */
     protected function trim_right($string, $length) {
-        return textlib::substr($string, 0, $length).'...';
+        return core_text::substr($string, 0, $length).'...';
     }
     /**
      * Truncate a string in the center
@@ -317,8 +317,8 @@ class block_navigation extends block_base {
      */
     protected function trim_center($string, $length) {
         $trimlength = ceil($length/2);
-        $start = textlib::substr($string, 0, $trimlength);
-        $end = textlib::substr($string, textlib::strlen($string)-$trimlength);
+        $start = core_text::substr($string, 0, $trimlength);
+        $end = core_text::substr($string, core_text::strlen($string)-$trimlength);
         $string = $start.'...'.$end;
         return $string;
     }
index 102a03c..567250b 100644 (file)
@@ -57,12 +57,15 @@ Feature: View my courses in navigation block
     Then I should see "cat1" in the "div.block_navigation .type_system" "css_element"
     And I should see "cat3" in the "div.block_navigation .type_system" "css_element"
     And I should not see "cat2" in the "div.block_navigation .type_system" "css_element"
-    When I expand "cat3" node
-    Then I should see "cat31" in the "div.block_navigation .type_system" "css_element"
+    And I expand "cat3" node
+    And I wait "2" seconds
+    And I should see "cat31" in the "div.block_navigation .type_system" "css_element"
     And I should see "cat33" in the "div.block_navigation .type_system" "css_element"
     And I should not see "cat32" in the "div.block_navigation .type_system" "css_element"
-    When I expand "cat31" node
-    Then I should see "c31" in the "div.block_navigation .type_system" "css_element"
-    When I expand "cat33" node
+    And I expand "cat31" node
+    And I wait "2" seconds
+    And I should see "c31" in the "div.block_navigation .type_system" "css_element"
+    And I expand "cat33" node
+    And I wait "2" seconds
     And I should see "c331" in the "div.block_navigation .type_system" "css_element"
     And I should not see "c332" in the "div.block_navigation .type_system" "css_element"
index 4b861a8..e2ab922 100644 (file)
 
         if(empty($title)){
             // no title present, use portion of description
-            $title = textlib::substr(strip_tags($description), 0, 20) . '...';
+            $title = core_text::substr(strip_tags($description), 0, 20) . '...';
         }else{
             $title = break_up_long_words($title, 30);
         }
      */
     function format_title($title,$max=64) {
 
-        if (textlib::strlen($title) <= $max) {
+        if (core_text::strlen($title) <= $max) {
             return s($title);
         } else {
-            return s(textlib::substr($title,0,$max-3).'...');
+            return s(core_text::substr($title,0,$max-3).'...');
         }
     }
 
index bc4420c..fc150c2 100644 (file)
@@ -59,7 +59,8 @@ class block_site_main_menu extends block_list {
             return $this->content;
         }
 
-/// slow & hacky editing mode
+        // Slow & hacky editing mode.
+        /** @var core_course_renderer $courserenderer */
         $courserenderer = $this->page->get_renderer('core', 'course');
         $ismoving = ismoving($course->id);
         course_create_sections_if_missing($course, 0);
@@ -72,7 +73,7 @@ class block_site_main_menu extends block_list {
             $strcancel= get_string('cancel');
             $stractivityclipboard = $USER->activitycopyname;
         }
-    /// Casting $course->modinfo to string prevents one notice when the field is null
+        // Casting $course->modinfo to string prevents one notice when the field is null.
         $editbuttons = '';
 
         if ($ismoving) {
@@ -90,8 +91,9 @@ class block_site_main_menu extends block_list {
                 if (!$ismoving) {
                     $actions = course_get_cm_edit_actions($mod, -1);
                     $editbuttons = html_writer::tag('div',
-                            $courserenderer->course_section_cm_edit_actions($actions),
-                            array('class' => 'buttons'));
+                        $courserenderer->course_section_cm_edit_actions($actions, $mod, array('donotenhance' => true)),
+                        array('class' => 'buttons')
+                    );
                 } else {
                     $editbuttons = '';
                 }
index 5e394e0..bcab936 100644 (file)
@@ -62,7 +62,8 @@ class block_social_activities extends block_list {
         }
 
 
-/// slow & hacky editing mode
+        // Slow & hacky editing mode.
+        /** @var core_course_renderer $courserenderer */
         $courserenderer = $this->page->get_renderer('core', 'course');
         $ismoving = ismoving($course->id);
         $modinfo = get_fast_modinfo($course);
@@ -74,7 +75,7 @@ class block_social_activities extends block_list {
             $strcancel= get_string('cancel');
             $stractivityclipboard = $USER->activitycopyname;
         }
-    /// Casting $course->modinfo to string prevents one notice when the field is null
+        // Casting $course->modinfo to string prevents one notice when the field is null.
         $editbuttons = '';
 
         if ($ismoving) {
@@ -92,7 +93,7 @@ class block_social_activities extends block_list {
                 if (!$ismoving) {
                     $actions = course_get_cm_edit_actions($mod, -1);
                     $editbuttons = '<br />'.
-                            $courserenderer->course_section_cm_edit_actions($actions);
+                            $courserenderer->course_section_cm_edit_actions($actions, $mod);
                 } else {
                     $editbuttons = '';
                 }
index cfe8771..c7ee5bd 100644 (file)
@@ -205,8 +205,8 @@ function blog_sync_external_entries($externalblog) {
         $newentry->subject = clean_param($entry->get_title(), PARAM_TEXT);
         // Observe 128 max chars in DB
         // TODO: +1 to raise this to 255
-        if (textlib::strlen($newentry->subject) > 128) {
-            $newentry->subject = textlib::substr($newentry->subject, 0, 125) . '...';
+        if (core_text::strlen($newentry->subject) > 128) {
+            $newentry->subject = core_text::substr($newentry->subject, 0, 125) . '...';
         }
         $newentry->summary = $entry->get_description();
 
@@ -241,7 +241,7 @@ function blog_sync_external_entries($externalblog) {
             $oldesttimestamp = $timestamp;
         }
 
-        if (textlib::strlen($newentry->uniquehash) > 255) {
+        if (core_text::strlen($newentry->uniquehash) > 255) {
             // The URL for this item is too long for the field. Rather than add
             // the entry without the link we will skip straight over it.
             // RSS spec says recommended length 500, we use 255.
index a508052..d743f70 100644 (file)
@@ -239,7 +239,6 @@ class blog_entry implements renderable {
     /**
      * Inserts this entry in the database. Access control checks must be done by calling code.
      * TODO Set the publishstate correctly
-     * @param mform $form Used for attachments
      * @return void
      */
     public function add() {
@@ -259,11 +258,17 @@ class blog_entry implements renderable {
 
         if (!empty($CFG->useblogassociations)) {
             $this->add_associations();
-            add_to_log(SITEID, 'blog', 'add', 'index.php?userid='.$this->userid.'&entryid='.$this->id, $this->subject);
         }
 
         tag_set('post', $this->id, $this->tags);
-        events_trigger('blog_entry_added', $this);
+
+        // Trigger an event for the new entry.
+        $event = \core\event\blog_entry_created::create(array('objectid' => $this->id,
+                                                            'userid'   => $this->userid,
+                                                            'other'    => array ("subject" => $this->subject)
+                                                      ));
+        $event->set_custom_data($this);
+        $event->trigger();
     }
 
     /**
@@ -311,11 +316,18 @@ class blog_entry implements renderable {
         $this->delete_attachments();
         $this->remove_associations();
 
+        // Get record to pass onto the event.
+        $record = $DB->get_record('post', array('id' => $this->id));
         $DB->delete_records('post', array('id' => $this->id));
         tag_set('post', $this->id, array());
 
-        add_to_log(SITEID, 'blog', 'delete', 'index.php?userid='. $this->userid, 'deleted blog entry with entry id# '. $this->id);
-        events_trigger('blog_entry_deleted', $this);
+        $event = \core\event\blog_entry_deleted::create(array('objectid' => $this->id,
+                                                            'userid'   => $this->userid,
+                                                            'other'   => array("record" => (array)$record)
+                                                      ));
+        $event->add_record_snapshot("post", $record);
+        $event->set_custom_data($this);
+        $event->trigger();
     }
 
     /**
index 7828194..1527a3c 100644 (file)
@@ -55,7 +55,6 @@ Feature: Comment on a blog entry
     And I follow "Save comment"
     And I wait "4" seconds
     When I click on ".comment-delete a" "css_element"
-    And I click on "Yes" "link"
     And I wait "4" seconds
     Then I should not see "$My own >nasty< \"string\"!"
     And I follow "Blog post from user 1"
index f385eb3..60e5858 100644 (file)
@@ -31,7 +31,7 @@ require_once($CFG->dirroot . '/blog/lib.php');
 /**
  * Test functions that rely on the DB tables
  */
-class bloglib_testcase extends advanced_testcase {
+class core_bloglib_testcase extends advanced_testcase {
 
     private $courseid; // To store important ids to be used in tests
     private $cmid;
@@ -150,4 +150,49 @@ class bloglib_testcase extends advanced_testcase {
         $blog_headers = blog_get_headers($this->courseid);
         $this->assertNotEquals($blog_headers['heading'], '');
     }
+
+    /**
+     * Test various blog related events.
+     */
+    public function test_blog_entry_events() {
+        global $USER, $DB;
+
+        $this->setAdminUser();
+        $this->resetAfterTest();
+
+        // Create a blog entry.
+        $blog = new blog_entry();
+        $blog->summary = "This is summary of blog";
+        $blog->subject = "Subject of blog";
+        $states = blog_entry::get_applicable_publish_states();
+        $blog->publishstate = reset($states);
+        $sink = $this->redirectEvents();
+        $blog->add();
+        $events = $sink->get_events();
+        $event = reset($events);
+        $sitecontext = context_system::instance();
+
+        // Validate event data.
+        $this->assertInstanceOf('\core\event\blog_entry_created', $event);
+        $this->assertEquals($sitecontext->id, $event->contextid);
+        $this->assertEquals($blog->id, $event->objectid);
+        $this->assertEquals($USER->id, $event->userid);
+        $this->assertEquals("post", $event->objecttable);
+
+        // Delete a blog entry.
+        $record = $DB->get_record('post', array('id' => $blog->id));
+        $blog->delete();
+        $events = $sink->get_events();
+        $event = array_pop($events);
+
+        // Validate event data.
+        $this->assertInstanceOf('\core\event\blog_entry_deleted', $event);
+        $this->assertEquals(context_system::instance()->id, $event->contextid);
+        $this->assertEquals($blog->id, $event->objectid);
+        $this->assertEquals($USER->id, $event->userid);
+        $this->assertEquals("post", $event->objecttable);
+        $this->assertEquals($record, $event->get_record_snapshot("post", $blog->id));
+        $this->assertSame('blog_entry_deleted', $event->get_legacy_eventname());
+
+    }
 }
index 71fce81..c72c52c 100644 (file)
@@ -149,7 +149,7 @@ class cache_config_writer extends cache_config {
         }
         $class = 'cachestore_'.$plugin;
         if (!class_exists($class)) {
-            $plugins = get_plugin_list_with_file('cachestore', 'lib.php');
+            $plugins = core_component::get_plugin_list_with_file('cachestore', 'lib.php');
             if (!array_key_exists($plugin, $plugins)) {
                 throw new cache_exception('Invalid plugin name specified. The plugin does not exist or is not valid.');
             }
@@ -204,7 +204,7 @@ class cache_config_writer extends cache_config {
         }
         $class = 'cachelock_'.$plugin;
         if (!class_exists($class)) {
-            $plugins = get_plugin_list_with_file('cachelock', 'lib.php');
+            $plugins = core_component::get_plugin_list_with_file('cachelock', 'lib.php');
             if (!array_key_exists($plugin, $plugins)) {
                 throw new cache_exception('Invalid lock name specified. The plugin does not exist or is not valid.');
             }
@@ -315,7 +315,7 @@ class cache_config_writer extends cache_config {
         if (!array_key_exists($name, $this->configstores)) {
             throw new cache_exception('The requested instance does not exist.');
         }
-        $plugins = get_plugin_list_with_file('cachestore', 'lib.php');
+        $plugins = core_component::get_plugin_list_with_file('cachestore', 'lib.php');
         if (!array_key_exists($plugin, $plugins)) {
             throw new cache_exception('Invalid plugin name specified. The plugin either does not exist or is not valid.');
         }
@@ -523,7 +523,7 @@ class cache_config_writer extends cache_config {
         if (!$coreonly) {
             $plugintypes = core_component::get_plugin_types();
             foreach ($plugintypes as $type => $location) {
-                $plugins = get_plugin_list_with_file($type, 'db/caches.php');
+                $plugins = core_component::get_plugin_list_with_file($type, 'db/caches.php');
                 foreach ($plugins as $plugin => $filepath) {
                     $component = clean_param($type.'_'.$plugin, PARAM_COMPONENT); // Standardised plugin name.
                     $files[$component] = $filepath;
@@ -738,7 +738,7 @@ abstract class cache_administration_helper extends cache_helper {
      */
     public static function get_store_plugin_summaries() {
         $return = array();
-        $plugins = get_plugin_list_with_file('cachestore', 'lib.php', true);
+        $plugins = core_component::get_plugin_list_with_file('cachestore', 'lib.php', true);
         foreach ($plugins as $plugin => $path) {
             $class = 'cachestore_'.$plugin;
             $return[$plugin] = array(
index 96d11b2..adc1a9b 100644 (file)
@@ -266,7 +266,7 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
         $this->definition = $definition;
         $hash = preg_replace('#[^a-zA-Z0-9]+#', '_', $this->definition->get_id());
         $this->path = $this->filestorepath.'/'.$hash;
-        make_writable_directory($this->path);
+        make_writable_directory($this->path, false);
         if ($this->prescan && $definition->get_mode() !== self::MODE_REQUEST) {
             $this->prescan = false;
         }
@@ -314,11 +314,13 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
             return $this->path . '/' . $key . '.cache';
         } else {
             // We are using a single subdirectory to achieve 1 level.
-            $subdir = substr($key, 0, 3);
+           // We suffix the subdir so it does not clash with any windows
+           // reserved filenames like 'con'.
+            $subdir = substr($key, 0, 3) . '-cache';
             $dir = $this->path . '/' . $subdir;
             if ($create) {
                 // Create the directory. This function does it recursivily!
-                make_writable_directory($dir);
+                make_writable_directory($dir, false);
             }
             return $dir . '/' . $key . '.cache';
         }
index 301bee1..4592e41 100644 (file)
@@ -57,7 +57,7 @@ $struntestable = new lang_string('untestable', 'cache');
 $strtested = new lang_string('tested', 'cache');
 $strnotready = new lang_string('storenotready', 'cache');
 
-foreach (get_plugin_list_with_file('cachestore', 'lib.php', true) as $plugin => $path) {
+foreach (core_component::get_plugin_list_with_file('cachestore', 'lib.php', true) as $plugin => $path) {
 
     $class = 'cachestore_'.$plugin;
     $plugin = get_string('pluginname', 'cachestore_'.$plugin);
diff --git a/cache/tests/administration_helper_test.php b/cache/tests/administration_helper_test.php
new file mode 100644 (file)
index 0000000..6a1630d
--- /dev/null
@@ -0,0 +1,236 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * PHPunit tests for the cache API and in particular things in locallib.php
+ *
+ * This file is part of Moodle's cache API, affectionately called MUC.
+ * It contains the components that are requried in order to use caching.
+ *
+ * @package    core
+ * @category   cache
+ * @copyright  2012 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// Include the necessary evils.
+global $CFG;
+require_once($CFG->dirroot.'/cache/locallib.php');
+require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
+
+
+/**
+ * PHPunit tests for the cache API and in particular the cache_administration_helper
+ *
+ * @copyright  2012 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_cache_administration_helper_testcase extends advanced_testcase {
+
+    /**
+     * Set things back to the default before each test.
+     */
+    public function setUp() {
+        parent::setUp();
+        cache_factory::reset();
+        cache_config_phpunittest::create_default_configuration();
+    }
+
+    /**
+     * Final task is to reset the cache system
+     */
+    public static function tearDownAfterClass() {
+        parent::tearDownAfterClass();
+        cache_factory::reset();
+    }
+
+    /**
+     * Test the numerous summaries the helper can produce.
+     */
+    public function test_get_summaries() {
+        // First the preparation.
+        $config = cache_config_writer::instance();
+        $this->assertTrue($config->add_store_instance('summariesstore', 'file'));
+        $config->set_definition_mappings('core/eventinvalidation', array('summariesstore'));
+        $this->assertTrue($config->set_mode_mappings(array(
+            cache_store::MODE_APPLICATION => array('summariesstore'),
+            cache_store::MODE_SESSION => array('default_session'),
+            cache_store::MODE_REQUEST => array('default_request'),
+        )));
+
+        $storesummaries = cache_administration_helper::get_store_instance_summaries();
+        $this->assertInternalType('array', $storesummaries);
+        $this->assertArrayHasKey('summariesstore', $storesummaries);
+        $summary = $storesummaries['summariesstore'];
+        // Check the keys
+        $this->assertArrayHasKey('name', $summary);
+        $this->assertArrayHasKey('plugin', $summary);
+        $this->assertArrayHasKey('default', $summary);
+        $this->assertArrayHasKey('isready', $summary);
+        $this->assertArrayHasKey('requirementsmet', $summary);
+        $this->assertArrayHasKey('mappings', $summary);
+        $this->assertArrayHasKey('modes', $summary);
+        $this->assertArrayHasKey('supports', $summary);
+        // Check the important/known values
+        $this->assertEquals('summariesstore', $summary['name']);
+        $this->assertEquals('file', $summary['plugin']);
+        $this->assertEquals(0, $summary['default']);
+        $this->assertEquals(1, $summary['isready']);
+        $this->assertEquals(1, $summary['requirementsmet']);
+        $this->assertEquals(1, $summary['mappings']);
+
+        $definitionsummaries = cache_administration_helper::get_definition_summaries();
+        $this->assertInternalType('array', $definitionsummaries);
+        $this->assertArrayHasKey('core/eventinvalidation', $definitionsummaries);
+        $summary = $definitionsummaries['core/eventinvalidation'];
+        // Check the keys
+        $this->assertArrayHasKey('id', $summary);
+        $this->assertArrayHasKey('name', $summary);
+        $this->assertArrayHasKey('mode', $summary);
+        $this->assertArrayHasKey('component', $summary);
+        $this->assertArrayHasKey('area', $summary);
+        $this->assertArrayHasKey('mappings', $summary);
+        // Check the important/known values
+        $this->assertEquals('core/eventinvalidation', $summary['id']);
+        $this->assertInstanceOf('lang_string', $summary['name']);
+        $this->assertEquals(cache_store::MODE_APPLICATION, $summary['mode']);
+        $this->assertEquals('core', $summary['component']);
+        $this->assertEquals('eventinvalidation', $summary['area']);
+        $this->assertInternalType('array', $summary['mappings']);
+        $this->assertContains('summariesstore', $summary['mappings']);
+
+        $pluginsummaries = cache_administration_helper::get_store_plugin_summaries();
+        $this->assertInternalType('array', $pluginsummaries);
+        $this->assertArrayHasKey('file', $pluginsummaries);
+        $summary = $pluginsummaries['file'];
+        // Check the keys
+        $this->assertArrayHasKey('name', $summary);
+        $this->assertArrayHasKey('requirementsmet', $summary);
+        $this->assertArrayHasKey('instances', $summary);
+        $this->assertArrayHasKey('modes', $summary);
+        $this->assertArrayHasKey('supports', $summary);
+        $this->assertArrayHasKey('canaddinstance', $summary);
+
+        $locksummaries = cache_administration_helper::get_lock_summaries();
+        $this->assertInternalType('array', $locksummaries);
+        $this->assertTrue(count($locksummaries) > 0);
+
+        $mappings = cache_administration_helper::get_default_mode_stores();
+        $this->assertInternalType('array', $mappings);
+        $this->assertCount(3, $mappings);
+        $this->assertArrayHasKey(cache_store::MODE_APPLICATION, $mappings);
+        $this->assertInternalType('array', $mappings[cache_store::MODE_APPLICATION]);
+        $this->assertContains('summariesstore', $mappings[cache_store::MODE_APPLICATION]);
+
+        $potentials = cache_administration_helper::get_definition_store_options('core', 'eventinvalidation');
+        $this->assertInternalType('array', $potentials); // Currently used, suitable, default
+        $this->assertCount(3, $potentials);
+        $this->assertArrayHasKey('summariesstore', $potentials[0]);
+        $this->assertArrayHasKey('summariesstore', $potentials[1]);
+        $this->assertArrayHasKey('default_application', $potentials[1]);
+    }
+
+    /**
+     * Test instantiating an add store form.
+     */
+    public function test_get_add_store_form() {
+        $form = cache_administration_helper::get_add_store_form('file');
+        $this->assertInstanceOf('moodleform', $form);
+
+        try {
+            $form = cache_administration_helper::get_add_store_form('somethingstupid');
+            $this->fail('You should not be able to create an add form for a store plugin that does not exist.');
+        } catch (moodle_exception $e) {
+            $this->assertInstanceOf('coding_exception', $e, 'Needs to be: ' .get_class($e)." ::: ".$e->getMessage());
+        }
+    }
+
+    /**
+     * Test instantiating a form to edit a store instance.
+     */
+    public function test_get_edit_store_form() {
+        $config = cache_config_writer::instance();
+        $this->assertTrue($config->add_store_instance('summariesstore', 'file'));
+
+        $form = cache_administration_helper::get_edit_store_form('file', 'summariesstore');
+        $this->assertInstanceOf('moodleform', $form);
+
+        try {
+            $form = cache_administration_helper::get_edit_store_form('somethingstupid', 'moron');
+            $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
+        } catch (moodle_exception $e) {
+            $this->assertInstanceOf('coding_exception', $e);
+        }
+
+        try {
+            $form = cache_administration_helper::get_edit_store_form('file', 'blisters');
+            $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
+        } catch (moodle_exception $e) {
+            $this->assertInstanceOf('coding_exception', $e);
+        }
+    }
+
+    /**
+     * Test the hash_key functionality.
+     */
+    public function test_hash_key() {
+        global $CFG;
+
+        $currentdebugging = $CFG->debug;
+
+        $CFG->debug = E_ALL;
+
+        // First with simplekeys
+        $instance = cache_config_phpunittest::instance(true);
+        $instance->phpunit_add_definition('phpunit/hashtest', array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'hashtest',
+            'simplekeys' => true
+        ));
+        $factory = cache_factory::instance();
+        $definition = $factory->create_definition('phpunit', 'hashtest');
+
+        $result = cache_helper::hash_key('test', $definition);
+        $this->assertEquals('test-'.$definition->generate_single_key_prefix(), $result);
+
+        try {
+            cache_helper::hash_key('test/test', $definition);
+            $this->fail('Invalid key was allowed, you should see this.');
+        } catch (coding_exception $e) {
+            $this->assertEquals('test/test', $e->debuginfo);
+        }
+
+        // Second without simple keys
+        $instance->phpunit_add_definition('phpunit/hashtest2', array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'hashtest2',
+            'simplekeys' => false
+        ));
+        $definition = $factory->create_definition('phpunit', 'hashtest2');
+
+        $result = cache_helper::hash_key('test', $definition);
+        $this->assertEquals(sha1($definition->generate_single_key_prefix().'-test'), $result);
+
+        $result = cache_helper::hash_key('test/test', $definition);
+        $this->assertEquals(sha1($definition->generate_single_key_prefix().'-test/test'), $result);
+
+        $CFG->debug = $currentdebugging;
+    }
+}
index 5121875..e7f4cdc 100644 (file)
@@ -39,7 +39,7 @@ require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
  * @copyright  2012 Sam Hemelryk
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class cache_phpunit_tests extends advanced_testcase {
+class core_cache_testcase extends advanced_testcase {
 
     /**
      * Set things back to the default before each test.
@@ -119,6 +119,23 @@ class cache_phpunit_tests extends advanced_testcase {
         }
     }
 
+    /**
+     * Tests for cache keys that would break on windows.
+     */
+    public function test_windows_nasty_keys() {
+        $instance = cache_config_phpunittest::instance();
+        $instance->phpunit_add_definition('phpunit/windowskeytest', array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'windowskeytest',
+            'simplekeys' => true,
+            'simpledata' => true
+        ));
+        $cache = cache::make('phpunit', 'windowskeytest');
+        $this->assertTrue($cache->set('contest', 'test data 1'));
+        $this->assertEquals('test data 1', $cache->get('contest'));
+    }
+
     /**
      * Tests the default application cache
      */
@@ -191,9 +208,9 @@ class cache_phpunit_tests extends advanced_testcase {
      * @param cache_loader $cache
      */
     protected function run_on_cache(cache_loader $cache) {
-        $key = 'testkey';
+        $key = 'contestkey';
         $datascalars = array('test data', null);
-        $dataarray = array('test' => 'data', 'part' => 'two');
+        $dataarray = array('contest' => 'data', 'part' => 'two');
         $dataobject = (object)$dataarray;
 
         foreach ($datascalars as $datascalar) {
@@ -850,7 +867,7 @@ class cache_phpunit_tests extends advanced_testcase {
         // OK data added, data invalidated, and invalidation time has been set.
         // Now we need to manually add back the data and adjust the invalidation time.
         $hash = md5(cache_store::MODE_APPLICATION.'/phpunit/eventinvalidationtest/'.$CFG->wwwroot.'phpunit');
-        $timefile = $CFG->dataroot."/cache/cachestore_file/default_application/phpunit_eventinvalidationtest/las/lastinvalidation-$hash.cache";
+        $timefile = $CFG->dataroot."/cache/cachestore_file/default_application/phpunit_eventinvalidationtest/las-cache/lastinvalidation-$hash.cache";
         // Make sure the file is correct.
         $this->assertTrue(file_exists($timefile));
         $timecont = serialize(cache::now() - 60); // Back 60sec in the past to force it to re-invalidate.
@@ -858,7 +875,7 @@ class cache_phpunit_tests extends advanced_testcase {
         file_put_contents($timefile, $timecont);
         $this->assertTrue(file_exists($timefile));
 
-        $datafile = $CFG->dataroot."/cache/cachestore_file/default_application/phpunit_eventinvalidationtest/tes/testkey1-$hash.cache";
+        $datafile = $CFG->dataroot."/cache/cachestore_file/default_application/phpunit_eventinvalidationtest/tes-cache/testkey1-$hash.cache";
         $datacont = serialize("test data 1");
         make_writable_directory(dirname($datafile));
         file_put_contents($datafile, $datacont);
similarity index 57%
rename from cache/tests/locallib_test.php
rename to cache/tests/config_writer_test.php
index 56397f2..f49f65e 100644 (file)
@@ -39,7 +39,7 @@ require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
  * @copyright  2012 Sam Hemelryk
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class cache_config_writer_phpunit_tests extends advanced_testcase {
+class core_cache_config_writer_testcase extends advanced_testcase {
 
     /**
      * Set things back to the default before each test.
@@ -288,204 +288,3 @@ class cache_config_writer_phpunit_tests extends advanced_testcase {
         }
     }
 }
-
-/**
- * PHPunit tests for the cache API and in particular the cache_administration_helper
- *
- * @copyright  2012 Sam Hemelryk
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class cache_administration_helper_phpunit_tests extends advanced_testcase {
-
-    /**
-     * Set things back to the default before each test.
-     */
-    public function setUp() {
-        parent::setUp();
-        cache_factory::reset();
-        cache_config_phpunittest::create_default_configuration();
-    }
-
-    /**
-     * Final task is to reset the cache system
-     */
-    public static function tearDownAfterClass() {
-        parent::tearDownAfterClass();
-        cache_factory::reset();
-    }
-
-    /**
-     * Test the numerous summaries the helper can produce.
-     */
-    public function test_get_summaries() {
-        // First the preparation.
-        $config = cache_config_writer::instance();
-        $this->assertTrue($config->add_store_instance('summariesstore', 'file'));
-        $config->set_definition_mappings('core/eventinvalidation', array('summariesstore'));
-        $this->assertTrue($config->set_mode_mappings(array(
-            cache_store::MODE_APPLICATION => array('summariesstore'),
-            cache_store::MODE_SESSION => array('default_session'),
-            cache_store::MODE_REQUEST => array('default_request'),
-        )));
-
-        $storesummaries = cache_administration_helper::get_store_instance_summaries();
-        $this->assertInternalType('array', $storesummaries);
-        $this->assertArrayHasKey('summariesstore', $storesummaries);
-        $summary = $storesummaries['summariesstore'];
-        // Check the keys
-        $this->assertArrayHasKey('name', $summary);
-        $this->assertArrayHasKey('plugin', $summary);
-        $this->assertArrayHasKey('default', $summary);
-        $this->assertArrayHasKey('isready', $summary);
-        $this->assertArrayHasKey('requirementsmet', $summary);
-        $this->assertArrayHasKey('mappings', $summary);
-        $this->assertArrayHasKey('modes', $summary);
-        $this->assertArrayHasKey('supports', $summary);
-        // Check the important/known values
-        $this->assertEquals('summariesstore', $summary['name']);
-        $this->assertEquals('file', $summary['plugin']);
-        $this->assertEquals(0, $summary['default']);
-        $this->assertEquals(1, $summary['isready']);
-        $this->assertEquals(1, $summary['requirementsmet']);
-        $this->assertEquals(1, $summary['mappings']);
-
-        $definitionsummaries = cache_administration_helper::get_definition_summaries();
-        $this->assertInternalType('array', $definitionsummaries);
-        $this->assertArrayHasKey('core/eventinvalidation', $definitionsummaries);
-        $summary = $definitionsummaries['core/eventinvalidation'];
-        // Check the keys
-        $this->assertArrayHasKey('id', $summary);
-        $this->assertArrayHasKey('name', $summary);
-        $this->assertArrayHasKey('mode', $summary);
-        $this->assertArrayHasKey('component', $summary);
-        $this->assertArrayHasKey('area', $summary);
-        $this->assertArrayHasKey('mappings', $summary);
-        // Check the important/known values
-        $this->assertEquals('core/eventinvalidation', $summary['id']);
-        $this->assertInstanceOf('lang_string', $summary['name']);
-        $this->assertEquals(cache_store::MODE_APPLICATION, $summary['mode']);
-        $this->assertEquals('core', $summary['component']);
-        $this->assertEquals('eventinvalidation', $summary['area']);
-        $this->assertInternalType('array', $summary['mappings']);
-        $this->assertContains('summariesstore', $summary['mappings']);
-
-        $pluginsummaries = cache_administration_helper::get_store_plugin_summaries();
-        $this->assertInternalType('array', $pluginsummaries);
-        $this->assertArrayHasKey('file', $pluginsummaries);
-        $summary = $pluginsummaries['file'];
-        // Check the keys
-        $this->assertArrayHasKey('name', $summary);
-        $this->assertArrayHasKey('requirementsmet', $summary);
-        $this->assertArrayHasKey('instances', $summary);
-        $this->assertArrayHasKey('modes', $summary);
-        $this->assertArrayHasKey('supports', $summary);
-        $this->assertArrayHasKey('canaddinstance', $summary);
-
-        $locksummaries = cache_administration_helper::get_lock_summaries();
-        $this->assertInternalType('array', $locksummaries);
-        $this->assertTrue(count($locksummaries) > 0);
-
-        $mappings = cache_administration_helper::get_default_mode_stores();
-        $this->assertInternalType('array', $mappings);
-        $this->assertCount(3, $mappings);
-        $this->assertArrayHasKey(cache_store::MODE_APPLICATION, $mappings);
-        $this->assertInternalType('array', $mappings[cache_store::MODE_APPLICATION]);
-        $this->assertContains('summariesstore', $mappings[cache_store::MODE_APPLICATION]);
-
-        $potentials = cache_administration_helper::get_definition_store_options('core', 'eventinvalidation');
-        $this->assertInternalType('array', $potentials); // Currently used, suitable, default
-        $this->assertCount(3, $potentials);
-        $this->assertArrayHasKey('summariesstore', $potentials[0]);
-        $this->assertArrayHasKey('summariesstore', $potentials[1]);
-        $this->assertArrayHasKey('default_application', $potentials[1]);
-    }
-
-    /**
-     * Test instantiating an add store form.
-     */
-    public function test_get_add_store_form() {
-        $form = cache_administration_helper::get_add_store_form('file');
-        $this->assertInstanceOf('moodleform', $form);
-
-        try {
-            $form = cache_administration_helper::get_add_store_form('somethingstupid');
-            $this->fail('You should not be able to create an add form for a store plugin that does not exist.');
-        } catch (moodle_exception $e) {
-            $this->assertInstanceOf('coding_exception', $e, 'Needs to be: ' .get_class($e)." ::: ".$e->getMessage());
-        }
-    }
-
-    /**
-     * Test instantiating a form to edit a store instance.
-     */
-    public function test_get_edit_store_form() {
-        $config = cache_config_writer::instance();
-        $this->assertTrue($config->add_store_instance('summariesstore', 'file'));
-
-        $form = cache_administration_helper::get_edit_store_form('file', 'summariesstore');
-        $this->assertInstanceOf('moodleform', $form);
-
-        try {
-            $form = cache_administration_helper::get_edit_store_form('somethingstupid', 'moron');
-            $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
-        } catch (moodle_exception $e) {
-            $this->assertInstanceOf('coding_exception', $e);
-        }
-
-        try {
-            $form = cache_administration_helper::get_edit_store_form('file', 'blisters');
-            $this->fail('You should not be able to create an edit form for a store plugin that does not exist.');
-        } catch (moodle_exception $e) {
-            $this->assertInstanceOf('coding_exception', $e);
-        }
-    }
-
-    /**
-     * Test the hash_key functionality.
-     */
-    public function test_hash_key() {
-        global $CFG;
-
-        $currentdebugging = $CFG->debug;
-
-        $CFG->debug = E_ALL;
-
-        // First with simplekeys
-        $instance = cache_config_phpunittest::instance(true);
-        $instance->phpunit_add_definition('phpunit/hashtest', array(
-            'mode' => cache_store::MODE_APPLICATION,
-            'component' => 'phpunit',
-            'area' => 'hashtest',
-            'simplekeys' => true
-        ));
-        $factory = cache_factory::instance();
-        $definition = $factory->create_definition('phpunit', 'hashtest');
-
-        $result = cache_helper::hash_key('test', $definition);
-        $this->assertEquals('test-'.$definition->generate_single_key_prefix(), $result);
-
-        try {
-            cache_helper::hash_key('test/test', $definition);
-            $this->fail('Invalid key was allowed, you should see this.');
-        } catch (coding_exception $e) {
-            $this->assertEquals('test/test', $e->debuginfo);
-        }
-
-        // Second without simple keys
-        $instance->phpunit_add_definition('phpunit/hashtest2', array(
-            'mode' => cache_store::MODE_APPLICATION,
-            'component' => 'phpunit',
-            'area' => 'hashtest2',
-            'simplekeys' => false
-        ));
-        $definition = $factory->create_definition('phpunit', 'hashtest2');
-
-        $result = cache_helper::hash_key('test', $definition);
-        $this->assertEquals(sha1($definition->generate_single_key_prefix().'-test'), $result);
-
-        $result = cache_helper::hash_key('test/test', $definition);
-        $this->assertEquals(sha1($definition->generate_single_key_prefix().'-test/test'), $result);
-
-        $CFG->debug = $currentdebugging;
-    }
-}
index e38538e..44bb9e7 100644 (file)
@@ -38,7 +38,7 @@ require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.5
  */
-class core_calendar_external_testcase extends externallib_advanced_testcase {
+class core_calendar_externallib_testcase extends externallib_advanced_testcase {
 
     /**
      * Tests set up
index db0b2f0..e6446e7 100644 (file)
@@ -37,7 +37,7 @@ require_once("$CFG->dirroot/cohort/lib.php");
  * @copyright  2012 Petr Skoda {@link http://skodak.org}
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class cohort_testcase extends advanced_testcase {
+class core_cohort_cohortlib_testcase extends advanced_testcase {
 
     public function test_cohort_add_cohort() {
         global $DB;
index c8137fb..8f7f4ba 100644 (file)
@@ -30,7 +30,7 @@ global $CFG;
 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
 require_once($CFG->dirroot . '/cohort/externallib.php');
 
-class core_cohort_external_testcase extends externallib_advanced_testcase {
+class core_cohort_externallib_testcase extends externallib_advanced_testcase {
 
     /**
      * Test create_cohorts
index 544d82f..d1cf768 100644 (file)
@@ -59,11 +59,6 @@ M.core_comment = {
                     }, this);
                 }
                 scope.toggle_textarea(false);
-                CommentHelper.confirmoverlay = new Y.Overlay({
-bodyContent: '<div class="comment-delete-confirm"><a href="#" id="confirmdelete-'+this.client_id+'">'+M.str.moodle.yes+'</a> <a href="#" id="canceldelete-'+this.client_id+'">'+M.str.moodle.no+'</a></div>',
-                                        visible: false
-                                        });
-                CommentHelper.confirmoverlay.render(document.body);
             },
             post: function() {
                 var ta = Y.one('#dlg-content-'+this.client_id);
@@ -238,7 +233,6 @@ bodyContent: '<div class="comment-delete-confirm"><a href="#" id="confirmdelete-
             dodelete: function(id) { // note: delete is a reserved word in javascript, chrome and safary do not like it at all here!
                 var scope = this;
                 var params = {'commentid': id};
-                scope.cancel_delete();
                 function remove_dom(type, anim, cmt) {
                     cmt.remove();
                 }
@@ -294,37 +288,23 @@ bodyContent: '<div class="comment-delete-confirm"><a href="#" id="confirmdelete-
                         if (commentid[1]) {
                             Y.Event.purgeElement('#'+theid, false, 'click');
                         }
-                        node.on('click', function(e, node) {
+                        node.on('click', function(e) {
                             e.preventDefault();
-                            var width = CommentHelper.confirmoverlay.bodyNode.getStyle('width');
-                            var re = new RegExp("(\\d+).*", "i");
-                            var result = width.match(re);
-                            if (result[1]) {
-                                width = Number(result[1]);
-                            } else {
-                                width = 0;
+                            if (commentid[1]) {
+                                scope.dodelete(commentid[1]);
                             }
-                            //CommentHelper.confirmoverlay.set('xy', [e.pageX-(width/2), e.pageY]);
-                            CommentHelper.confirmoverlay.set('xy', [e.pageX-width-5, e.pageY]);
-                            CommentHelper.confirmoverlay.set('visible', true);
-                            Y.one('#canceldelete-'+scope.client_id).on('click', function(e) {
-                                e.preventDefault();
-                                scope.cancel_delete();
-                                });
-                            Y.Event.purgeElement('#confirmdelete-'+scope.client_id, false, 'click');
-                            Y.one('#confirmdelete-'+scope.client_id).on('click', function(e) {
-                                e.preventDefault();
-                                if (commentid[1]) {
-                                    scope.dodelete(commentid[1]);
-                                }
-                            });
-                        }, scope, node);
+                        });
+                        // Also handle space/enter key.
+                        node.on('key', function(e) {
+                            e.preventDefault();
+                            if (commentid[1]) {
+                                scope.dodelete(commentid[1]);
+                            }
+                        }, '13,32');
+                        // 13 and 32 are the keycodes for space and enter.
                     }
                 );
             },
-            cancel_delete: function() {
-                CommentHelper.confirmoverlay.set('visible', false);
-            },
             register_pagination: function() {
                 var scope = this;
                 // page buttons
@@ -374,7 +354,7 @@ bodyContent: '<div class="comment-delete-confirm"><a href="#" id="confirmdelete-
                 if (ta) {
                     //toggle_textarea.apply(ta, [false]);
                     //// reset textarea size
-                    ta.on('click', function() {
+                    ta.on('focus', function() {
                         this.toggle_textarea(true);
                     }, this);
                     //ta.onkeypress = function() {
index 2022649..8c3b733 100644 (file)
@@ -365,25 +365,6 @@ $CFG->admin = 'admin';
 // Locking resolves race conditions and is strongly recommended for production servers.
 //     $CFG->preventfilelocking = false;
 //
-// If $CFG->langstringcache is enabled (which should always be in production
-// environment), Moodle keeps aggregated strings in its own internal format
-// optimised for performance. By default, this on-disk cache is created in
-// $CFG->cachedir/lang. In cluster environment, you may wish to specify
-// an alternative location of this cache so that each web server in the cluster
-// uses its own local cache and does not need to access the shared dataroot.
-// Make sure that the web server process has write permission to this location
-// and that it has permission to remove the folder, too (so that the cache can
-// be pruned).
-//
-//     $CFG->langcacheroot = '/var/www/moodle/htdocs/altcache/lang';
-//
-// If $CFG->langcache is enabled (which should always be in production
-// environment), Moodle stores the list of available languages in a cache file.
-// By default, the file $CFG->dataroot/languages is used. You may wish to
-// specify an alternative location of this cache file.
-//
-//     $CFG->langmenucachefile = '/var/www/moodle/htdocs/altcache/languages';
-//
 // Site default language can be set via standard administration interface. If you
 // want to have initial error messages for eventual database connection problems
 // localized too, you have to set your language code here.
@@ -488,7 +469,7 @@ $CFG->admin = 'admin';
 // Prevent JS caching
 // $CFG->jsrev = -1; // NOT FOR PRODUCTION SERVERS!
 //
-// Prevent core_string_manager on-disk cache
+// Prevent core_string_manager application caching
 // $CFG->langstringcache = false; // NOT FOR PRODUCTION SERVERS!
 //
 // When working with production data on test servers, no emails or other messages
index b1dbc63..118647c 100644 (file)
@@ -1053,8 +1053,12 @@ M.course_dndupload = {
      * @param sectionnumber the number of the selected course section
      */
     add_editing: function(elementid) {
+        var node = Y.one('#' + elementid);
         YUI().use('moodle-course-coursebase', function(Y) {
-            M.course.coursebase.invoke_function('setup_for_resource', '#' + elementid);
+            M.course.register_new_module(node);
         });
+        if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {
+            M.core.actionmenu.newDOMNode(node);
+        }
     }
 };
index a1b8d02..917d670 100644 (file)
@@ -588,9 +588,9 @@ class dndupload_ajax_processor {
      * @return string the display name to use
      */
     protected function display_name_from_file($filename) {
-        $pos = textlib::strrpos($filename, '.');
+        $pos = core_text::strrpos($filename, '.');
         if ($pos) { // Want to skip if $pos === 0 OR $pos === false.
-            $filename = textlib::substr($filename, 0, $pos);
+            $filename = core_text::substr($filename, 0, $pos);
         }
         return str_replace('_', ' ', $filename);
     }
@@ -744,11 +744,11 @@ class dndupload_ajax_processor {
         $resp->content = $mod->get_content();
         $resp->elementid = 'module-'.$mod->id;
         $actions = course_get_cm_edit_actions($mod, 0, $mod->sectionnum);
-        $resp->commands = ' '. $courserenderer->course_section_cm_edit_actions($actions);
+        $resp->commands = ' '. $courserenderer->course_section_cm_edit_actions($actions, $mod);
         $resp->onclick = $mod->get_on_click();
         $resp->visible = $mod->visible;
 
-        // if using groupings, then display grouping name
+        // If using groupings, then display grouping name.
         if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', $this->context)) {
             $groupings = groups_get_all_groupings($this->course->id);
             $resp->groupingname = format_string($groupings[$mod->groupingid]->name);