Merge branch 'MDL-58776-master' of git://github.com/ankitagarwal/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 16 May 2017 16:48:56 +0000 (17:48 +0100)
committerDan Poltawski <dan@moodle.com>
Tue, 16 May 2017 16:48:56 +0000 (17:48 +0100)
671 files changed:
admin/environment.xml
admin/index.php
admin/registration/forms.php
admin/settings/plugins.php
admin/tool/assignmentupgrade/version.php
admin/tool/availabilityconditions/version.php
admin/tool/behat/version.php
admin/tool/capability/version.php
admin/tool/cohortroles/version.php
admin/tool/customlang/version.php
admin/tool/dbtransfer/version.php
admin/tool/filetypes/version.php
admin/tool/generator/version.php
admin/tool/health/version.php
admin/tool/innodb/version.php
admin/tool/installaddon/version.php
admin/tool/langimport/version.php
admin/tool/log/store/database/version.php
admin/tool/log/store/legacy/version.php
admin/tool/log/store/standard/version.php
admin/tool/log/version.php
admin/tool/lp/templates/comment_area.mustache
admin/tool/lp/version.php
admin/tool/lpimportcsv/version.php
admin/tool/lpmigrate/version.php
admin/tool/messageinbound/version.php
admin/tool/mobile/version.php
admin/tool/monitor/version.php
admin/tool/multilangupgrade/version.php
admin/tool/oauth2/lang/en/tool_oauth2.php
admin/tool/oauth2/version.php
admin/tool/phpunit/version.php
admin/tool/profiling/version.php
admin/tool/recyclebin/version.php
admin/tool/replace/version.php
admin/tool/spamcleaner/version.php
admin/tool/task/version.php
admin/tool/templatelibrary/classes/api.php
admin/tool/templatelibrary/version.php
admin/tool/unsuproles/version.php
admin/tool/uploadcourse/tests/course_test.php
admin/tool/uploadcourse/version.php
admin/tool/uploaduser/version.php
admin/tool/usertours/lang/en/tool_usertours.php
admin/tool/usertours/version.php
admin/tool/xmldb/version.php
auth/cas/db/upgrade.php
auth/cas/settings.php
auth/cas/version.php
auth/classes/output/login.php
auth/db/db/upgrade.php
auth/db/settings.php
auth/db/version.php
auth/email/db/upgrade.php
auth/email/settings.php
auth/email/version.php
auth/fc/db/upgrade.php
auth/fc/settings.php
auth/fc/version.php
auth/imap/db/upgrade.php
auth/imap/settings.php
auth/imap/version.php
auth/ldap/auth.php
auth/ldap/db/upgrade.php
auth/ldap/lang/en/auth_ldap.php
auth/ldap/settings.php
auth/ldap/version.php
auth/lti/version.php
auth/manual/db/upgrade.php
auth/manual/settings.php
auth/manual/version.php
auth/mnet/db/upgrade.php
auth/mnet/version.php
auth/nntp/db/upgrade.php
auth/nntp/settings.php
auth/nntp/version.php
auth/nologin/version.php
auth/none/db/upgrade.php
auth/none/settings.php
auth/none/version.php
auth/oauth2/classes/api.php
auth/oauth2/classes/linked_login.php
auth/oauth2/confirm-account.php
auth/oauth2/confirm-linkedlogin.php
auth/oauth2/db/events.php [new file with mode: 0644]
auth/oauth2/lang/en/auth_oauth2.php
auth/oauth2/lib.php
auth/oauth2/linkedlogins.php
auth/oauth2/login.php
auth/oauth2/settings.php
auth/oauth2/tests/api_test.php [new file with mode: 0644]
auth/oauth2/version.php
auth/pam/db/upgrade.php
auth/pam/settings.php
auth/pam/version.php
auth/pop3/db/upgrade.php
auth/pop3/settings.php
auth/pop3/version.php
auth/shibboleth/db/upgrade.php
auth/shibboleth/settings.php
auth/shibboleth/version.php
auth/upgrade.txt
auth/webservice/version.php
availability/condition/completion/version.php
availability/condition/date/version.php
availability/condition/grade/version.php
availability/condition/group/version.php
availability/condition/grouping/version.php
availability/condition/profile/version.php
backup/backup.class.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
backup/moodle2/tests/backup_xml_transformer_test.php [new file with mode: 0644]
backup/util/helper/restore_structure_parser_processor.class.php
backup/util/helper/tests/restore_structure_parser_processor_test.php [new file with mode: 0644]
backup/util/settings/base_setting.class.php
backup/util/settings/setting_dependency.class.php
blocks/activity_modules/version.php
blocks/activity_results/block_activity_results.php
blocks/activity_results/version.php
blocks/admin_bookmarks/version.php
blocks/badges/version.php
blocks/blog_menu/version.php
blocks/blog_recent/version.php
blocks/blog_tags/version.php
blocks/calendar_month/version.php
blocks/calendar_upcoming/version.php
blocks/comments/version.php
blocks/community/version.php
blocks/completionstatus/version.php
blocks/course_list/version.php
blocks/course_summary/version.php
blocks/feedback/version.php
blocks/globalsearch/version.php
blocks/glossary_random/version.php
blocks/html/version.php
blocks/login/version.php
blocks/lp/version.php
blocks/mentees/version.php
blocks/messages/version.php
blocks/mnet_hosts/version.php
blocks/myoverview/amd/build/event_list_by_course.min.js
blocks/myoverview/amd/src/event_list_by_course.js
blocks/myoverview/lang/en/block_myoverview.php
blocks/myoverview/templates/course-event-list.mustache
blocks/myoverview/templates/courses-view.mustache
blocks/myoverview/templates/event-list.mustache
blocks/myoverview/templates/main.mustache
blocks/myoverview/templates/progress-chart.mustache
blocks/myoverview/templates/timeline-view-courses.mustache
blocks/myoverview/tests/behat/block_myoverview_progress.feature
blocks/myoverview/version.php
blocks/myprofile/version.php
blocks/navigation/version.php
blocks/news_items/version.php
blocks/online_users/version.php
blocks/participants/version.php
blocks/private_files/version.php
blocks/quiz_results/version.php
blocks/recent_activity/version.php
blocks/rss_client/version.php
blocks/search_forums/version.php
blocks/section_links/version.php
blocks/selfcompletion/version.php
blocks/settings/version.php
blocks/site_main_menu/version.php
blocks/social_activities/version.php
blocks/tag_flickr/version.php
blocks/tag_youtube/version.php
blocks/tags/version.php
blog/external_blog_edit.php
blog/lib.php
cache/locks/file/version.php
cache/stores/apcu/version.php
cache/stores/file/version.php
cache/stores/memcache/version.php
cache/stores/memcached/lib.php
cache/stores/memcached/tests/memcached_test.php
cache/stores/memcached/version.php
cache/stores/mongodb/version.php
cache/stores/redis/version.php
cache/stores/session/version.php
cache/stores/static/version.php
calendar/classes/external/event_action_exporter.php
calendar/classes/external/event_exporter.php
calendar/classes/external/event_icon_exporter.php
calendar/classes/local/event/container.php
calendar/classes/local/event/data_access/event_vault.php
calendar/classes/local/event/entities/event_interface.php
calendar/classes/local/event/factories/event_abstract_factory.php
calendar/classes/local/event/mappers/event_mapper.php
calendar/classes/local/event/proxies/cm_info_proxy.php [moved from calendar/classes/local/event/proxies/module_std_proxy.php with 53% similarity]
calendar/classes/local/event/proxies/proxy_interface.php
calendar/classes/local/event/proxies/std_proxy.php
calendar/classes/rrule_manager.php
calendar/export_execute.php
calendar/externallib.php
calendar/lib.php
calendar/renderer.php
calendar/tests/cm_info_proxy_test.php [new file with mode: 0644]
calendar/tests/container_test.php
calendar/tests/event_factory_test.php
calendar/tests/event_mapper_test.php
calendar/tests/event_vault_test.php
calendar/tests/externallib_test.php
calendar/tests/helpers.php
calendar/tests/lib_test.php
calendar/tests/module_std_proxy_test.php [deleted file]
calendar/tests/rrule_manager_test.php
calendar/tests/std_proxy_test.php
calendar/type/gregorian/version.php
competency/classes/competency.php
competency/classes/user_competency_course.php
completion/tests/behat/bulk_edit_activity_completion.feature
completion/tests/behat/default_activity_completion.feature
course/amd/build/actions.min.js
course/amd/src/actions.js
course/changenumsections.php
course/editsection.php
course/externallib.php
course/format/lib.php
course/format/renderer.php
course/format/singleactivity/version.php
course/format/social/version.php
course/format/topics/lang/en/format_topics.php
course/format/topics/tests/behat/edit_delete_sections.feature
course/format/topics/version.php
course/format/upgrade.txt
course/format/weeks/backup/moodle2/restore_format_weeks_plugin.class.php
course/format/weeks/classes/observer.php [new file with mode: 0644]
course/format/weeks/db/events.php [new file with mode: 0644]
course/format/weeks/db/upgrade.php
course/format/weeks/lang/en/format_weeks.php
course/format/weeks/lib.php
course/format/weeks/tests/behat/edit_delete_sections.feature
course/format/weeks/tests/observer_test.php [new file with mode: 0644]
course/format/weeks/version.php
course/tests/externallib_test.php
course/upgrade.txt
dataformat/csv/version.php
dataformat/excel/version.php
dataformat/html/version.php
dataformat/json/version.php
dataformat/ods/version.php
enrol/category/version.php
enrol/cohort/version.php
enrol/database/version.php
enrol/flatfile/version.php
enrol/guest/version.php
enrol/imsenterprise/version.php
enrol/ldap/lang/en/enrol_ldap.php
enrol/ldap/version.php
enrol/lti/version.php
enrol/manual/version.php
enrol/meta/version.php
enrol/mnet/version.php
enrol/paypal/version.php
enrol/self/version.php
files/converter/googledrive/lang/en/fileconverter_googledrive.php
files/converter/googledrive/version.php
files/converter/unoconv/version.php
filter/activitynames/version.php
filter/algebra/version.php
filter/censor/version.php
filter/data/version.php
filter/emailprotect/version.php
filter/emoticon/version.php
filter/glossary/version.php
filter/mathjaxloader/version.php
filter/mediaplugin/version.php
filter/multilang/version.php
filter/tex/version.php
filter/tidy/version.php
filter/urltolink/version.php
grade/export/ods/version.php
grade/export/txt/version.php
grade/export/xls/version.php
grade/export/xml/version.php
grade/grading/form/guide/version.php
grade/grading/form/rubric/version.php
grade/import/csv/version.php
grade/import/direct/version.php
grade/import/xml/version.php
grade/report/grader/version.php
grade/report/history/version.php
grade/report/outcomes/version.php
grade/report/overview/version.php
grade/report/singleview/version.php
grade/report/user/version.php
index.php
install/lang/cs/install.php
install/lang/de/install.php
install/lang/en/install.php
install/lang/es_mx/install.php
install/lang/fa/error.php
install/lang/fr/install.php
install/lang/he/admin.php
install/lang/hu/install.php
install/lang/ja/install.php
install/lang/pt/install.php
install/lang/pt_br/install.php
install/lang/sr_cr/install.php
install/lang/sr_lt/install.php
lang/en/admin.php
lang/en/auth.php
lang/en/backup.php
lang/en/badges.php
lang/en/blog.php
lang/en/calendar.php
lang/en/completion.php
lang/en/error.php
lang/en/install.php
lang/en/moodle.php
lang/en/plugin.php
lib/amd/build/modal_save_cancel.min.js
lib/amd/build/templates.min.js
lib/amd/src/modal_save_cancel.js
lib/amd/src/templates.js
lib/antivirus/clamav/version.php
lib/classes/message/manager.php
lib/classes/oauth2/client.php
lib/classes/output/icon_system_fontawesome.php
lib/classes/task/calendar_cron_task.php
lib/classes/task/refresh_mod_calendar_events_task.php
lib/db/upgrade.php
lib/deprecatedlib.php
lib/editor/atto/plugins/accessibilitychecker/version.php
lib/editor/atto/plugins/accessibilityhelper/version.php
lib/editor/atto/plugins/align/version.php
lib/editor/atto/plugins/backcolor/version.php
lib/editor/atto/plugins/bold/version.php
lib/editor/atto/plugins/charmap/version.php
lib/editor/atto/plugins/clear/version.php
lib/editor/atto/plugins/collapse/version.php
lib/editor/atto/plugins/emoticon/version.php
lib/editor/atto/plugins/equation/version.php
lib/editor/atto/plugins/fontcolor/version.php
lib/editor/atto/plugins/html/version.php
lib/editor/atto/plugins/image/version.php
lib/editor/atto/plugins/indent/version.php
lib/editor/atto/plugins/italic/version.php
lib/editor/atto/plugins/link/version.php
lib/editor/atto/plugins/managefiles/version.php
lib/editor/atto/plugins/media/version.php
lib/editor/atto/plugins/noautolink/version.php
lib/editor/atto/plugins/orderedlist/version.php
lib/editor/atto/plugins/rtl/version.php
lib/editor/atto/plugins/strike/version.php
lib/editor/atto/plugins/subscript/version.php
lib/editor/atto/plugins/superscript/version.php
lib/editor/atto/plugins/table/version.php
lib/editor/atto/plugins/title/version.php
lib/editor/atto/plugins/underline/version.php
lib/editor/atto/plugins/undo/version.php
lib/editor/atto/plugins/unorderedlist/version.php
lib/editor/atto/version.php
lib/editor/textarea/version.php
lib/editor/tinymce/plugins/ctrlhelp/version.php
lib/editor/tinymce/plugins/managefiles/version.php
lib/editor/tinymce/plugins/moodleemoticon/tinymce/editor_plugin.js
lib/editor/tinymce/plugins/moodleemoticon/version.php
lib/editor/tinymce/plugins/moodleimage/version.php
lib/editor/tinymce/plugins/moodlemedia/version.php
lib/editor/tinymce/plugins/moodlenolink/version.php
lib/editor/tinymce/plugins/pdw/version.php
lib/editor/tinymce/plugins/spellchecker/version.php
lib/editor/tinymce/plugins/wrap/version.php
lib/editor/tinymce/version.php
lib/filestorage/stored_file.php
lib/ldaplib.php
lib/ltiprovider/readme_moodle.txt
lib/ltiprovider/src/HTTPMessage.php
lib/messagelib.php
lib/oauthlib.php
lib/outputrequirementslib.php
lib/portfolio/plugin.php
lib/setuplib.php
lib/statslib.php
lib/templates/columns-1to1to1.mustache
lib/templates/columns-1to2.mustache
lib/templates/columns-2to1.mustache
lib/tests/calendar_cron_task_test.php
lib/tests/ldaplib_test.php
lib/tests/message_test.php
lib/tests/messagelib_test.php
lib/tests/upgradelib_test.php
lib/upgrade.txt
lib/upgradelib.php
login/signup.php
media/player/html5audio/version.php
media/player/html5video/version.php
media/player/swf/version.php
media/player/videojs/version.php
media/player/vimeo/version.php
media/player/youtube/version.php
message/output/airnotifier/version.php
message/output/email/version.php
message/output/jabber/version.php
message/output/lib.php
message/output/popup/message_output_popup.php
message/output/popup/version.php
mnet/service/enrol/version.php
mod/assign/backup/moodle2/restore_assign_stepslib.php
mod/assign/db/upgrade.php
mod/assign/externallib.php
mod/assign/feedback/comments/version.php
mod/assign/feedback/editpdf/lib.php
mod/assign/feedback/editpdf/version.php
mod/assign/feedback/file/lib.php
mod/assign/feedback/file/version.php
mod/assign/feedback/offline/version.php
mod/assign/gradingtable.php
mod/assign/lib.php
mod/assign/locallib.php
mod/assign/renderer.php
mod/assign/submission/comments/version.php
mod/assign/submission/file/lib.php
mod/assign/submission/file/locallib.php
mod/assign/submission/file/tests/behat/file_type_restriction.feature
mod/assign/submission/file/tests/locallib_test.php
mod/assign/submission/file/version.php
mod/assign/submission/onlinetext/lib.php
mod/assign/submission/onlinetext/locallib.php
mod/assign/submission/onlinetext/version.php
mod/assign/tests/externallib_test.php
mod/assign/tests/locallib_test.php
mod/assign/upgrade.txt
mod/assign/version.php
mod/assignment/type/offline/version.php
mod/assignment/type/online/version.php
mod/assignment/type/upload/version.php
mod/assignment/type/uploadsingle/version.php
mod/assignment/version.php
mod/book/lib.php
mod/book/tool/exportimscp/version.php
mod/book/tool/importhtml/version.php
mod/book/tool/print/version.php
mod/book/version.php
mod/chat/lib.php
mod/chat/version.php
mod/choice/lib.php
mod/choice/report.php
mod/choice/version.php
mod/data/field/checkbox/version.php
mod/data/field/date/version.php
mod/data/field/file/version.php
mod/data/field/latlong/version.php
mod/data/field/menu/version.php
mod/data/field/multimenu/version.php
mod/data/field/number/version.php
mod/data/field/picture/version.php
mod/data/field/radiobutton/version.php
mod/data/field/text/version.php
mod/data/field/textarea/version.php
mod/data/field/url/version.php
mod/data/lib.php
mod/data/preset/imagegallery/version.php
mod/data/tests/lib_test.php
mod/data/version.php
mod/feedback/analysis.php
mod/feedback/analysis_course.php
mod/feedback/analysis_to_excel.php [new file with mode: 0644]
mod/feedback/classes/completion.php
mod/feedback/classes/structure.php
mod/feedback/lib.php
mod/feedback/tests/behat/anonymous.feature
mod/feedback/tests/lib_test.php
mod/feedback/version.php
mod/folder/lib.php
mod/folder/version.php
mod/forum/externallib.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/tests/lib_test.php
mod/forum/version.php
mod/glossary/lang/en/glossary.php
mod/glossary/lib.php
mod/glossary/locallib.php
mod/glossary/tests/lib_test.php
mod/glossary/version.php
mod/imscp/lib.php
mod/imscp/version.php
mod/label/lib.php
mod/label/version.php
mod/lesson/classes/external.php
mod/lesson/lib.php
mod/lesson/pagetypes/branchtable.php
mod/lesson/pagetypes/numerical.php
mod/lesson/tests/external_test.php
mod/lesson/version.php
mod/lti/classes/service_exception_handler.php
mod/lti/lib.php
mod/lti/locallib.php
mod/lti/service/memberships/version.php
mod/lti/service/profile/version.php
mod/lti/service/toolproxy/version.php
mod/lti/service/toolsettings/version.php
mod/lti/version.php
mod/page/lib.php
mod/page/version.php
mod/quiz/accessrule/delaybetweenattempts/version.php
mod/quiz/accessrule/ipaddress/version.php
mod/quiz/accessrule/numattempts/version.php
mod/quiz/accessrule/offlineattempts/version.php
mod/quiz/accessrule/openclosedate/version.php
mod/quiz/accessrule/password/version.php
mod/quiz/accessrule/safebrowser/version.php
mod/quiz/accessrule/securewindow/version.php
mod/quiz/accessrule/timelimit/version.php
mod/quiz/lib.php
mod/quiz/report/grading/version.php
mod/quiz/report/overview/version.php
mod/quiz/report/responses/version.php
mod/quiz/report/statistics/version.php
mod/quiz/version.php
mod/quiz/yui/build/moodle-mod_quiz-util-slot/moodle-mod_quiz-util-slot-debug.js
mod/quiz/yui/build/moodle-mod_quiz-util-slot/moodle-mod_quiz-util-slot-min.js
mod/quiz/yui/build/moodle-mod_quiz-util-slot/moodle-mod_quiz-util-slot.js
mod/quiz/yui/src/util/js/slot.js
mod/resource/lib.php
mod/resource/version.php
mod/scorm/lang/en/scorm.php
mod/scorm/lib.php
mod/scorm/report/basic/version.php
mod/scorm/report/graphs/version.php
mod/scorm/report/interactions/version.php
mod/scorm/report/objectives/version.php
mod/scorm/tests/lib_test.php
mod/scorm/version.php
mod/survey/lib.php
mod/survey/version.php
mod/url/lib.php
mod/url/version.php
mod/wiki/lang/en/wiki.php
mod/wiki/lib.php
mod/wiki/version.php
mod/workshop/allocation/manual/version.php
mod/workshop/allocation/random/version.php
mod/workshop/allocation/scheduled/version.php
mod/workshop/eval/best/version.php
mod/workshop/form/accumulative/version.php
mod/workshop/form/comments/version.php
mod/workshop/form/numerrors/version.php
mod/workshop/form/rubric/version.php
mod/workshop/version.php
portfolio/boxnet/version.php
portfolio/download/file.php
portfolio/download/version.php
portfolio/flickr/version.php
portfolio/googledocs/version.php
portfolio/mahara/version.php
portfolio/picasa/version.php
question/behaviour/adaptive/version.php
question/behaviour/adaptivenopenalty/version.php
question/behaviour/deferredcbm/version.php
question/behaviour/deferredfeedback/version.php
question/behaviour/immediatecbm/version.php
question/behaviour/immediatefeedback/version.php
question/behaviour/informationitem/version.php
question/behaviour/interactive/version.php
question/behaviour/interactivecountback/version.php
question/behaviour/manualgraded/version.php
question/behaviour/missing/version.php
question/format/aiken/version.php
question/format/blackboard_six/version.php
question/format/examview/version.php
question/format/gift/version.php
question/format/missingword/version.php
question/format/multianswer/version.php
question/format/webct/version.php
question/format/xhtml/version.php
question/format/xml/version.php
question/type/calculated/questiontype.php
question/type/calculated/tests/questiontype_test.php
question/type/calculated/version.php
question/type/calculatedmulti/version.php
question/type/calculatedsimple/version.php
question/type/ddimageortext/version.php
question/type/ddmarker/version.php
question/type/ddwtos/version.php
question/type/description/version.php
question/type/essay/db/install.xml
question/type/essay/lang/en/qtype_essay.php
question/type/essay/question.php
question/type/essay/tests/behat/edit.feature
question/type/essay/tests/helper.php
question/type/essay/tests/question_test.php
question/type/essay/version.php
question/type/gapselect/version.php
question/type/match/version.php
question/type/missingtype/version.php
question/type/multianswer/version.php
question/type/multichoice/version.php
question/type/numerical/version.php
question/type/random/version.php
question/type/randomsamatch/version.php
question/type/shortanswer/version.php
question/type/truefalse/version.php
report/backups/version.php
report/competency/version.php
report/completion/version.php
report/configlog/version.php
report/courseoverview/version.php
report/eventlist/version.php
report/log/version.php
report/loglive/version.php
report/outline/version.php
report/participation/version.php
report/performance/version.php
report/progress/version.php
report/questioninstances/version.php
report/security/version.php
report/stats/version.php
report/usersessions/version.php
repository/areafiles/version.php
repository/boxnet/version.php
repository/coursefiles/version.php
repository/dropbox/version.php
repository/equella/version.php
repository/filesystem/lib.php
repository/filesystem/version.php
repository/flickr/version.php
repository/flickr_public/version.php
repository/googledocs/lang/en/repository_googledocs.php
repository/googledocs/lib.php
repository/googledocs/version.php
repository/local/version.php
repository/merlot/version.php
repository/onedrive/classes/remove_temp_access_task.php
repository/onedrive/classes/rest.php
repository/onedrive/lang/en/repository_onedrive.php
repository/onedrive/lib.php
repository/onedrive/version.php
repository/picasa/version.php
repository/recent/version.php
repository/s3/version.php
repository/skydrive/version.php
repository/upload/version.php
repository/url/version.php
repository/user/version.php
repository/webdav/version.php
repository/wikimedia/version.php
repository/youtube/version.php
search/engine/solr/version.php
theme/boost/pix/fp/alias.svg
theme/boost/pix/fp/alias_sm.svg [new file with mode: 0644]
theme/boost/scss/moodle/blocks.scss
theme/boost/scss/moodle/filemanager.scss
theme/boost/scss/moodle/icons.scss
theme/boost/templates/core/columns-1to1to1.mustache [new file with mode: 0644]
theme/boost/templates/core/columns-1to2.mustache [new file with mode: 0644]
theme/boost/templates/core/columns-2to1.mustache [new file with mode: 0644]
theme/boost/version.php
theme/bootstrapbase/less/moodle/blocks.less
theme/bootstrapbase/style/moodle.css
theme/bootstrapbase/templates/block_myoverview/course-event-list.mustache
theme/bootstrapbase/templates/block_myoverview/courses-view.mustache
theme/bootstrapbase/version.php
theme/clean/version.php
theme/more/version.php
user/profile/field/checkbox/version.php
user/profile/field/datetime/version.php
user/profile/field/menu/field.class.php
user/profile/field/menu/version.php
user/profile/field/text/version.php
user/profile/field/textarea/version.php
version.php
webservice/rest/version.php
webservice/soap/version.php
webservice/xmlrpc/locallib.php
webservice/xmlrpc/version.php

index f875211..916c8a7 100644 (file)
       <PHP_EXTENSION name="json" level="required">
       </PHP_EXTENSION>
       <PHP_EXTENSION name="hash" level="required"/>
+      <PHP_EXTENSION name="fileinfo" level="required"/>
     </PHP_EXTENSIONS>
     <PHP_SETTINGS>
       <PHP_SETTING name="memory_limit" value="96M" level="required">
index 30ba5cb..6cf7f45 100644 (file)
@@ -101,6 +101,12 @@ if (function_exists('opcache_invalidate')) {
 // indirectly calls the protected init() method is good here.
 core_component::get_core_subsystems();
 
+if (is_major_upgrade_required() && isloggedin()) {
+    // A major upgrade is required.
+    // Terminate the session and redirect back here before anything DB-related happens.
+    redirect_if_major_upgrade_required();
+}
+
 require_once($CFG->libdir.'/adminlib.php');    // various admin-only functions
 require_once($CFG->libdir.'/upgradelib.php');  // general upgrade/install related functions
 
index 5f89d0c..ddf2db6 100644 (file)
@@ -422,12 +422,12 @@ class site_registration_form extends moodleform {
             $mform->addElement('checkbox', 'badges', '',
                     " " . get_string('badgesnumber', 'hub', $badges));
             $mform->setDefault('badges', $badgesnumber != -1);
-            $mform->setType('resources', PARAM_INT);
+            $mform->setType('badges', PARAM_INT);
 
             $mform->addElement('checkbox', 'issuedbadges', '',
                     " " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
             $mform->setDefault('issuedbadges', $issuedbadgesnumber != -1);
-            $mform->setType('resources', PARAM_INT);
+            $mform->setType('issuedbadges', PARAM_INT);
 
             $mform->addElement('checkbox', 'participantnumberaverage', '',
                     " " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
index 1dfdd6a..e63f190 100644 (file)
@@ -232,7 +232,7 @@ if ($hassiteconfig) {
 
     // Convert plugins.
     $ADMIN->add('modules', new admin_category('fileconverterplugins', new lang_string('type_fileconverter_plural', 'plugin')));
-    $temp = new admin_settingpage('managefileconverterplugins', new lang_string('type_fileconverter', 'plugin'));
+    $temp = new admin_settingpage('managefileconverterplugins', new lang_string('type_fileconvertermanage', 'plugin'));
     $temp->add(new admin_setting_manage_fileconverter_plugins());
     $ADMIN->add('fileconverterplugins', $temp);
 
index c44e6a3..b9f686e 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;
-$plugin->requires  = 2016112900;
+$plugin->version   = 2017051500;
+$plugin->requires  = 2017050500;
 $plugin->component = 'tool_assignmentupgrade';
-$plugin->dependencies = array('mod_assign' => 2016112900);
+$plugin->dependencies = array('mod_assign' => 2017050500);
index 88205f6..c653aae 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'tool_availabilityconditions';
index e79651f..86b4270 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;   // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;   // Requires this Moodle version
+$plugin->version   = 2017051500;   // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;   // Requires this Moodle version
 $plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
index 8fd2642..207cc49 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
index f65a0fb..4184223 100644 (file)
@@ -25,8 +25,8 @@
 defined('MOODLE_INTERNAL') || die();
 
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
 
 $plugin->dependencies = array(
index b2a4907..d781f1c 100644 (file)
@@ -25,6 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;
-$plugin->requires  = 2016112900;
+$plugin->version   = 2017051500;
+$plugin->requires  = 2017050500;
 $plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
index 0f52139..77a6bb5 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_dbtransfer'; // Full name of the plugin (used for diagnostics).
index 05ad249..cdeb0bc 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'tool_filetypes';
index 2e19cbb..2bbb64a 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'tool_generator';
index e7e62f8..cefee6d 100644 (file)
@@ -25,8 +25,8 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_health'; // Full name of the plugin (used for diagnostics)
 
 $plugin->maturity  = MATURITY_ALPHA; // this version's maturity level
index 439c750..4c6c9b2 100644 (file)
@@ -25,6 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_innodb'; // Full name of the plugin (used for diagnostics)
index b9426f4..023919f 100644 (file)
@@ -24,6 +24,6 @@
 defined('MOODLE_INTERNAL') || die();
 
 $plugin->component  = 'tool_installaddon';
-$plugin->version    = 2016120500;
-$plugin->requires   = 2016112900;
+$plugin->version    = 2017051500;
+$plugin->requires   = 2017050500;
 $plugin->maturity   = MATURITY_STABLE;
index 6b2724e..dd33c73 100644 (file)
@@ -25,6 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_langimport'; // Full name of the plugin (used for diagnostics)
index 13e0a29..40d4db1 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2016112900; // Requires this Moodle version.
+$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2017050500; // Requires this Moodle version.
 $plugin->component = 'logstore_database'; // Full name of the plugin (used for diagnostics).
index d8eb2b4..54b807f 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2016112900; // Requires this Moodle version.
+$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2017050500; // Requires this Moodle version.
 $plugin->component = 'logstore_legacy'; // Full name of the plugin (used for diagnostics).
index 36da7a1..3406918 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2016112900; // Requires this Moodle version.
+$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2017050500; // Requires this Moodle version.
 $plugin->component = 'logstore_standard'; // Full name of the plugin (used for diagnostics).
index 59fc1ff..6a64dec 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2016112900; // Requires this Moodle version.
+$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_log'; // Full name of the plugin (used for diagnostics).
index bd49f87..a73f3ed 100644 (file)
@@ -30,7 +30,7 @@
     * autostart
     * canpost
     * cid
-    * collapsediconurl
+    * collapsediconkey
     * commentarea
     * component
     * contextid
index 84d7b12..3dadfb7 100644 (file)
@@ -25,6 +25,6 @@
 defined('MOODLE_INTERNAL') || die();
 
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
index 79a1d15..d9cde29 100644 (file)
@@ -25,8 +25,8 @@
 defined('MOODLE_INTERNAL') || die();
 
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_lpimportcsv'; // Full name of the plugin (used for diagnostics).
-$plugin->dependencies = array('tool_lp' => 2016112900);
+$plugin->dependencies = array('tool_lp' => 2017050500);
 
index 0eb8e8c..c26c239 100644 (file)
@@ -24,8 +24,8 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_lpmigrate'; // Full name of the plugin (used for diagnostics).
 $plugin->dependencies = array(
     'tool_lp' => ANY_VERSION
index 9b419f3..dea4dde 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;
-$plugin->requires  = 2016112900;
+$plugin->version   = 2017051500;
+$plugin->requires  = 2017050500;
 $plugin->component = 'tool_messageinbound';
index d42f121..0903cc5 100644 (file)
@@ -23,9 +23,9 @@
  */
 
 defined('MOODLE_INTERNAL') || die();
-$plugin->version   = 2017041200; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
 $plugin->dependencies = array(
-    'webservice_rest' => 2016120500
+    'webservice_rest' => 2017050500
 );
index 2a46e91..0d70292 100644 (file)
@@ -26,6 +26,6 @@
 
 defined('MOODLE_INTERNAL') || die;
 
-$plugin->version   = 2017021300;     // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900;     // Requires this Moodle version.
+$plugin->version   = 2017051500;     // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500;     // Requires this Moodle version.
 $plugin->component = 'tool_monitor'; // Full name of the plugin (used for diagnostics).
index e5d7f88..4f66912 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_multilangupgrade'; // Full name of the plugin (used for diagnostics)
 
index d2c9a2a..3fdb55f 100644 (file)
@@ -29,7 +29,7 @@ $string['configured'] = 'Configured';
 $string['configuredstatus'] = 'Configured';
 $string['connectsystemaccount'] = 'Connect to a system account';
 $string['createfromtemplate'] = 'Create an OAuth 2 service from a template';
-$string['createfromtemplatedesc'] = 'Choose one of the OAuth 2 service template below to create an OAuth service with a valid configuration for one of the known service types. This will create the OAuth 2 service, with all the correct end points and parameters required for authentication, but you will still need to enter the client ID and secret for the new service before it can be used.';
+$string['createfromtemplatedesc'] = 'Choose one of the OAuth 2 service templates below to create an OAuth service with a valid configuration for one of the known service types. This will create the OAuth 2 service, with all the correct end points and parameters required for authentication, though you will still need to enter the client ID and secret for the new service before it can be used.';
 $string['createnewendpoint'] = 'Create new endpoint for issuer "{$a}"';
 $string['createnewfacebookissuer'] = 'Create new Facebook service';
 $string['createnewgoogleissuer'] = 'Create new Google service';
@@ -39,7 +39,7 @@ $string['createnewuserfieldmapping'] = 'Create new user field mapping for issuer
 $string['deleteconfirm'] = 'Are you sure you want to delete the identity issuer "{$a}"? Any plugins relying on this issuer will stop working.';
 $string['deleteendpointconfirm'] = 'Are you sure you want to delete the endpoint "{$a->endpoint}" for issuer "{$a->issuer}"? Any plugins relying on this endpoint will stop working.';
 $string['deleteuserfieldmappingconfirm'] = 'Are you sure you want to delete the user field mapping for issuer "{$a}"?';
-$string['discovered_help'] = 'Discovery means that the OAuth2 endpoints could be automatically determined from the base url for the OAuth service. Not all services are required to be "discovered", but if they are not, then the endpoints and user mapping information will need to be entered manually.';
+$string['discovered_help'] = 'Discovery means that the OAuth 2 endpoints could be automatically determined from the base URL for the OAuth service. Not all services are required to be "discovered", but if they are not, then the endpoints and user mapping information will need to be entered manually.';
 $string['discovered'] = 'Service discovery successful';
 $string['discoverystatus'] = 'Discovery';
 $string['editendpoint'] = 'Edit endpoint: {$a->endpoint} for issuer {$a->issuer}';
@@ -52,25 +52,25 @@ $string['endpointname_help'] = 'Key used to search for this endpoint. Must end w
 $string['endpointname'] = 'Name';
 $string['endpointsforissuer'] = 'Endpoints for issuer: {$a}';
 $string['endpointurl_help'] = 'URL for this endpoint. Must use https:// protocol.';
-$string['endpointurl'] = 'Url';
-$string['issuersetup'] = 'Detailed instructions on configuring the common OAuth 2 Services';
+$string['endpointurl'] = 'URL';
+$string['issuersetup'] = 'Detailed instructions on configuring the common OAuth 2 services';
 $string['issuersetuptype'] = 'Detailed instructions on setting up the {$a} OAuth 2 provider';
 $string['issueralloweddomains_help'] = 'If set, this setting is a comma separated list of domains that logins will be restricted to when using this provider.';
 $string['issueralloweddomains_link'] = 'OAuth_2_login_domains';
 $string['issueralloweddomains'] = 'Login domains';
-$string['issuerbaseurl_help'] = 'Base url used to access the service.';
-$string['issuerbaseurl'] = 'Service base url';
-$string['issuerclientid'] = 'Client Id';
+$string['issuerbaseurl_help'] = 'Base URL used to access the service.';
+$string['issuerbaseurl'] = 'Service base URL';
+$string['issuerclientid'] = 'Client ID';
 $string['issuerclientid_help'] = 'The OAuth client ID for this issuer.';
-$string['issuerclientsecret'] = 'Client Secret';
+$string['issuerclientsecret'] = 'Client secret';
 $string['issuerclientsecret_help'] = 'The OAuth client secret for this issuer.';
 $string['issuerdeleted'] = 'Identity issuer deleted';
 $string['issuerdisabled'] = 'Identity issuer disabled';
 $string['issuerenabled'] = 'Identity issuer enabled';
-$string['issuerimage_help'] = 'An image url used to show a logo for this issuer. May be displayed on login page.';
+$string['issuerimage_help'] = 'An image URL used to show a logo for this issuer. May be displayed on login page.';
 $string['issuerimage'] = 'Logo URL';
 $string['issuerloginparams'] = 'Additional parameters included in a login request.';
-$string['issuerloginparams_help'] = 'Some systems require additional parameters for a login request in order to read the users basic profile.';
+$string['issuerloginparams_help'] = 'Some systems require additional parameters for a login request in order to read the user\'s basic profile.';
 $string['issuerloginparamsoffline'] = 'Additional parameters included in a login request for offline access.';
 $string['issuerloginparamsoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Google requires the additional params: "access_type=offline&prompt=consent" these parameters should be in url query parameter format.';
 $string['issuerloginscopes_help'] = 'Some systems require additional scopes for a login request in order to read the users basic profile. The standard scopes for an OpenID Connect compliant system are "openid profile email".';
@@ -79,14 +79,14 @@ $string['issuerloginscopesoffline'] = 'Scopes included in a login request for of
 $string['issuerloginscopes'] = 'Scopes included in a login request.';
 $string['issuername_help'] = 'Name of the identity issuer. May be displayed on login page.';
 $string['issuername'] = 'Name';
-$string['issuershowonloginpage_help'] = 'If the OpenID Connect Authentication plugin is enabled, this login issuer will be listed on the login page to allow users to login with accounts from this issuer.';
+$string['issuershowonloginpage_help'] = 'If the OpenID Connect Authentication plugin is enabled, this login issuer will be listed on the login page to allow users to log in with accounts from this issuer.';
 $string['issuershowonloginpage'] = 'Show on login page.';
 $string['issuers'] = 'Issuers';
 $string['loginissuer'] = 'Allow login';
 $string['notconfigured'] = 'Not configured';
 $string['notdiscovered'] = 'Service discovery not successful';
 $string['notloginissuer'] = 'Do not allow login';
-$string['pluginname'] = 'OAuth 2 Services';
+$string['pluginname'] = 'OAuth 2 services';
 $string['savechanges'] = 'Save changes';
 $string['serviceshelp'] = 'Service provider setup instructions.';
 $string['systemaccountconnected_help'] = 'System accounts are used to provide advanced functionality for plugins. They are not required for login functionality only, but other plugins using the OAuth service may offer a reduced set of features if the system account has not been connected. For example repositories cannot support "controlled links" without a system account to perform file operations.';
index 22ed6ee..8a08f7c 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_oauth2'; // Full name of the plugin (used for diagnostics).
 
index 1e4f201..5ee13dd 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_phpunit'; // Full name of the plugin (used for diagnostics)
 
index c5392cd..9adf0db 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_profiling'; // Full name of the plugin (used for diagnostics)
index 3f175ff..167b312 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_recyclebin'; // Full name of the plugin (used for diagnostics).
index 02187ed..54c7726 100644 (file)
@@ -25,8 +25,8 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_replace'; // Full name of the plugin (used for diagnostics)
 
 $plugin->maturity  = MATURITY_ALPHA; // this version's maturity level
index 6bbc743..284a709 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;
-$plugin->requires  = 2016112900;
+$plugin->version   = 2017051500;
+$plugin->requires  = 2017050500;
 $plugin->component = 'tool_spamcleaner'; // Full name of the plugin (used for diagnostics)
 
index 5b18888..a6b9679 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_task'; // Full name of the plugin (used for diagnostics)
 
index b760007..7ae2b0e 100644 (file)
@@ -70,6 +70,9 @@ class api {
             // Look at all the templates dirs for subsystems.
             $subsystems = core_component::get_core_subsystems();
             foreach ($subsystems as $subsystem => $dir) {
+                if (empty($dir)) {
+                    continue;
+                }
                 $dir .= '/templates';
                 if (is_dir($dir)) {
                     $dirs = mustache_template_finder::get_template_directories_for_component('core_' . $subsystem, $themename);
index 76bfae2..e53fbfe 100644 (file)
@@ -21,6 +21,6 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 defined('MOODLE_INTERNAL') || die();
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900; // Requires this Moodle version.
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_templatelibrary'; // Full name of the plugin (used for diagnostics).
index 3a26e06..dc879b0 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_unsuproles'; // Full name of the plugin (used for diagnostics)
 
index 2d58c06..3ac9fe0 100644 (file)
@@ -246,7 +246,7 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
             'visible' => '0',
             'idnumber' => '123abc',
             'summary' => 'Summary',
-            'format' => 'weeks',
+            'format' => 'topics',
             'theme' => 'afterburner',
             'lang' => 'en',
             'newsitems' => '7',
@@ -457,7 +457,7 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
             'enddate' => 645667200,
             'idnumber' => '123abc',
             'summary' => 'Summary',
-            'format' => 'weeks',
+            'format' => 'topics',
             'theme' => 'afterburner',
             'lang' => 'en',
             'newsitems' => '7',
index 871661f..f5d2a5c 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;            // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900;            // Requires this Moodle version.
+$plugin->version   = 2017051500;            // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500;            // Requires this Moodle version.
 $plugin->component = 'tool_uploadcourse';   // Full name of the plugin (used for diagnostics).
index 912729d..980892a 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_uploaduser'; // Full name of the plugin (used for diagnostics)
 
index e6d9d2f..9842e41 100644 (file)
@@ -140,7 +140,7 @@ $string['tour_resetforall'] = 'The state of the tour has been reset. It will be
 
 // Boost - administrator tour.
 $string['tour1_title_welcome'] = 'Welcome';
-$string['tour1_content_welcome'] = 'Welcome to the Boost theme for Moodle 3.2. If you\'ve used Moodle before you might find some things look a bit different.';
+$string['tour1_content_welcome'] = 'Welcome to the Boost theme. If you\'ve upgraded from an earlier version, you might find some things look a bit different with this theme.';
 $string['tour1_title_navigation'] = 'Navigation';
 $string['tour1_content_navigation'] = 'Major navigation is now through this nav drawer. The contents update depending on where you are in the site. Use the button at the top to hide or show it.';
 $string['tour1_title_customisation'] = 'Customisation';
@@ -150,11 +150,11 @@ $string['tour1_content_blockregion'] = 'There is still a block region over here.
 $string['tour1_title_addingblocks'] = 'Adding blocks';
 $string['tour1_content_addingblocks'] = 'In fact, think carefully about including any blocks on your pages. Blocks are not shown on the Moodle Mobile app, so as a general rule it\'s much better to make sure your site works well without any blocks.';
 $string['tour1_title_end'] = 'End of tour';
-$string['tour1_content_end'] = 'This has been a user tour, a new feature in Moodle 3.2. It won\'t show again unless you reset it using the link in the footer. As an admin you can also create your own tours like this!';
+$string['tour1_content_end'] = 'This is the end of your user tour. It won\'t show again unless you reset it using the link in the footer. As an admin you can also create your own tours like this!';
 
 // Boost - course view tour.
 $string['tour2_title_welcome'] = 'Welcome';
-$string['tour2_content_welcome'] = 'Welcome to the Boost theme for Moodle 3.2. If you\'ve used Moodle before you might find things look a bit different here on the course page.';
+$string['tour2_content_welcome'] = 'Welcome to the Boost theme. If your site has been upgraded from an earlier version, you might find things look a bit different here on the course page.';
 $string['tour2_title_customisation'] = 'Customisation';
 $string['tour2_content_customisation'] = 'To change any course settings, use the settings menu in the corner of this header. You will find a similar settings menu on the home page of every activity, too. Try turning editing on right now.';
 $string['tour2_title_navigation'] = 'Navigation';
@@ -168,4 +168,4 @@ $string['tour2_content_addblock'] = 'If you turn editing on you can add blocks f
 $string['tour2_title_addingblocks'] = 'Adding blocks';
 $string['tour2_content_addingblocks'] = 'You can add blocks to this page using this button. However, think carefully about including any blocks on your pages. Blocks are not shown on the Moodle Mobile app, so for the best user experience it is better to make sure your course works well without any blocks.';
 $string['tour2_title_end'] = 'End of tour';
-$string['tour2_content_end'] = 'This has been a user tour, a new feature in Moodle 3.2. It won\'t show again unless you reset it using the link in the footer. The site admin can also create further tours for this site if required.';
+$string['tour2_content_end'] = 'This is the end of your user tour. It won\'t show again unless you reset it using the link in the footer. The site admin can also create further tours for this site if required.';
index 384b8f4..b890559 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120501;            // The current module version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900;            // Requires this Moodle version.
+$plugin->version   = 2017051500;            // The current module version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500;            // Requires this Moodle version.
 $plugin->component = 'tool_usertours';      // Full name of the plugin (used for diagnostics).
index 9c2edef..b42ae5c 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900; // Requires this Moodle version
+$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500; // Requires this Moodle version
 $plugin->component = 'tool_xmldb'; // Full name of the plugin (used for diagnostics)
 
index 9de6515..7c7c1c0 100644 (file)
@@ -61,7 +61,8 @@ function xmldb_auth_cas_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/cas to auth_cas.
-        $DB->set_field('config_plugins', 'plugin', 'auth_cas', array('plugin' => 'auth/cas'));
+        upgrade_fix_config_auth_plugin_names('cas');
+        upgrade_fix_config_auth_plugin_defaults('cas');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'cas');
     }
 
index 961c8d2..2bd7434 100644 (file)
@@ -264,7 +264,7 @@ if ($ADMIN->fulltree) {
     }
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('cas');
     $help  = get_string('auth_ldapextrafields', 'auth_ldap');
     $help .= get_string('auth_updatelocal_expl', 'auth');
     $help .= get_string('auth_fieldlock_expl', 'auth');
index 26f3bc5..b99fa65 100644 (file)
@@ -26,8 +26,8 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_cas';        // Full name of the plugin (used for diagnostics)
 
-$plugin->dependencies = array('auth_ldap' => 2017020700);
+$plugin->dependencies = array('auth_ldap' => 2017050500);
index fcb42b7..8bdf91d 100644 (file)
@@ -128,7 +128,7 @@ class login implements renderable, templatable {
         $data->error = $this->error;
         $data->forgotpasswordurl = $this->forgotpasswordurl->out(false);
         $data->hasidentityproviders = !empty($this->identityproviders);
-        $data->hasinstructions = !empty($this->instructions);
+        $data->hasinstructions = !empty($this->instructions) || $this->cansignup;
         $data->identityproviders = $identityproviders;
         list($data->instructions, $data->instructionsformat) = external_format_text($this->instructions, FORMAT_MOODLE,
             context_system::instance()->id);
index 08db727..00e18b9 100644 (file)
@@ -37,7 +37,8 @@ function xmldb_auth_db_upgrade($oldversion) {
 
     if ($oldversion < 2017032800) {
         // Convert info in config plugins from auth/db to auth_db
-        $DB->set_field('config_plugins', 'plugin', 'auth_db', array('plugin' => 'auth/db'));
+        upgrade_fix_config_auth_plugin_names('db');
+        upgrade_fix_config_auth_plugin_defaults('db');
         upgrade_plugin_savepoint(true, 2017032800, 'auth', 'db');
     }
 
index da5622a..54f3450 100644 (file)
@@ -135,7 +135,7 @@ if ($ADMIN->fulltree) {
         new lang_string('auth_dbupdateusers_description', 'auth_db'), 0, $yesno));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('db');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_dbextrafields', 'auth_db'),
             true, true, $authplugin->get_custom_user_profile_fields());
index f291cf8..a8d12b7 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017032800;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_db';         // Full name of the plugin (used for diagnostics)
index 36d6d1f..cd0ed73 100644 (file)
@@ -37,10 +37,10 @@ function xmldb_auth_email_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/email to auth_email.
-        $DB->set_field('config_plugins', 'plugin', 'auth_email', array('plugin' => 'auth/email'));
+        upgrade_fix_config_auth_plugin_names('email');
+        upgrade_fix_config_auth_plugin_defaults('email');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'email');
     }
 
     return true;
 }
-
index 88d7bc2..29d2849 100644 (file)
@@ -40,7 +40,7 @@ if ($ADMIN->fulltree) {
         new lang_string('auth_emailrecaptcha', 'auth_email'), 0, $options));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('email');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index 5787477..e6138fc 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die;
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_email';      // Full name of the plugin (used for diagnostics)
index 6909e6c..61a9bab 100644 (file)
@@ -37,7 +37,8 @@ function xmldb_auth_fc_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/fc to auth_fc.
-        $DB->set_field('config_plugins', 'plugin', 'auth_fc', array('plugin' => 'auth/fc'));
+        upgrade_fix_config_auth_plugin_names('fc');
+        upgrade_fix_config_auth_plugin_defaults('fc');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'fc');
     }
 
index 6039a64..ff3aa3f 100644 (file)
@@ -55,7 +55,7 @@ if ($ADMIN->fulltree) {
             get_string('changepasswordhelp', 'auth'), '', PARAM_URL));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('fc');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index 55fc7e5..386950a 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_fc';         // Full name of the plugin (used for diagnostics)
index 96dc3df..d26dac2 100644 (file)
@@ -37,10 +37,10 @@ function xmldb_auth_imap_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/imap to auth_imap.
-        $DB->set_field('config_plugins', 'plugin', 'auth_imap', array('plugin' => 'auth/imap'));
+        upgrade_fix_config_auth_plugin_names('imap');
+        upgrade_fix_config_auth_plugin_defaults('imap');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'imap');
     }
 
     return true;
 }
-
index b2478bd..fe8e7a1 100644 (file)
@@ -55,7 +55,7 @@ if ($ADMIN->fulltree) {
             get_string('changepasswordhelp', 'auth'), '', PARAM_URL));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('imap');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_fieldlocks_help', 'auth'), false, false);
 
index 5c102b0..b38709a 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_imap';       // Full name of the plugin (used for diagnostics)
index 7e6fd3b..7f59282 100644 (file)
@@ -276,7 +276,7 @@ class auth_plugin_ldap extends auth_plugin_base {
             }
             $ldapval = NULL;
             foreach ($values as $value) {
-                $entry = array_change_key_case($user_entry[0], CASE_LOWER);
+                $entry = $user_entry[0];
                 if (($value == 'dn') || ($value == 'distinguishedname')) {
                     $result[$key] = $user_dn;
                     continue;
@@ -634,7 +634,7 @@ class auth_plugin_ldap extends auth_plugin_base {
         if ($sr)  {
             $info = ldap_get_entries_moodle($ldapconnection, $sr);
             if (!empty ($info)) {
-                $info = array_change_key_case($info[0], CASE_LOWER);
+                $info = $info[0];
                 if (isset($info[$this->config->expireattr][0])) {
                     $expiretime = $this->ldap_expirationtime2unix($info[$this->config->expireattr][0], $ldapconnection, $user_dn);
                     if ($expiretime != 0) {
@@ -1201,7 +1201,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                 return false;
             }
 
-            $user_entry = array_change_key_case($user_entry[0], CASE_LOWER);
+            $user_entry = $user_entry[0];
 
             foreach ($attrmap as $key => $ldapkeys) {
                 $profilefield = '';
@@ -1369,7 +1369,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                 $sr = ldap_read($ldapconnection, $user_dn, '(objectClass=*)', $search_attribs);
                 if ($sr) {
                     $entry = ldap_get_entries_moodle($ldapconnection, $sr);
-                    $info = array_change_key_case($entry[0], CASE_LOWER);
+                    $info = $entry[0];
                     $newattrs = array();
                     if (!empty($info[$this->config->expireattr][0])) {
                         // Set expiration time only if passwordExpirationInterval is defined
@@ -1844,7 +1844,7 @@ class auth_plugin_ldap extends auth_plugin_base {
         }
 
         $entry = ldap_get_entries_moodle($ldapconn, $sr);
-        $info = array_change_key_case($entry[0], CASE_LOWER);
+        $info = $entry[0];
         $useraccountcontrol = $info['useraccountcontrol'][0];
         if ($useraccountcontrol & UF_DONT_EXPIRE_PASSWD) {
             // Password doesn't expire.
@@ -1889,17 +1889,17 @@ class auth_plugin_ldap extends auth_plugin_base {
         }
 
         $entry = ldap_get_entries_moodle($ldapconn, $sr);
-        $info = array_change_key_case($entry[0], CASE_LOWER);
+        $info = $entry[0];
         $domaindn = $info['defaultnamingcontext'][0];
 
         $sr = ldap_read ($ldapconn, $domaindn, '(objectClass=*)',
                          array('maxPwdAge'));
         $entry = ldap_get_entries_moodle($ldapconn, $sr);
-        $info = array_change_key_case($entry[0], CASE_LOWER);
+        $info = $entry[0];
         $maxpwdage = $info['maxpwdage'][0];
         if ($sr = ldap_read($ldapconn, $user_dn, '(objectClass=*)', array('msDS-ResultantPSO'))) {
             if ($entry = ldap_get_entries_moodle($ldapconn, $sr)) {
-                $info = array_change_key_case($entry[0], CASE_LOWER);
+                $info = $entry[0];
                 $userpso = $info['msds-resultantpso'][0];
 
                 // If a PSO exists, FGPP is being utilized.
@@ -1907,7 +1907,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                 if (!empty($userpso)) {
                     $sr = ldap_read($ldapconn, $userpso, '(objectClass=*)', array('msDS-MaximumPasswordAge'));
                     if ($entry = ldap_get_entries_moodle($ldapconn, $sr)) {
-                        $info = array_change_key_case($entry[0], CASE_LOWER);
+                        $info = $entry[0];
                         // Default value of msds-maximumpasswordage is 42 and is always set.
                         $maxpwdage = $info['msds-maximumpasswordage'][0];
                     }
index e6c02cd..355b719 100644 (file)
@@ -61,7 +61,8 @@ function xmldb_auth_ldap_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/ldap to auth_ldap.
-        $DB->set_field('config_plugins', 'plugin', 'auth_ldap', array('plugin' => 'auth/ldap'));
+        upgrade_fix_config_auth_plugin_names('ldap');
+        upgrade_fix_config_auth_plugin_defaults('ldap');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'ldap');
     }
 
index c1c828b..8efc99a 100644 (file)
@@ -79,7 +79,7 @@ $string['auth_ldap_passtype'] = 'Specify the format of new or changed passwords
 $string['auth_ldap_passtype_key'] = 'Password format';
 $string['auth_ldap_passwdexpire_settings'] = 'LDAP password expiration settings';
 $string['auth_ldap_preventpassindb'] = 'Select yes to prevent passwords from being stored in Moodle\'s DB.';
-$string['auth_ldap_preventpassindb_key'] = 'Don\'t cache passwords';
+$string['auth_ldap_preventpassindb_key'] = 'Prevent password caching';
 $string['auth_ldap_search_sub'] = 'Search users from subcontexts.';
 $string['auth_ldap_search_sub_key'] = 'Search subcontexts';
 $string['auth_ldap_server_settings'] = 'LDAP server settings';
index 85c5f79..5f62569 100644 (file)
@@ -295,7 +295,7 @@ if ($ADMIN->fulltree) {
     }
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('ldap');
     $help  = get_string('auth_ldapextrafields', 'auth_ldap');
     $help .= get_string('auth_updatelocal_expl', 'auth');
     $help .= get_string('auth_fieldlock_expl', 'auth');
index 8afa03a..5e96509 100644 (file)
@@ -25,6 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_ldap';       // Full name of the plugin (used for diagnostics)
index 1da5ecc..66901a2 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2016112900; // Requires this Moodle version (3.1).
+$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2017050500; // Requires this Moodle version (3.1).
 $plugin->component = 'auth_lti'; // Full name of the plugin (used for diagnostics).
index d9c6e3c..ca483c0 100644 (file)
@@ -49,7 +49,8 @@ function xmldb_auth_manual_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/manual to auth_manual.
-        $DB->set_field('config_plugins', 'plugin', 'auth_manual', array('plugin' => 'auth/manual'));
+        upgrade_fix_config_auth_plugin_names('manual');
+        upgrade_fix_config_auth_plugin_defaults('manual');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'manual');
     }
 
index cb546e0..95b29b1 100644 (file)
@@ -72,7 +72,7 @@ if ($ADMIN->fulltree) {
         new lang_string('expiration_warning_desc', 'auth_manual'), 0, $expirationwarningoptions));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('manual');
     display_auth_lock_options($settings, $authplugin->authtype,
         $authplugin->userfields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index 794366f..4411e68 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_manual';     // Full name of the plugin (used for diagnostics)
index 5cccdeb..46786fe 100644 (file)
@@ -48,7 +48,8 @@ function xmldb_auth_mnet_upgrade($oldversion) {
     // Put any upgrade step following this.
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/mnet to auth_mnet.
-        $DB->set_field('config_plugins', 'plugin', 'auth_mnet', array('plugin' => 'auth/mnet'));
+        upgrade_fix_config_auth_plugin_names('mnet');
+        upgrade_fix_config_auth_plugin_defaults('mnet');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'mnet');
     }
 
index 6bc7751..47b270e 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_mnet';       // Full name of the plugin (used for diagnostics)
index 129d8e9..8708487 100644 (file)
@@ -37,7 +37,8 @@ function xmldb_auth_nntp_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/nntp to auth_nntp.
-        $DB->set_field('config_plugins', 'plugin', 'auth_nntp', array('plugin' => 'auth/nntp'));
+        upgrade_fix_config_auth_plugin_names('nntp');
+        upgrade_fix_config_auth_plugin_defaults('nntp');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'nntp');
     }
 
index d318c68..bf475ee 100644 (file)
@@ -44,7 +44,7 @@ if ($ADMIN->fulltree) {
             get_string('changepasswordhelp', 'auth'), '', PARAM_URL));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('nntp');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index b94e05e..4ee22dc 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_nntp';       // Full name of the plugin (used for diagnostics)
index c7317df..e9c7094 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_nologin';    // Full name of the plugin (used for diagnostics)
index d54035e..56bf606 100644 (file)
@@ -37,10 +37,10 @@ function xmldb_auth_none_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/none to auth_none.
-        $DB->set_field('config_plugins', 'plugin', 'auth_none', array('plugin' => 'auth/none'));
+        upgrade_fix_config_auth_plugin_names('none');
+        upgrade_fix_config_auth_plugin_defaults('none');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'none');
     }
 
     return true;
 }
-
index 8f79897..28ff931 100644 (file)
@@ -31,7 +31,7 @@ if ($ADMIN->fulltree) {
         new lang_string('auth_nonedescription', 'auth_none')));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('none');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
         get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index 4530356..7a5f580 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_none';       // Full name of the plugin (used for diagnostics)
index 430abee..689ad1c 100644 (file)
@@ -39,6 +39,16 @@ defined('MOODLE_INTERNAL') || die();
  */
 class api {
 
+    /**
+     * Remove all linked logins that are using issuers that have been deleted.
+     *
+     * @param int $issuerid The issuer id of the issuer to check, or false to check all (defaults to all)
+     * @return boolean
+     */
+    public static function clean_orphaned_linked_logins($issuerid = false) {
+        return linked_login::delete_orphaned($issuerid);
+    }
+
     /**
      * List linked logins
      *
@@ -105,6 +115,10 @@ class api {
             $userid = $USER->id;
         }
 
+        if (linked_login::has_existing_issuer_match($issuer, $userinfo['username'])) {
+            throw new moodle_exception('alreadylinked', 'auth_oauth2');
+        }
+
         if (\core\session\manager::is_loggedinas()) {
             throw new moodle_exception('notwhileloggedinas', 'auth_oauth2');
         }
@@ -144,9 +158,8 @@ class api {
         $record->issuerid = $issuer->get('id');
         $record->username = $userinfo['username'];
         $record->userid = $userid;
-        $existing = linked_login::get_record((array)$record);
-        if ($existing) {
-            return false;
+        if (linked_login::has_existing_issuer_match($issuer, $userinfo['username'])) {
+            throw new moodle_exception('alreadylinked', 'auth_oauth2');
         }
         $record->email = $userinfo['email'];
         $record->confirmtoken = random_string(32);
@@ -239,6 +252,10 @@ class api {
         require_once($CFG->dirroot.'/user/profile/lib.php');
         require_once($CFG->dirroot.'/user/lib.php');
 
+        if (linked_login::has_existing_issuer_match($issuer, $userinfo['username'])) {
+            throw new moodle_exception('alreadylinked', 'auth_oauth2');
+        }
+
         $user = new stdClass();
         $user->username = $userinfo['username'];
         $user->email = $userinfo['email'];
@@ -319,4 +336,28 @@ class api {
 
         $login->delete();
     }
+
+    /**
+     * Delete linked logins for a user.
+     *
+     * @param \core\event\user_deleted $event
+     * @return boolean
+     */
+    public static function user_deleted(\core\event\user_deleted $event) {
+        global $DB;
+
+        $userid = $event->objectid;
+
+        return $DB->delete_records(linked_login::TABLE, ['userid' => $userid]);
+    }
+
+    /**
+     * Is the plugin enabled.
+     *
+     * @return bool
+     */
+    public static function is_enabled() {
+        $plugininfo = \core_plugin_manager::instance()->get_plugin_info('auth_oauth2');
+        return $plugininfo->is_enabled();
+    }
 }
index e4a56ca..96be2ae 100644 (file)
@@ -65,4 +65,49 @@ class linked_login extends persistent {
         );
     }
 
+    /**
+     * Check whether there are any valid linked accounts for this issuer
+     * and username combination.
+     *
+     * @param \core\oauth2\issuer $issuer The issuer
+     * @param string $username The username to check
+     */
+    public static function has_existing_issuer_match(\core\oauth2\issuer $issuer, $username) {
+        global $DB;
+
+        $where = "issuerid = :issuerid
+              AND username = :username
+              AND (confirmtokenexpires = 0 OR confirmtokenexpires > :maxexpiry)";
+
+        $count = $DB->count_records_select(static::TABLE, $where, [
+            'issuerid' => $issuer->get('id'),
+            'username' => $username,
+            'maxexpiry' => (new \DateTime('NOW'))->getTimestamp(),
+        ]);
+
+        return $count > 0;
+    }
+
+    /**
+     * Remove all linked logins that are using issuers that have been deleted.
+     *
+     * @param int $issuerid The issuer id of the issuer to check, or false to check all (defaults to all)
+     * @return boolean
+     */
+    public static function delete_orphaned($issuerid = false) {
+        global $DB;
+        // Delete any linked_login entries with a issuerid
+        // which does not exist in the issuer table.
+        // In the left join, the issuer id will be null
+        // where a match linked_login.issuerid is not found.
+        $sql = "DELETE FROM {" . self::TABLE . "}
+                 WHERE issuerid NOT IN (SELECT id FROM {" . \core\oauth2\issuer::TABLE . "})";
+        $params = [];
+        if (!empty($issuerid)) {
+            $sql .= ' AND issuerid = ?';
+            $params['issuerid'] = $issuerid;
+        }
+        return $DB->execute($sql, $params);
+    }
+
 }
index 54e3383..9b4a129 100644 (file)
@@ -34,6 +34,10 @@ $PAGE->set_context(context_system::instance());
 
 $auth = get_auth_plugin('oauth2');
 
+if (!\auth_oauth2\api::is_enabled()) {
+    throw new \moodle_exception('notenabled', 'auth_oauth2');
+}
+
 $confirmed = $auth->user_confirm($username, $usersecret);
 
 if ($confirmed == AUTH_CONFIRM_ALREADY) {
@@ -85,7 +89,7 @@ if ($confirmed == AUTH_CONFIRM_ALREADY) {
     echo $OUTPUT->footer();
     exit;
 } else {
-    print_error('invalidconfirmdata');
+    \core\notification::error(get_string('confirmationinvalid', 'auth_oauth2'));
 }
 
 redirect("$CFG->wwwroot/");
index 26182af..a05ba2a 100644 (file)
@@ -34,6 +34,10 @@ $redirect = optional_param('redirect', '', PARAM_LOCALURL);    // Where to redir
 $PAGE->set_url('/auth/oauth2/confirm-linkedlogin.php');
 $PAGE->set_context(context_system::instance());
 
+if (!\auth_oauth2\api::is_enabled()) {
+    throw new \moodle_exception('notenabled', 'auth_oauth2');
+}
+
 $confirmed = \auth_oauth2\api::confirm_link_login($userid, $username, $issuerid, $token);
 
 if ($confirmed) {
@@ -72,7 +76,7 @@ if ($confirmed) {
     echo $OUTPUT->footer();
     exit;
 } else {
-    print_error('invalidconfirmdata');
+    \core\notification::error(get_string('confirmationinvalid', 'auth_oauth2'));
 }
 
 redirect("$CFG->wwwroot/");
diff --git a/auth/oauth2/db/events.php b/auth/oauth2/db/events.php
new file mode 100644 (file)
index 0000000..b6f793c
--- /dev/null
@@ -0,0 +1,31 @@
+<?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/>.
+
+/**
+ * This file definies observers needed by the plugin.
+ *
+ * @package    auth_oauth2
+ * @copyright  2017 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// List of observers.
+$observers = [
+    [
+        'eventname'   => '\core\event\user_deleted',
+        'callback'    => '\auth_oauth2\api::user_deleted',
+    ],
+];
index fb6e6c4..75201f2 100644 (file)
@@ -22,7 +22,7 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['accountexists'] = 'A user already exists on this site with this username. If this is your account, login manually and link this link from your preferences page.';
+$string['accountexists'] = 'A user already exists on this site with this username. If this is your account, log in by entering your username and password and add it as a linked login via your preferences page.';
 $string['auth_oauth2description'] = 'OAuth 2 standards based authentication';
 $string['auth_oauth2settings'] = 'OAuth 2 authentication settings.';
 $string['confirmaccountemail'] = 'Hi {$a->fullname},
@@ -42,6 +42,7 @@ line at the top of your web browser window.
 If you need help, please contact the site administrator,
 {$a->admin}';
 $string['confirmaccountemailsubject'] = '{$a}: account confirmation';
+$string['confirmationinvalid'] = 'The confirmation link is either invalid, or has expired. Please start the login process again to generate a new confirmation email.';
 $string['confirmationpending'] = 'This account is pending email confirmation.';
 $string['confirmlinkedloginemail'] = 'Hi {$a->fullname},
 
@@ -65,21 +66,25 @@ $string['createaccountswarning'] = 'This authentication plugin allows users to c
 $string['createnewlinkedlogin'] = 'Link a new account ({$a})';
 $string['emailconfirmlink'] = 'Link your accounts';
 $string['emailconfirmlinksent'] = '<p>An existing account was found with this email address but it is not linked yet.</p>
-   <p>The accounts must be linked before you can login.</p>
-   <p>An email should have been sent to your address at <b>{$a}</b></p>
+   <p>The accounts must be linked before you can log in.</p>
+   <p>An email should have been sent to your address at <b>{$a}</b>.</p>
    <p>It contains easy instructions to link your accounts.</p>
-   <p>If you continue to have difficulty, contact the site administrator.</p>';
+   <p>If you have any difficulty, contact the site administrator.</p>';
 $string['info'] = 'External account';
 $string['issuer'] = 'OAuth 2 Service';
+$string['issuernologin'] = 'This issuer can not be used to login';
 $string['linkedlogins'] = 'Linked logins';
-$string['linkedloginshelp'] = 'Help with linked logins.';
+$string['linkedloginshelp'] = 'Help with linked logins';
 $string['loginerror_userincomplete'] = 'The user information returned did not contain a username and email address. The OAuth 2 service may be configured incorrectly.';
 $string['loginerror_nouserinfo'] = 'No user information was returned. The OAuth 2 service may be configured incorrectly.';
 $string['loginerror_invaliddomain'] = 'The email address is not allowed at this site.';
 $string['loginerror_authenticationfailed'] = 'The authentication process failed.';
-$string['loginerror_cannotcreateaccounts'] = 'The account does not exist and this site does not allow self-registration.';
+$string['loginerror_cannotcreateaccounts'] = 'An account with your email address could not be found.';
+$string['noissuersavailable'] = 'None of the configured OAuth2 services allow you to link login accounts';
 $string['notloggedindebug'] = 'The login attempt failed. Reason: {$a}';
 $string['notwhileloggedinas'] = 'Linked logins cannot be managed while logged in as another user.';
 $string['oauth2:managelinkedlogins'] = 'Manage own linked login accounts';
-$string['plugindescription'] = 'This authentication plugin displays a list of the configured identity providers on the moodle login page. Selecting an identity provider allows users to login with their credentials from an OAuth 2 provider.';
+$string['notenabled'] = 'Sorry, OAuth 2 authentication plugin is not enabled';
+$string['plugindescription'] = 'This authentication plugin displays a list of the configured identity providers on the login page. Selecting an identity provider allows users to login with their credentials from an OAuth 2 provider.';
 $string['pluginname'] = 'OAuth 2';
+$string['alreadylinked'] = 'This external account is already linked to an account on this site';
index 486ce0a..faa35da 100644 (file)
@@ -40,7 +40,7 @@ function auth_oauth2_extend_navigation_user_settings(navigation_node $useraccoun
                                                      context_course $coursecontext) {
     global $USER;
 
-    if (!\core\session\manager::is_loggedinas()) {
+    if (\auth_oauth2\api::is_enabled() && !\core\session\manager::is_loggedinas()) {
         if (has_capability('auth/oauth2:managelinkedlogins', $context) && $user->id == $USER->id) {
 
             $parent = $useraccount->parent->find('useraccount', navigation_node::TYPE_CONTAINER);
index 1228530..146e261 100644 (file)
@@ -35,12 +35,19 @@ $PAGE->set_heading($strheading);
 
 require_login();
 
+if (!\auth_oauth2\api::is_enabled()) {
+    throw new \moodle_exception('notenabled', 'auth_oauth2');
+}
+
 $action = optional_param('action', '', PARAM_ALPHAEXT);
 if ($action == 'new') {
     require_sesskey();
     $issuerid = required_param('issuerid', PARAM_INT);
     $issuer = \core\oauth2\api::get_issuer($issuerid);
 
+    if (!$issuer->is_authentication_supported() || !$issuer->get('showonloginpage') || !$issuer->get('enabled')) {
+        throw new \moodle_exception('issuernologin', 'auth_oauth2');
+    }
 
     // We do a login dance with this issuer.
     $addparams = ['action' => 'new', 'issuerid' => $issuerid, 'sesskey' => sesskey()];
@@ -58,8 +65,12 @@ if ($action == 'new') {
     $userinfo = $client->get_userinfo();
 
     if (!empty($userinfo)) {
-        \auth_oauth2\api::link_login($userinfo, $issuer);
-        redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
+        try {
+            \auth_oauth2\api::link_login($userinfo, $issuer);
+            redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
+        } catch (Exception $e) {
+            redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
+        }
     } else {
         redirect($PAGE->url, get_string('notloggedin', 'auth_oauth2'), null, \core\output\notification::NOTIFY_ERROR);
     }
@@ -76,24 +87,40 @@ $renderer = $PAGE->get_renderer('auth_oauth2');
 $linkedloginid = optional_param('id', '', PARAM_RAW);
 $linkedlogin = null;
 
-echo $OUTPUT->header();
-echo $OUTPUT->heading(get_string('linkedlogins', 'auth_oauth2'));
-echo $OUTPUT->doc_link('Linked_Logins', get_string('linkedloginshelp', 'auth_oauth2'));
-$linkedlogins = auth_oauth2\api::get_linked_logins();
-
-echo $renderer->linked_logins_table($linkedlogins);
+auth_oauth2\api::clean_orphaned_linked_logins();
 
 $issuers = \core\oauth2\api::get_all_issuers();
 
+$anyshowinloginpage = false;
+$issuerbuttons = array();
 foreach ($issuers as $issuer) {
-    if (!$issuer->is_authentication_supported()) {
+    if (!$issuer->is_authentication_supported() || !$issuer->get('showonloginpage') || !$issuer->get('enabled')) {
         continue;
     }
+    $anyshowinloginpage = true;
 
     $addparams = ['action' => 'new', 'issuerid' => $issuer->get('id'), 'sesskey' => sesskey(), 'logout' => true];
     $addurl = new moodle_url('/auth/oauth2/linkedlogins.php', $addparams);
-    echo $renderer->single_button($addurl, get_string('createnewlinkedlogin', 'auth_oauth2', s($issuer->get('name'))));
+    $issuerbuttons[$issuer->get('id')] = $renderer->single_button($addurl, get_string('createnewlinkedlogin', 'auth_oauth2', s($issuer->get('name'))));
+}
+
+if (!$anyshowinloginpage) {
+    // Just a notification that we can't make it.
+    $preferencesurl = new moodle_url('/user/preferences.php');
+    redirect($preferencesurl, get_string('noissuersavailable', 'auth_oauth2'), null, \core\output\notification::NOTIFY_WARNING);
 }
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('linkedlogins', 'auth_oauth2'));
+echo $OUTPUT->doc_link('Linked_Logins', get_string('linkedloginshelp', 'auth_oauth2'));
+$linkedlogins = auth_oauth2\api::get_linked_logins();
+
+echo $renderer->linked_logins_table($linkedlogins);
+
+foreach ($issuerbuttons as $issuerbutton) {
+    echo $issuerbutton;
+}
+
 echo $OUTPUT->footer();
 
 
index d1d8f79..5a9d7e8 100644 (file)
@@ -29,6 +29,10 @@ $wantsurl = new moodle_url(optional_param('wantsurl', '', PARAM_URL));
 
 require_sesskey();
 
+if (!\auth_oauth2\api::is_enabled()) {
+    throw new \moodle_exception('notenabled', 'auth_oauth2');
+}
+
 $issuer = new \core\oauth2\issuer($issuerid);
 
 $returnparams = ['wantsurl' => $wantsurl, 'sesskey' => sesskey(), 'id' => $issuerid];
index 51e15b7..cecdae5 100644 (file)
@@ -29,7 +29,7 @@ if ($ADMIN->fulltree) {
     $warning = $OUTPUT->notification(get_string('createaccountswarning', 'auth_oauth2'), 'warning');
     $settings->add(new admin_setting_heading('auth_oauth2/pluginname', '', $warning));
 
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('oauth2');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
diff --git a/auth/oauth2/tests/api_test.php b/auth/oauth2/tests/api_test.php
new file mode 100644 (file)
index 0000000..817430a
--- /dev/null
@@ -0,0 +1,101 @@
+<?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/>.
+
+/**
+ * Auth oauth2 api functions tests.
+ *
+ * @package     auth_oauth2
+ * @copyright   2017 Damyon Wiese
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+/**
+ * External auth oauth2 API tests.
+ *
+ * @package     auth_oauth2
+ * @copyright   2017 Damyon Wiese
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class auth_oauth2_external_testcase extends advanced_testcase {
+
+    /**
+     * Test the cleaning of orphaned linked logins for all issuers.
+     */
+    public function test_clean_orphaned_linked_logins() {
+        $this->resetAfterTest();
+        $this->setAdminUser();
+
+        $issuer = \core\oauth2\api::create_standard_issuer('google');
+        \core\oauth2\api::create_standard_issuer('microsoft');
+
+        $user = $this->getDataGenerator()->create_user();
+        $info = [];
+        $info['username'] = 'banana';
+        $info['email'] = 'banana@example.com';
+        \auth_oauth2\api::link_login($info, $issuer, $user->id, false);
+
+        \core\oauth2\api::delete_issuer($issuer->get('id'));
+
+        $linkedlogins = \auth_oauth2\api::get_linked_logins($user->id, $issuer);
+        $this->assertCount(1, $linkedlogins);
+
+        \auth_oauth2\api::clean_orphaned_linked_logins();
+
+        $linkedlogins = \auth_oauth2\api::get_linked_logins($user->id, $issuer);
+        $this->assertCount(0, $linkedlogins);
+
+        $match = \auth_oauth2\api::match_username_to_user('banana', $issuer);
+        $this->assertFalse($match);
+    }
+
+    /**
+     * Test the cleaning of orphaned linked logins for a specific issuer.
+     */
+    public function test_clean_orphaned_linked_logins_with_issuer_id() {
+        $this->resetAfterTest();
+        $this->setAdminUser();
+
+        $issuer1 = \core\oauth2\api::create_standard_issuer('google');
+        $issuer2 = \core\oauth2\api::create_standard_issuer('microsoft');
+
+        $user1 = $this->getDataGenerator()->create_user();
+        $info = [];
+        $info['username'] = 'banana';
+        $info['email'] = 'banana@example.com';
+        \auth_oauth2\api::link_login($info, $issuer1, $user1->id, false);
+
+        $user2 = $this->getDataGenerator()->create_user();
+        $info = [];
+        $info['username'] = 'apple';
+        $info['email'] = 'apple@example.com';
+        \auth_oauth2\api::link_login($info, $issuer2, $user2->id, false);
+
+        \core\oauth2\api::delete_issuer($issuer1->get('id'));
+
+        \auth_oauth2\api::clean_orphaned_linked_logins($issuer1->get('id'));
+
+        $linkedlogins = \auth_oauth2\api::get_linked_logins($user1->id, $issuer1);
+        $this->assertCount(0, $linkedlogins);
+
+        $linkedlogins = \auth_oauth2\api::get_linked_logins($user2->id, $issuer2);
+        $this->assertCount(1, $linkedlogins);
+    }
+
+}
index 2ff2041..2758934 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017032300;        // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires  = 2016112900;        // Requires this Moodle version.
+$plugin->version   = 2017051501;        // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2017050500;        // Requires this Moodle version.
 $plugin->component = 'auth_oauth2';       // Full name of the plugin (used for diagnostics).
index 3bff038..e69eb57 100644 (file)
@@ -37,7 +37,8 @@ function xmldb_auth_pam_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/pam to auth_pam.
-        $DB->set_field('config_plugins', 'plugin', 'auth_pam', array('plugin' => 'auth/pam'));
+        upgrade_fix_config_auth_plugin_names('pam');
+        upgrade_fix_config_auth_plugin_defaults('pam');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'pam');
     }
 
index 40ef60a..7a053a3 100644 (file)
@@ -31,7 +31,7 @@ if ($ADMIN->fulltree) {
         new lang_string('auth_pamdescription', 'auth_pam')));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('pam');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
         get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index 8cbc60d..3589681 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_pam';       // Full name of the plugin (used for diagnostics)
index 702fe51..e540c77 100644 (file)
@@ -37,7 +37,8 @@ function xmldb_auth_pop3_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/pop3 to auth_pop3.
-        $DB->set_field('config_plugins', 'plugin', 'auth_pop3', array('plugin' => 'auth/pop3'));
+        upgrade_fix_config_auth_plugin_names('pop3');
+        upgrade_fix_config_auth_plugin_defaults('pop3');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'pop3');
     }
 
index 5454f95..fa9c6a9 100644 (file)
@@ -59,7 +59,7 @@ if ($ADMIN->fulltree) {
             get_string('changepasswordhelp', 'auth'), '', PARAM_URL));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('pop3');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             get_string('auth_fieldlocks_help', 'auth'), false, false);
 }
index 7218aa2..a4b54ac 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_pop3';       // Full name of the plugin (used for diagnostics)
index 8b95151..38cec6c 100644 (file)
@@ -37,7 +37,8 @@ function xmldb_auth_shibboleth_upgrade($oldversion) {
 
     if ($oldversion < 2017020700) {
         // Convert info in config plugins from auth/shibboleth to auth_shibboleth.
-        $DB->set_field('config_plugins', 'plugin', 'auth_shibboleth', array('plugin' => 'auth/shibboleth'));
+        upgrade_fix_config_auth_plugin_names('shibboleth');
+        upgrade_fix_config_auth_plugin_defaults('shibboleth');
         upgrade_plugin_savepoint(true, 2017020700, 'auth', 'shibboleth');
     }
 
index 94db01f..c901378 100644 (file)
@@ -75,7 +75,7 @@ if ($ADMIN->fulltree) {
             get_string('changepasswordhelp', 'auth'), '', PARAM_URL));
 
     // Display locking / mapping of profile fields.
-    $authplugin = get_auth_plugin($this->name);
+    $authplugin = get_auth_plugin('shibboleth');
     display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
             '', true, false, $authplugin->get_custom_user_profile_fields());
 
index 9a9e3e2..e0aad0e 100644 (file)
@@ -25,6 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017020700;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_shibboleth'; // Full name of the plugin (used for diagnostics)
index def7fa2..fff9fdd 100644 (file)
@@ -3,8 +3,11 @@ information provided here is intended especially for developers.
 
 === 3.3 ===
 
-* Authentication plugins have been migrated to use the admin settings API.
-  Plugins should use a settings.php file to manage configurations rather than using the config.html files.
+* Authentication plugins have been migrated to use the admin settings API.  Plugins should use a settings.php file to
+  manage configurations rather than using the old config.html files. See how the helper function
+  upgrade_fix_config_auth_plugin_names() can be used to convert the legacy settings to the new ones. Another helper
+  function upgrade_fix_config_auth_plugin_defaults() can be used to populate the settings with default values so that
+  they are not falsely reported as newly added ones.
 * The function 'print_auth_lock_options' has been replaced by 'display_auth_lock_options' which uses the admin settings API.
   See auth_manual as an exmple of how it can be used.  More information can be found in MDL-12689.
 * The list of supported identity providers (SSO IdP) returned by the 'loginpage_idp_list' method (used to render the
index 576fdbd..416c4f0 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016120500;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2016112900;        // Requires this Moodle version
+$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires  = 2017050500;        // Requires this Moodle version
 $plugin->component = 'auth_webservice'; // Full name of the plugin (used for diagnostics)
index d57b8b7..29ff423 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'availability_completion';
index fc366c1..ad4638a 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'availability_date';
index 9556f99..5ce9b39 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'availability_grade';
index 54d5a0a..054a355 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'availability_group';
index 3b3017e..26d0460 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'availability_grouping';
index bf4e0e6..da86203 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2016120500;
-$plugin->requires = 2016112900;
+$plugin->version = 2017051500;
+$plugin->requires = 2017050500;
 $plugin->component = 'availability_profile';
index 0361f10..d8f66f6 100644 (file)
@@ -136,11 +136,11 @@ abstract class backup implements checksumable {
      * point is backup when some behavior/approach channged, in order to allow
      * conditional coding based on it.
      */
-    const VERSION = 2016120500;
+    const VERSION = 2017051500;
     /**
      * Usually same than major release zero version, mainly for informative/historic purposes.
      */
-    const RELEASE = '3.3';
+    const RELEASE = '3.4';
 }
 
 /*
index 8855d58..acdf34b 100644 (file)
@@ -863,8 +863,9 @@ class backup_calendarevents_structure_step extends backup_structure_step {
 
         $event = new backup_nested_element('event', array('id'), array(
                 'name', 'description', 'format', 'courseid', 'groupid', 'userid',
-                'repeatid', 'modulename', 'instance', 'eventtype', 'timestart',
-                'timeduration', 'visible', 'uuid', 'sequence', 'timemodified'));
+                'repeatid', 'modulename', 'instance', 'type', 'eventtype', 'timestart',
+                'timeduration', 'timesort', 'visible', 'uuid', 'sequence', 'timemodified',
+                'priority'));
 
         // Build the tree
         $events->add_child($event);
@@ -876,6 +877,14 @@ class backup_calendarevents_structure_step extends backup_structure_step {
                         AND (eventtype = 'course' OR eventtype = 'group')";
             $calendar_items_params = array('courseid'=>backup::VAR_COURSEID);
             $event->set_source_sql($calendar_items_sql, $calendar_items_params);
+        } else if ($this->name == 'activity_calendar') {
+            $params = array('instance' => backup::VAR_ACTIVITYID, 'modulename' => backup::VAR_MODNAME);
+            // If we don't want to include the userinfo in the backup then setting the courseid
+            // will filter out all of the user override events (which have a course id of zero).
+            if (!$this->get_setting_value('userinfo')) {
+                $params['courseid'] = backup::VAR_COURSEID;
+            }
+            $event->set_source_table('event', $params);
         } else {
             $event->set_source_table('event', array('courseid' => backup::VAR_COURSEID, 'instance' => backup::VAR_ACTIVITYID, 'modulename' => backup::VAR_MODNAME));
         }
index a0fc059..bfd741b 100644 (file)
@@ -1593,6 +1593,10 @@ class restore_section_structure_step extends restore_structure_step {
                 }
             }
             $newitemid = $DB->insert_record('course_sections', $section);
+            $section->id = $newitemid;
+
+            core\event\course_section_created::create_from_section($section)->trigger();
+
             $restorefiles = true;
 
         // Section exists, update non-empty information
@@ -1612,6 +1616,17 @@ class restore_section_structure_step extends restore_structure_step {
 
             $DB->update_record('course_sections', $section);
             $newitemid = $secrec->id;
+
+            // Trigger an event for course section update.
+            $event = \core\event\course_section_updated::create(
+                array(
+                    'objectid' => $section->id,
+                    'courseid' => $section->course,
+                    'context' => context_course::instance($section->course),
+                    'other' => array('sectionnum' => $section->section)
+                )
+            );
+            $event->trigger();
         }
 
         // Annotate the section mapping, with restorefiles option if needed
@@ -2638,6 +2653,16 @@ class restore_calendarevents_structure_step extends restore_structure_step {
         $data = (object)$data;
         $oldid = $data->id;
         $restorefiles = true; // We'll restore the files
+        // User overrides for activities are identified by having a courseid of zero with
+        // both a modulename and instance value set.
+        $isuseroverride = !$data->courseid && $data->modulename && $data->instance;
+
+        // If we don't want to include user data and this record is a user override event
+        // for an activity then we should not create it.
+        if (!$this->task->get_setting_value('userinfo') && $isuseroverride) {
+            return;
+        }
+
         // Find the userid and the groupid associated with the event.
         $data->userid = $this->get_mappingid('user', $data->userid);
         if ($data->userid === false) {
@@ -2673,18 +2698,23 @@ class restore_calendarevents_structure_step extends restore_structure_step {
                 'name'           => $data->name,
                 'description'    => $data->description,
                 'format'         => $data->format,
-                'courseid'       => $this->get_courseid(),
+                // User overrides in activities use a course id of zero. All other event types
+                // must use the mapped course id.
+                'courseid'       => $data->courseid ? $this->get_courseid() : 0,
                 'groupid'        => $data->groupid,
                 'userid'         => $data->userid,
                 'repeatid'       => $this->get_mappingid('event', $data->repeatid),
                 'modulename'     => $data->modulename,
+                'type'           => isset($data->type) ? $data->type : 0,
                 'eventtype'      => $data->eventtype,
                 'timestart'      => $this->apply_date_offset($data->timestart),
                 'timeduration'   => $data->timeduration,
+                'timesort'       => isset($data->timesort) ? $this->apply_date_offset($data->timesort) : null,
                 'visible'        => $data->visible,
                 'uuid'           => $data->uuid,
                 'sequence'       => $data->sequence,
-                'timemodified'    => $this->apply_date_offset($data->timemodified));
+                'timemodified'   => $this->apply_date_offset($data->timemodified),
+                'priority'       => isset($data->priority) ? $data->priority : null);
         if ($this->name == 'activity_calendar') {
             $params['instance'] = $this->task->get_activityid();
         } else {
@@ -2695,10 +2725,11 @@ class restore_calendarevents_structure_step extends restore_structure_step {
                  WHERE " . $DB->sql_compare_text('name', 255) . " = " . $DB->sql_compare_text('?', 255) . "
                    AND courseid = ?
                    AND modulename = ?
+                   AND instance = ?
                    AND timestart = ?
                    AND timeduration = ?
                    AND " . $DB->sql_compare_text('description', 255) . " = " . $DB->sql_compare_text('?', 255);
-        $arg = array ($params['name'], $params['courseid'], $params['modulename'], $params['timestart'], $params['timeduration'], $params['description']);
+        $arg = array ($params['name'], $params['courseid'], $params['modulename'], $params['instance'], $params['timestart'], $params['timeduration'], $params['description']);
         $result = $DB->record_exists_sql($sql, $arg);
         if (empty($result)) {
             $newitemid = $DB->insert_record('event', $params);
@@ -5497,4 +5528,4 @@ class restore_completion_defaults_structure_step extends restore_structure_step
         // Save id mapping for restoring associated events.
         $this->set_mapping('course_completion_defaults', $oldid, $newid);
     }
-}
\ No newline at end of file
+}
diff --git a/backup/moodle2/tests/backup_xml_transformer_test.php b/backup/moodle2/tests/backup_xml_transformer_test.php
new file mode 100644 (file)
index 0000000..55af176
--- /dev/null
@@ -0,0 +1,99 @@
+<?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 backup_xml_transformer class.
+ *
+ * @package     core_backup
+ * @subpackage  moodle2
+ * @category    backup
+ * @copyright   2017 Dmitrii Metelkin (dmitriim@catalyst-au.net)
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
+require_once($CFG->dirroot . '/backup/moodle2/backup_plan_builder.class.php');
+
+/**
+ * Tests for backup_xml_transformer.
+ *
+ * @package core_backup
+ * @copyright 2017 Dmitrii Metelkin (dmitriim@catalyst-au.net)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class backup_xml_transformer_testcase extends advanced_testcase {
+
+    /**
+     * Initial set up.
+     */
+    public function setUp() {
+        parent::setUp();
+
+        $this->resetAfterTest(true);
+    }
+
+    /**
+     * Data provider for ::test_filephp_links_replace.
+     *
+     * @return array
+     */
+    public function filephp_links_replace_data_provider() {
+        return array(
+            array('http://test.test/', 'http://test.test/'),
+            array('http://test.test/file.php/1', 'http://test.test/file.php/1'),
+            array('http://test.test/file.php/2/1.jpg', 'http://test.test/file.php/2/1.jpg'),
+            array('http://test.test/file.php/2', 'http://test.test/file.php/2'),
+            array('http://test.test/file.php/1/1.jpg', '$@FILEPHP@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php/1//1.jpg', '$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php?file=/1', '$@FILEPHP@$'),
+            array('http://test.test/file.php?file=/2/1.jpg', 'http://test.test/file.php?file=/2/1.jpg'),
+            array('http://test.test/file.php?file=/2', 'http://test.test/file.php?file=/2'),
+            array('http://test.test/file.php?file=/1/1.jpg', '$@FILEPHP@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php?file=/1//1.jpg', '$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php?file=%2f1', '$@FILEPHP@$'),
+            array('http://test.test/file.php?file=%2f2%2f1.jpg', 'http://test.test/file.php?file=%2f2%2f1.jpg'),
+            array('http://test.test/file.php?file=%2f2', 'http://test.test/file.php?file=%2f2'),
+            array('http://test.test/file.php?file=%2f1%2f1.jpg', '$@FILEPHP@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php?file=%2f1%2f%2f1.jpg', '$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php?file=%2F1', '$@FILEPHP@$'),
+            array('http://test.test/file.php?file=%2F2%2F1.jpg', 'http://test.test/file.php?file=%2F2%2F1.jpg'),
+            array('http://test.test/file.php?file=%2F2', 'http://test.test/file.php?file=%2F2'),
+            array('http://test.test/file.php?file=%2F1%2F1.jpg', '$@FILEPHP@$$@SLASH@$1.jpg'),
+            array('http://test.test/file.php?file=%2F1%2F%2F1.jpg', '$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'),
+        );
+    }
+
+    /**
+     * Test that backup_xml_transformer replaces file php links to $@FILEPHP@$.
+     *
+     * @dataProvider filephp_links_replace_data_provider
+     * @param string $content Testing content.
+     * @param string $expected Expected result.
+     */
+    public function test_filephp_links_replace($content, $expected) {
+        global $CFG;
+
+        $CFG->wwwroot = 'http://test.test';
+
+        $transformer = new backup_xml_transformer(1);
+
+        $this->assertEquals($expected, $transformer->process($content));
+    }
+
+}
index 500fa0c..add8d85 100644 (file)
@@ -60,17 +60,26 @@ class restore_structure_parser_processor extends grouped_parser_processor {
         } else if (strpos($cdata, '$@FILEPHP@$') === false) { // No $@FILEPHP@$, nothing to convert
             return $cdata;
         }
+
+        if ($CFG->slasharguments) {
+            $slash = '/';
+            $forcedownload = '?forcedownload=1';
+        } else {
+            $slash = '%2F';
+            $forcedownload = '&amp;forcedownload=1';
+        }
+
+        // We have to remove trailing slashes, otherwise file URLs will be restored with an extra slash.
+        $basefileurl = rtrim(moodle_url::make_legacyfile_url($this->courseid, null)->out(true), $slash);
         // Decode file.php calls
         $search = array ("$@FILEPHP@$");
-        $replace = array(moodle_url::make_legacyfile_url($this->courseid, null));
+        $replace = array($basefileurl);
         $result = str_replace($search, $replace, $cdata);
+
         // Now $@SLASH@$ and $@FORCEDOWNLOAD@$ MDL-18799
         $search = array('$@SLASH@$', '$@FORCEDOWNLOAD@$');
-        if ($CFG->slasharguments) {
-            $replace = array('/', '?forcedownload=1');
-        } else {
-            $replace = array('%2F', '&amp;forcedownload=1');
-        }
+        $replace = array($slash, $forcedownload);
+
         return str_replace($search, $replace, $result);
     }
 
diff --git a/backup/util/helper/tests/restore_structure_parser_processor_test.php b/backup/util/helper/tests/restore_structure_parser_processor_test.php
new file mode 100644 (file)
index 0000000..069163a
--- /dev/null
@@ -0,0 +1,132 @@
+<?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 restore_structure_parser_processor class.
+ *
+ * @package     core_backup
+ * @category    test
+ * @copyright   2017 Dmitrii Metelkin (dmitriim@catalyst-au.net)
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
+require_once($CFG->dirroot . '/backup/util/helper/restore_structure_parser_processor.class.php');
+
+/**
+ * Tests for restore_structure_parser_processor class.
+ *
+ * @package core_backup
+ * @copyright 2017 Dmitrii Metelkin (dmitriim@catalyst-au.net)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_structure_parser_processor_test extends advanced_testcase {
+
+    /**
+     * Initial set up.
+     */
+    public function setUp() {
+        parent::setUp();
+
+        $this->resetAfterTest(true);
+    }
+
+    /**
+     * Data provider for ::test_process_cdata.
+     *
+     * @return array
+     */
+    public function process_cdata_data_provider() {
+        return array(
+            array(null, null, true),
+            array("$@NULL@$", null, true),
+            array("$@NULL@$ ", "$@NULL@$ ", true),
+            array(1, 1, true),
+            array(" ", " ", true),
+            array("1", "1", true),
+            array("$@FILEPHP@$1.jpg", "$@FILEPHP@$1.jpg", true),
+            array(
+                "http://test.test/$@SLASH@$",
+                "http://test.test/$@SLASH@$",
+                true
+            ),
+            array(
+                "<a href='$@FILEPHP@$1.jpg'>Image</a>",
+                "<a href='http://test.test/file.php/11.jpg'>Image</a>",
+                true
+            ),
+            array(
+                "<a href='$@FILEPHP@$$@SLASH@$1.jpg'>Image</a>",
+                "<a href='http://test.test/file.php/1/1.jpg'>Image</a>",
+                true
+            ),
+            array(
+                "<a href='$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'>Image</a>",
+                "<a href='http://test.test/file.php/1//1.jpg'>Image</a>",
+                true
+            ),
+            array(
+                "<a href='$@FILEPHP@$1.jpg'>Image</a>",
+                "<a href='http://test.test/file.php?file=%2F11.jpg'>Image</a>",
+                false
+            ),
+            array(
+                "<a href='$@FILEPHP@$$@SLASH@$1.jpg'>Image</a>",
+                "<a href='http://test.test/file.php?file=%2F1%2F1.jpg'>Image</a>",
+                false
+            ),
+            array(
+                "<a href='$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'>Image</a>",
+                "<a href='http://test.test/file.php?file=%2F1%2F%2F1.jpg'>Image</a>",
+                false
+            ),
+            array(
+                "<a href='$@FILEPHP@$$@SLASH@$1.jpg$@FORCEDOWNLOAD@$'>Image</a>",
+                "<a href='http://test.test/file.php/1/1.jpg?forcedownload=1'>Image</a>",
+                true
+            ),
+            array(
+                "<a href='$@FILEPHP@$$@SLASH@$1.jpg$@FORCEDOWNLOAD@$'>Image</a>",
+                "<a href='http://test.test/file.php?file=%2F1%2F1.jpg&amp;forcedownload=1'>Image</a>",
+                false
+            ),
+        );
+    }
+
+    /**
+     * Test that restore_structure_parser_processor replaces $@FILEPHP@$ to correct file php links.
+     *
+     * @dataProvider process_cdata_data_provider
+     * @param string $content Testing content.
+     * @param string $expected Expected result.
+     * @param bool $slasharguments A value for $CFG->slasharguments setting.
+     */
+    public function test_process_cdata($content, $expected, $slasharguments) {
+        global $CFG;
+
+        $CFG->slasharguments = $slasharguments;
+        $CFG->wwwroot = 'http://test.test';
+
+        $processor = new restore_structure_parser_processor(1, 1);
+
+        $this->assertEquals($expected, $processor->process_cdata($content));
+    }
+
+}
index c5cb567..4988d52 100644 (file)
@@ -70,6 +70,7 @@ abstract class base_setting {
     protected $visibility; // visibility of the setting (setting_base::VISIBLE/setting_base::HIDDEN)
     protected $status; // setting_base::NOT_LOCKED/setting_base::LOCKED_BY_PERMISSION...
 
+    /** @var setting_dependency[] */
     protected $dependencies = array(); // array of dependent (observer) objects (usually setting_base ones)
     protected $dependenton = array();
 
@@ -201,6 +202,12 @@ abstract class base_setting {
     public function set_status($status) {
         $status = $this->validate_status($status);
 
+        if (($this->status == base_setting::LOCKED_BY_PERMISSION || $this->status == base_setting::LOCKED_BY_CONFIG)
+                && $status == base_setting::LOCKED_BY_HIERARCHY) {
+            // Lock by permission or config can not be overriden by lock by hierarchy.
+            return;
+        }
+
         // If the setting is being unlocked&