Merge branch 'MDL-68537-master' of git://github.com/jleyva/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Fri, 15 May 2020 01:04:21 +0000 (09:04 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Fri, 15 May 2020 02:36:54 +0000 (10:36 +0800)
925 files changed:
.eslintignore
.gherkin-lintrc
.nvmrc
.stylelintignore
.travis.yml
Gruntfile.js
admin/cli/adhoc_task.php [new file with mode: 0644]
admin/cli/cfg.php
admin/cli/scheduled_task.php [new file with mode: 0644]
admin/renderer.php
admin/settings/appearance.php
admin/settings/courses.php
admin/settings/development.php
admin/settings/h5p.php
admin/tests/behat/filter_users.feature
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js
admin/tool/lp/amd/build/menubar.min.js
admin/tool/lp/amd/build/menubar.min.js.map
admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder-min.js
admin/tool/messageinbound/lang/en/tool_messageinbound.php
admin/tool/mobile/classes/api.php
admin/tool/mobile/classes/external.php
admin/tool/mobile/db/services.php
admin/tool/mobile/lang/en/tool_mobile.php
admin/tool/mobile/lib.php
admin/tool/mobile/settings.php
admin/tool/mobile/tests/api_test.php
admin/tool/mobile/tests/externallib_test.php
admin/tool/mobile/version.php
admin/tool/monitor/yui/build/moodle-tool_monitor-dropdown/moodle-tool_monitor-dropdown-min.js
admin/tool/policy/styles.css
admin/tool/task/classes/run_from_cli.php
admin/tool/task/cli/adhoc_task.php
admin/tool/task/cli/schedule_task.php
admin/tool/task/lang/en/tool_task.php
admin/tool/task/renderer.php
admin/tool/task/schedule_task.php
admin/tool/uploadcourse/classes/course.php
admin/tool/uploadcourse/classes/helper.php
admin/tool/uploadcourse/classes/step2_form.php
admin/tool/uploadcourse/index.php
admin/tool/uploadcourse/lang/en/tool_uploadcourse.php
admin/tool/uploadcourse/tests/behat/create.feature
admin/tool/uploadcourse/tests/behat/update.feature
admin/tool/uploadcourse/tests/course_test.php
admin/tool/uploadcourse/tests/fixtures/courses_custom_fields.csv [new file with mode: 0644]
admin/tool/uploadcourse/tests/helper_test.php
admin/tool/uploaduser/tests/behat/upload_users.feature
admin/tool/usertours/amd/build/tour.min.js
admin/tool/usertours/amd/build/tour.min.js.map
admin/tool/xmldb/actions/view_xml/view_xml.class.php
admin/tool/xmldb/lang/en/tool_xmldb.php
admin/user/user_bulk_download.php
availability/condition/completion/classes/condition.php
availability/condition/completion/classes/frontend.php
availability/condition/completion/db/caches.php [new file with mode: 0644]
availability/condition/completion/lang/en/availability_completion.php
availability/condition/completion/tests/behat/availability_completion_previous.feature [new file with mode: 0644]
availability/condition/completion/tests/condition_test.php
availability/condition/completion/version.php
availability/condition/completion/yui/build/moodle-availability_completion-form/moodle-availability_completion-form-min.js
availability/condition/date/yui/build/moodle-availability_date-form/moodle-availability_date-form-min.js
availability/condition/grade/yui/build/moodle-availability_grade-form/moodle-availability_grade-form-min.js
availability/condition/group/yui/build/moodle-availability_group-form/moodle-availability_group-form-min.js
availability/condition/grouping/yui/build/moodle-availability_grouping-form/moodle-availability_grouping-form-min.js
availability/condition/profile/yui/build/moodle-availability_profile-form/moodle-availability_profile-form-min.js
availability/tests/fixtures/mock_info_module.php [new file with mode: 0644]
availability/tests/fixtures/mock_info_section.php [new file with mode: 0644]
availability/yui/build/moodle-core_availability-form/moodle-core_availability-form-min.js
backup/moodle2/backup_course_task.class.php
backup/moodle2/backup_root_task.class.php
backup/moodle2/backup_settingslib.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_course_task.class.php
backup/moodle2/restore_root_task.class.php
backup/moodle2/restore_settingslib.php
backup/moodle2/restore_stepslib.php
backup/moodle2/tests/moodle2_test.php
backup/util/dbops/backup_controller_dbops.class.php
backup/util/dbops/restore_controller_dbops.class.php
backup/util/ui/tests/behat/import_contentbank_content.feature [new file with mode: 0644]
backup/util/ui/tests/behat/restore_moodle2_courses_settings.feature
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js
backup/util/ui/yui/build/moodle-backup-confirmcancel/moodle-backup-confirmcancel-min.js
badges/tests/behat/award_badge_groups.feature
blocks/moodleblock.class.php
blocks/navigation/amd/build/ajax_response_renderer.min.js
blocks/navigation/amd/build/ajax_response_renderer.min.js.map
blocks/recent_activity/renderer.php
blocks/recent_activity/styles.css
blocks/recentlyaccesseditems/tests/behat/block_recentlyaccesseditems_dashboard.feature
blocks/settings/styles.css
blocks/site_main_menu/tests/behat/add_url.feature
cache/classes/helper.php
cache/classes/loaders.php
cache/classes/store.php
cache/tests/cache_test.php
cache/upgrade.txt
calendar/amd/build/crud.min.js
calendar/amd/build/crud.min.js.map
calendar/amd/build/modal_delete.min.js
calendar/amd/build/modal_delete.min.js.map
calendar/amd/build/view_manager.min.js
calendar/amd/build/view_manager.min.js.map
calendar/amd/src/crud.js
calendar/amd/src/modal_delete.js
completion/classes/api.php
composer.json
composer.lock
config-dist.php
contentbank/amd/build/actions.min.js
contentbank/amd/build/actions.min.js.map
contentbank/amd/build/search.min.js [new file with mode: 0644]
contentbank/amd/build/search.min.js.map [new file with mode: 0644]
contentbank/amd/build/selectors.min.js [new file with mode: 0644]
contentbank/amd/build/selectors.min.js.map [new file with mode: 0644]
contentbank/amd/src/actions.js
contentbank/amd/src/search.js [new file with mode: 0644]
contentbank/amd/src/selectors.js [new file with mode: 0644]
contentbank/classes/content.php
contentbank/classes/contentbank.php
contentbank/classes/contenttype.php
contentbank/classes/external/rename_content.php [new file with mode: 0644]
contentbank/classes/output/bankcontent.php
contentbank/classes/privacy/provider.php
contentbank/contenttype/h5p/classes/contenttype.php
contentbank/contenttype/h5p/lang/en/contenttype_h5p.php
contentbank/contenttype/h5p/tests/behat/admin_upload_content.feature
contentbank/contenttype/h5p/tests/behat/manage_content.feature [new file with mode: 0644]
contentbank/contenttype/h5p/tests/content_h5p_test.php
contentbank/index.php
contentbank/templates/bankcontent.mustache
contentbank/templates/bankcontent/search.mustache [new file with mode: 0644]
contentbank/templates/bankcontent/toolbar.mustache [moved from contentbank/templates/toolbar.mustache with 91% similarity]
contentbank/templates/renamecontent.mustache [new file with mode: 0644]
contentbank/tests/behat/access_permissions.feature
contentbank/tests/behat/delete_content.feature
contentbank/tests/behat/events.feature [new file with mode: 0644]
contentbank/tests/behat/search_content.feature [new file with mode: 0644]
contentbank/tests/content_test.php
contentbank/tests/contentbank_test.php
contentbank/tests/contenttype_test.php
contentbank/tests/external/delete_content_test.php
contentbank/tests/external/rename_content_test.php [new file with mode: 0644]
contentbank/tests/privacy_test.php [new file with mode: 0644]
contentbank/upload.php
contentbank/view.php
course/amd/build/activitychooser.min.js
course/amd/build/activitychooser.min.js.map
course/amd/build/local/activitychooser/dialogue.min.js
course/amd/build/local/activitychooser/dialogue.min.js.map
course/amd/src/activitychooser.js
course/amd/src/local/activitychooser/dialogue.js
course/classes/management_renderer.php
course/format/renderer.php
course/format/singleactivity/tests/behat/edit_format_course.feature
course/format/topics/styles.css [deleted file]
course/format/weeks/styles.css [deleted file]
course/recent.php
course/renderer.php
course/tests/behat/activity_chooser.feature
course/tests/behat/category_resort.feature
course/tests/behat/course_category_management_listing.feature
course/tests/behat/course_resort.feature
course/tests/behat/create_delete_course.feature
course/tests/behat/edit_settings.feature
course/yui/build/moodle-course-categoryexpander/moodle-course-categoryexpander-min.js
course/yui/build/moodle-course-coursebase/moodle-course-coursebase-min.js
course/yui/build/moodle-course-dragdrop/moodle-course-dragdrop-debug.js
course/yui/build/moodle-course-dragdrop/moodle-course-dragdrop-min.js
course/yui/build/moodle-course-dragdrop/moodle-course-dragdrop.js
course/yui/build/moodle-course-formatchooser/moodle-course-formatchooser-min.js
course/yui/build/moodle-course-management/moodle-course-management-debug.js
course/yui/build/moodle-course-management/moodle-course-management-min.js
course/yui/build/moodle-course-management/moodle-course-management.js
course/yui/build/moodle-course-util-base/moodle-course-util-base-min.js
course/yui/build/moodle-course-util-cm/moodle-course-util-cm-min.js
course/yui/build/moodle-course-util-section/moodle-course-util-section-min.js
course/yui/src/dragdrop/js/section.js
course/yui/src/management/build.json
course/yui/src/management/js/category.js
course/yui/src/management/js/console.js
course/yui/src/management/js/course.js
course/yui/src/management/js/dd.js
course/yui/src/management/js/item.js
course/yui/src/management/js/shared.js [new file with mode: 0644]
customfield/classes/data_controller.php
customfield/classes/field_controller.php
customfield/classes/handler.php
customfield/field/date/classes/field_controller.php
customfield/field/date/tests/behat/field.feature
customfield/field/date/tests/plugin_test.php
customfield/field/select/classes/field_controller.php
customfield/field/select/tests/plugin_test.php
customfield/field/textarea/classes/data_controller.php
customfield/tests/behat/unique_field.feature
dataformat/pdf/classes/writer.php
dataformat/upgrade.txt
enrol/database/settings.php
enrol/database/upgrade.txt
enrol/guest/tests/behat/guest_access.feature
filter/glossary/yui/build/moodle-filter_glossary-autolinker/moodle-filter_glossary-autolinker-min.js
filter/mathjaxloader/db/upgrade.php
filter/mathjaxloader/readme_moodle.txt
filter/mathjaxloader/settings.php
filter/mathjaxloader/version.php
filter/mathjaxloader/yui/build/moodle-filter_mathjaxloader-loader/moodle-filter_mathjaxloader-loader-min.js
grade/grading/form/guide/lang/en/gradingform_guide.php
grade/grading/form/guide/templates/grades/grader/gradingpanel.mustache
grade/grading/form/rubric/renderer.php
grade/grading/form/rubric/styles.css
grade/grading/form/rubric/tests/behat/grade_calculation.feature
grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js
grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js
grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js
grade/report/grader/yui/src/gradereporttable/js/floatingheaders.js
grade/report/history/yui/build/moodle-gradereport_history-userselector/moodle-gradereport_history-userselector-min.js
grade/tests/behat/grade_override_letter.feature
group/tests/behat/create_groups.feature
group/tests/behat/group_description.feature
h5p/classes/core.php
h5p/classes/editor.php
h5p/classes/editor_ajax.php
h5p/classes/editor_framework.php
h5p/classes/helper.php
h5p/classes/local/library/autoloader.php
h5p/classes/local/library/handler.php
h5p/h5plib/v124/joubel/editor/readme_moodle.txt
h5p/h5plib/v124/lang/en/h5plib_v124.php
h5p/tests/editor_ajax_test.php
h5p/tests/editor_framework_test.php
h5p/tests/editor_test.php
h5p/tests/generator/lib.php
h5p/tests/h5p_core_test.php
h5p/tests/local/library/handler_test.php [new file with mode: 0644]
install/lang/en_us_wp/langconfig.php [new file with mode: 0644]
install/lang/fr/error.php
install/lang/nl_wp/langconfig.php [new file with mode: 0644]
install/lang/pt_br_wp/langconfig.php [new file with mode: 0644]
install/lang/scn/langconfig.php [new file with mode: 0644]
lang/en/admin.php
lang/en/backup.php
lang/en/cache.php
lang/en/contentbank.php
lang/en/course.php
lang/en/enrol.php
lang/en/error.php
lang/en/h5p.php
lang/en/moodle.php
lang/en/repository.php
lang/en/role.php
lib/accesslib.php
lib/adminlib.php
lib/amd/build/adapter.min.js
lib/amd/build/adapter.min.js.map
lib/amd/build/chart_base.min.js
lib/amd/build/chart_base.min.js.map
lib/amd/build/chart_series.min.js
lib/amd/build/chart_series.min.js.map
lib/amd/build/chartjs-lazy.min.js
lib/amd/build/chartjs-lazy.min.js.map
lib/amd/build/custom_interaction_events.min.js
lib/amd/build/custom_interaction_events.min.js.map
lib/amd/build/drawer.min.js
lib/amd/build/drawer.min.js.map
lib/amd/build/emoji/auto_complete.min.js
lib/amd/build/emoji/auto_complete.min.js.map
lib/amd/build/emoji/picker.min.js
lib/amd/build/emoji/picker.min.js.map
lib/amd/build/form-autocomplete.min.js
lib/amd/build/form-autocomplete.min.js.map
lib/amd/build/local/modal/alert.min.js [new file with mode: 0644]
lib/amd/build/local/modal/alert.min.js.map [new file with mode: 0644]
lib/amd/build/loglevel.min.js
lib/amd/build/loglevel.min.js.map
lib/amd/build/modal.min.js
lib/amd/build/modal.min.js.map
lib/amd/build/modal_cancel.min.js
lib/amd/build/modal_cancel.min.js.map
lib/amd/build/modal_factory.min.js
lib/amd/build/modal_factory.min.js.map
lib/amd/build/modal_registry.min.js
lib/amd/build/modal_registry.min.js.map
lib/amd/build/modal_save_cancel.min.js
lib/amd/build/modal_save_cancel.min.js.map
lib/amd/build/mustache.min.js
lib/amd/build/mustache.min.js.map
lib/amd/build/notification.min.js
lib/amd/build/notification.min.js.map
lib/amd/build/popper.min.js
lib/amd/build/popper.min.js.map
lib/amd/build/prefetch.min.js [new file with mode: 0644]
lib/amd/build/prefetch.min.js.map [new file with mode: 0644]
lib/amd/build/sortable_list.min.js
lib/amd/build/sortable_list.min.js.map
lib/amd/build/str.min.js
lib/amd/build/str.min.js.map
lib/amd/build/templates.min.js
lib/amd/build/templates.min.js.map
lib/amd/build/toast.min.js
lib/amd/build/toast.min.js.map
lib/amd/build/truncate.min.js
lib/amd/build/truncate.min.js.map
lib/amd/build/user_date.min.js
lib/amd/build/user_date.min.js.map
lib/amd/src/custom_interaction_events.js
lib/amd/src/form-autocomplete.js
lib/amd/src/local/modal/alert.js [new file with mode: 0644]
lib/amd/src/modal.js
lib/amd/src/modal_cancel.js
lib/amd/src/modal_factory.js
lib/amd/src/modal_registry.js
lib/amd/src/modal_save_cancel.js
lib/amd/src/notification.js
lib/amd/src/prefetch.js [new file with mode: 0644]
lib/amd/src/templates.js
lib/amd/src/user_date.js
lib/antivirus/clamav/adminlib.php
lib/antivirus/clamav/classes/scanner.php
lib/antivirus/clamav/lang/en/antivirus_clamav.php
lib/behat/classes/behat_core_generator.php
lib/behat/lib.php
lib/classes/component.php
lib/classes/dataformat.php [new file with mode: 0644]
lib/classes/dataformat/base.php
lib/classes/dataformat/spout_base.php
lib/classes/dml/sql_join.php
lib/classes/event/contentbank_content_created.php [new file with mode: 0644]
lib/classes/event/contentbank_content_deleted.php [new file with mode: 0644]
lib/classes/event/contentbank_content_updated.php [new file with mode: 0644]
lib/classes/event/contentbank_content_uploaded.php [new file with mode: 0644]
lib/classes/event/contentbank_content_viewed.php [new file with mode: 0644]
lib/classes/hub/registration.php
lib/classes/ip_utils.php
lib/classes/plugin_manager.php
lib/classes/qrcode.php [moved from enrol/database/settingslib.php with 56% similarity]
lib/classes/session/redis.php
lib/classes/task/completion_daily_task.php
lib/classes/task/h5p_get_content_types_task.php
lib/classes/task/manager.php
lib/classes/task/messaging_cleanup_task.php
lib/cronlib.php
lib/dataformatlib.php
lib/db/access.php
lib/db/caches.php
lib/db/services.php
lib/db/upgrade.php
lib/deprecatedlib.php
lib/editor/atto/plugins/accessibilitychecker/tests/behat/accessibilitychecker.feature
lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-min.js
lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-min.js
lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-min.js
lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-min.js
lib/editor/atto/plugins/bold/tests/behat/bold.feature
lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-debug.js
lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-min.js
lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button.js
lib/editor/atto/plugins/bold/yui/src/button/js/button.js
lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js
lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-min.js
lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-min.js
lib/editor/atto/plugins/emojipicker/yui/build/moodle-atto_emojipicker-button/moodle-atto_emojipicker-button-min.js
lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-min.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-min.js
lib/editor/atto/plugins/h5p/yui/build/moodle-atto_h5p-button/moodle-atto_h5p-button-min.js
lib/editor/atto/plugins/html/yui/build/moodle-atto_html-beautify/moodle-atto_html-beautify-min.js
lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-min.js
lib/editor/atto/plugins/html/yui/build/moodle-atto_html-codemirror/moodle-atto_html-codemirror-min.js
lib/editor/atto/plugins/image/lang/en/atto_image.php
lib/editor/atto/plugins/image/tests/behat/image.feature
lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js
lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js
lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
lib/editor/atto/plugins/image/yui/src/button/js/button.js
lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-min.js
lib/editor/atto/plugins/italic/tests/behat/italic.feature
lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-debug.js
lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-min.js
lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button.js
lib/editor/atto/plugins/italic/yui/src/button/js/button.js
lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js
lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-min.js
lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-min.js
lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js
lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-min.js
lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-min.js
lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-button/moodle-atto_recordrtc-button-min.js
lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js
lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-min.js
lib/editor/atto/plugins/strike/tests/behat/strike.feature
lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-debug.js
lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-min.js
lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button.js
lib/editor/atto/plugins/strike/yui/src/button/js/button.js
lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-min.js
lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-min.js
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js
lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-min.js
lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-min.js
lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-min.js
lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-min.js
lib/editor/atto/tests/behat/customtoolbar.feature
lib/editor/atto/tests/behat/disablecontrol.feature
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js
lib/editor/atto/yui/build/moodle-editor_atto-menu/moodle-editor_atto-menu-min.js
lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin-debug.js
lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin-min.js
lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin.js
lib/editor/atto/yui/build/moodle-editor_atto-rangy/moodle-editor_atto-rangy-min.js
lib/editor/atto/yui/src/editor/js/autosave.js
lib/editor/atto/yui/src/editor/js/clean.js
lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js
lib/editor/atto/yui/src/editor/js/selection.js
lib/editor/atto/yui/src/editor/js/styling.js
lib/editor/atto/yui/src/editor/js/toolbar-keyboardnav.js
lib/external/externallib.php
lib/external/tests/external_test.php
lib/form/checkbox.php
lib/form/course.php
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/form/duration.php
lib/form/tests/behat/autocomplete.feature
lib/form/tests/behat/behat_core_form.php [new file with mode: 0644]
lib/form/tests/behat/fixtures/repeat_defaults_form.php [new file with mode: 0644]
lib/form/tests/behat/repeat_defaults.feature [new file with mode: 0644]
lib/form/tests/course_test.php [new file with mode: 0644]
lib/form/tests/fixtures/autocomplete-disabledif.php [new file with mode: 0644]
lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-debug.js
lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-min.js
lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector.js
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js
lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js
lib/form/yui/src/dateselector/build.json
lib/form/yui/src/dateselector/js/calendar.js
lib/form/yui/src/dateselector/js/dateselector.js
lib/form/yui/src/dateselector/js/moodlecalendar.js
lib/form/yui/src/dateselector/js/shared.js [new file with mode: 0644]
lib/formslib.php
lib/grade/grade_category.php
lib/grade/grade_grade.php
lib/grade/grade_item.php
lib/grouplib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/pagelib.php
lib/plist/LICENSE [new file with mode: 0644]
lib/plist/README.md [new file with mode: 0644]
lib/plist/classes/CFPropertyList/CFBinaryPropertyList.php [new file with mode: 0644]
lib/plist/classes/CFPropertyList/CFPropertyList.php [new file with mode: 0644]
lib/plist/classes/CFPropertyList/CFType.php [new file with mode: 0644]
lib/plist/classes/CFPropertyList/CFTypeDetector.php [new file with mode: 0644]
lib/plist/classes/CFPropertyList/IOException.php [new file with mode: 0644]
lib/plist/classes/CFPropertyList/PListException.php [new file with mode: 0644]
lib/plist/readme_moodle.txt [new file with mode: 0644]
lib/questionlib.php
lib/table/amd/build/dynamic.min.js
lib/table/amd/build/dynamic.min.js.map
lib/table/amd/build/local/dynamic/events.min.js [new file with mode: 0644]
lib/table/amd/build/local/dynamic/events.min.js.map [new file with mode: 0644]
lib/table/amd/build/local/dynamic/repository.min.js
lib/table/amd/build/local/dynamic/repository.min.js.map
lib/table/amd/build/local/dynamic/selectors.min.js
lib/table/amd/build/local/dynamic/selectors.min.js.map
lib/table/amd/src/dynamic.js
lib/table/amd/src/local/dynamic/events.js [moved from mod/quiz/accessrule/safebrowser/version.php with 70% similarity]
lib/table/amd/src/local/dynamic/repository.js
lib/table/amd/src/local/dynamic/selectors.js
lib/table/classes/dynamic.php
lib/table/classes/external/dynamic/fetch.php
lib/table/tests/external/dynamic/fetch_test.php
lib/tablelib.php
lib/templates/drawer.mustache
lib/templates/local/modal/alert.mustache [new file with mode: 0644]
lib/templates/single_select.mustache
lib/templates/time_element.mustache [new file with mode: 0644]
lib/templates/url_select.mustache
lib/testing/generator/block_generator.php
lib/testing/generator/module_generator.php
lib/testing/generator/repository_generator.php
lib/tests/accesslib_test.php
lib/tests/adminlib_test.php [new file with mode: 0644]
lib/tests/behat/action_modal.feature
lib/tests/behat/alpha_chooser.feature
lib/tests/behat/behat_navigation.php
lib/tests/behat/largeforms.feature
lib/tests/behat/locking.feature
lib/tests/behat/permissionmanager.feature
lib/tests/behat/readonlyform.feature
lib/tests/behat/securelayout.feature
lib/tests/completion_daily_task_test.php [new file with mode: 0644]
lib/tests/dataformat_test.php [new file with mode: 0644]
lib/tests/event/contentbank_content_created_test.php [new file with mode: 0644]
lib/tests/event/contentbank_content_deleted_test.php [new file with mode: 0644]
lib/tests/event/contentbank_content_updated_test.php [new file with mode: 0644]
lib/tests/event/contentbank_content_uploaded_test.php [new file with mode: 0644]
lib/tests/event/contentbank_content_viewed_test.php [new file with mode: 0644]
lib/tests/grouplib_test.php
lib/tests/moodlelib_test.php
lib/tests/qrcode_test.php [new file with mode: 0644]
lib/tests/questionlib_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
lib/xapi/classes/local/statement.php
lib/xapi/classes/local/statement/item_attachment.php [new file with mode: 0644]
lib/xapi/classes/local/statement/item_context.php [moved from mod/quiz/accessrule/safebrowser/classes/privacy/provider.php with 56% similarity]
lib/xapi/classes/local/statement/item_result.php [new file with mode: 0644]
lib/xapi/classes/local/statement/item_score.php [new file with mode: 0644]
lib/xapi/tests/local/statement/item_attachment_test.php [new file with mode: 0644]
lib/xapi/tests/local/statement/item_context_test.php [new file with mode: 0644]
lib/xapi/tests/local/statement/item_result_test.php [new file with mode: 0644]
lib/xapi/tests/local/statement/item_score_test.php [new file with mode: 0644]
lib/xapi/tests/local/statement_test.php
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks.js
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js
lib/yui/build/moodle-core-event/moodle-core-event-min.js
lib/yui/build/moodle-core-formchangechecker/moodle-core-formchangechecker-min.js
lib/yui/build/moodle-core-handlebars/moodle-core-handlebars-min.js
lib/yui/build/moodle-core-languninstallconfirm/moodle-core-languninstallconfirm-debug.js
lib/yui/build/moodle-core-languninstallconfirm/moodle-core-languninstallconfirm-min.js
lib/yui/build/moodle-core-languninstallconfirm/moodle-core-languninstallconfirm.js
lib/yui/build/moodle-core-lockscroll/moodle-core-lockscroll-min.js
lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-min.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-debug.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception-min.js
lib/yui/build/moodle-core-notification-ajaxexception/moodle-core-notification-ajaxexception.js
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-debug.js
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert-min.js
lib/yui/build/moodle-core-notification-alert/moodle-core-notification-alert.js
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-debug.js
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm-min.js
lib/yui/build/moodle-core-notification-confirm/moodle-core-notification-confirm.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-debug.js
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception-min.js
lib/yui/build/moodle-core-notification-exception/moodle-core-notification-exception.js
lib/yui/build/moodle-core-notification/moodle-core-notification-min.js
lib/yui/build/moodle-core-popuphelp/moodle-core-popuphelp-min.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-min.js
lib/yui/build/moodle-core-widget-focusafterclose/moodle-core-widget-focusafterclose-min.js
lib/yui/src/blocks/build.json
lib/yui/src/blocks/js/blockregion.js
lib/yui/src/blocks/js/blocks.js
lib/yui/src/blocks/js/manager.js
lib/yui/src/blocks/js/shared.js [new file with mode: 0644]
lib/yui/src/languninstallconfirm/js/languninstallconfirm.js
lib/yui/src/notification/js/ajaxexception.js
lib/yui/src/notification/js/alert.js
lib/yui/src/notification/js/confirm.js
lib/yui/src/notification/js/dialogue.js
lib/yui/src/notification/js/exception.js
lib/yui/src/notification/js/info.js
lib/yui/src/notification/js/shared.js
media/player/videojs/amd/build/Youtube-lazy.min.js
media/player/videojs/amd/build/Youtube-lazy.min.js.map
media/player/videojs/amd/build/video-lazy.min.js
media/player/videojs/amd/build/video-lazy.min.js.map
media/player/videojs/amd/build/videojs-flash-lazy.min.js
media/player/videojs/amd/build/videojs-flash-lazy.min.js.map
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/videojs-flash-lazy.js
media/player/videojs/classes/plugin.php
media/player/videojs/readme_moodle.txt
media/player/videojs/tests/player_test.php
media/player/videojs/thirdpartylibs.xml
media/player/videojs/videojs/lang/ar.js
media/player/videojs/videojs/lang/ar.json
media/player/videojs/videojs/lang/de.js
media/player/videojs/videojs/lang/de.json
media/player/videojs/videojs/lang/en.js
media/player/videojs/videojs/lang/en.json
media/player/videojs/videojs/lang/fa.js
media/player/videojs/videojs/lang/fa.json
media/player/videojs/videojs/lang/nb.js
media/player/videojs/videojs/lang/nb.json
media/player/videojs/videojs/lang/nn.js
media/player/videojs/videojs/lang/nn.json
message/amd/build/message_drawer.min.js
message/amd/build/message_drawer.min.js.map
message/amd/build/message_drawer_helper.min.js
message/amd/build/message_drawer_helper.min.js.map
message/amd/build/message_drawer_router.min.js
message/amd/build/message_drawer_router.min.js.map
message/amd/build/message_drawer_view_conversation.min.js
message/amd/build/message_drawer_view_conversation.min.js.map
message/amd/build/message_drawer_view_conversation_patcher.min.js
message/amd/build/message_drawer_view_conversation_patcher.min.js.map
message/amd/build/message_drawer_view_search.min.js
message/amd/build/message_drawer_view_search.min.js.map
message/amd/build/message_popover.min.js
message/amd/build/message_popover.min.js.map
message/amd/build/message_preferences.min.js [new file with mode: 0644]
message/amd/build/message_preferences.min.js.map [new file with mode: 0644]
message/amd/build/message_user_button.min.js
message/amd/build/message_user_button.min.js.map
message/amd/src/message_drawer.js
message/amd/src/message_drawer_helper.js
message/amd/src/message_popover.js
message/amd/src/message_preferences.js [new file with mode: 0644]
message/amd/src/message_user_button.js
message/output/airnotifier/classes/manager.php
message/output/airnotifier/db/install.php
message/output/airnotifier/lang/en/message_airnotifier.php
message/output/airnotifier/lib.php [new file with mode: 0644]
message/output/airnotifier/requestaccesskey.php
message/output/airnotifier/settings.php
message/output/airnotifier/yui/build/moodle-message_airnotifier-toolboxes/moodle-message_airnotifier-toolboxes-min.js
message/output/email/classes/task/send_email_task.php
message/output/email/lang/en/deprecated.txt [new file with mode: 0644]
message/output/email/lang/en/message_email.php
message/output/email/tests/send_email_task_test.php
message/output/lib.php
message/output/popup/amd/build/notification_area_control_area.min.js
message/output/popup/amd/build/notification_area_control_area.min.js.map
message/output/popup/db/upgrade.php
message/output/popup/message_output_popup.php
message/output/popup/tests/messaging_cleanup_test.php [new file with mode: 0644]
message/output/popup/version.php
message/templates/message_jumpto.mustache [new file with mode: 0644]
message/templates/message_popover.mustache
message/templates/message_preferences.mustache [new file with mode: 0644]
message/templates/message_preferences_component.mustache [new file with mode: 0644]
message/templates/message_preferences_notification_processor.mustache [new file with mode: 0644]
message/tests/behat/message_manage_notification_preferences.feature
message/tests/behat/message_preferences.feature [new file with mode: 0644]
message/upgrade.txt
mod/assign/feedback/editpdf/tests/behat/view_previous_annotations.feature
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotation.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationhighlight.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationline.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationoval.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationpen.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationrectangle.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationstamp.js
mod/assign/feedback/editpdf/yui/src/editor/js/comment.js
mod/assign/feedback/editpdf/yui/src/editor/js/commentsearch.js
mod/assign/feedback/editpdf/yui/src/editor/js/drawable.js
mod/assign/feedback/editpdf/yui/src/editor/js/editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/quickcommentlist.js
mod/assign/lang/en/assign.php
mod/assign/lib.php
mod/assign/tests/behat/edit_previous_feedback.feature
mod/assign/tests/behat/hide_grader.feature
mod/assign/yui/build/moodle-mod_assign-history/moodle-mod_assign-history-min.js
mod/chat/lib.php
mod/choice/locallib.php
mod/data/locallib.php
mod/data/tests/behat/add_entries.feature
mod/feedback/classes/responses_table.php
mod/feedback/lib.php
mod/folder/lib.php
mod/forum/amd/build/discussion_nested_v2.min.js
mod/forum/amd/build/discussion_nested_v2.min.js.map
mod/forum/amd/build/grades/expandconversation.min.js
mod/forum/amd/build/grades/expandconversation.min.js.map
mod/forum/amd/build/grades/grader.min.js
mod/forum/amd/build/grades/grader.min.js.map
mod/forum/amd/build/local/grades/grader.min.js
mod/forum/amd/build/local/grades/grader.min.js.map
mod/forum/amd/build/local/grades/local/grader/user_picker.min.js
mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map
mod/forum/amd/build/local/layout/fullscreen.min.js
mod/forum/amd/build/local/layout/fullscreen.min.js.map
mod/forum/classes/local/exporters/post.php
mod/forum/export.php
mod/forum/lib.php
mod/forum/locallib.php
mod/forum/report/summary/templates/bulk_action_menu.mustache
mod/forum/templates/discussion_list.mustache
mod/forum/templates/forum_discussion_nested_v2_first_post.mustache
mod/forum/templates/forum_discussion_post.mustache
mod/forum/templates/forum_discussion_threaded_post.mustache
mod/forum/tests/behat/add_forum_inline.feature
mod/forum/tests/behat/favourite_discussion.feature
mod/forum/tests/behat/inpage_reply.feature
mod/forum/tests/generator/lib.php
mod/forum/view.php
mod/glossary/lib.php
mod/h5pactivity/backup/moodle2/backup_h5pactivity_stepslib.php
mod/h5pactivity/backup/moodle2/restore_h5pactivity_stepslib.php
mod/h5pactivity/classes/local/attempt.php
mod/h5pactivity/classes/local/grader.php [new file with mode: 0644]
mod/h5pactivity/classes/local/manager.php [new file with mode: 0644]
mod/h5pactivity/classes/privacy/provider.php
mod/h5pactivity/classes/xapi/handler.php
mod/h5pactivity/db/install.xml
mod/h5pactivity/db/upgrade.php
mod/h5pactivity/lang/en/h5pactivity.php
mod/h5pactivity/lib.php
mod/h5pactivity/mod_form.php
mod/h5pactivity/tests/behat/add_h5pactivity.feature
mod/h5pactivity/tests/behat/define_settings.feature [new file with mode: 0644]
mod/h5pactivity/tests/behat/grading_attempts.feature [new file with mode: 0644]
mod/h5pactivity/tests/behat/sending_attempt.feature
mod/h5pactivity/tests/event/course_module_instance_list_viewed_test.php
mod/h5pactivity/tests/event/course_module_viewed_test.php
mod/h5pactivity/tests/event/statement_received_test.php
mod/h5pactivity/tests/generator/lib.php
mod/h5pactivity/tests/generator_test.php
mod/h5pactivity/tests/local/attempt_test.php
mod/h5pactivity/tests/local/grader_test.php [new file with mode: 0644]
mod/h5pactivity/tests/local/manager_test.php [new file with mode: 0644]
mod/h5pactivity/tests/privacy_test.php
mod/h5pactivity/tests/restore_test.php [new file with mode: 0644]
mod/h5pactivity/tests/xapi/handler_test.php
mod/h5pactivity/version.php
mod/h5pactivity/view.php
mod/lesson/lang/en/lesson.php
mod/lesson/lib.php
mod/lesson/tests/behat/duplicate_lesson_page.feature
mod/lesson/tests/behat/import_fillintheblank_question.feature
mod/lesson/tests/behat/lesson_student_dashboard.feature
mod/lesson/tests/behat/teacher_grade_essays.feature
mod/lti/lang/en/lti.php
mod/lti/mod_form.php
mod/quiz/accessrule/safebrowser/rule.php [deleted file]
mod/quiz/accessrule/safebrowser/tests/rule_test.php [deleted file]
mod/quiz/accessrule/seb/amd/build/managetemplates.min.js [new file with mode: 0644]
mod/quiz/accessrule/seb/amd/build/managetemplates.min.js.map [new file with mode: 0644]
mod/quiz/accessrule/seb/amd/src/managetemplates.js [new file with mode: 0644]
mod/quiz/accessrule/seb/backup/moodle2/backup_quizaccess_seb_subplugin.class.php [new file with mode: 0644]
mod/quiz/accessrule/seb/backup/moodle2/restore_quizaccess_seb_subplugin.class.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/access_manager.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/config_key.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/event/access_prevented.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/event/template_created.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/event/template_deleted.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/event/template_disabled.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/event/template_enabled.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/event/template_updated.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/helper.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/hideif_rule.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/link_generator.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/local/form/template.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/local/table/template_list.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/privacy/provider.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/property_list.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/quiz_settings.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/settings_provider.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/template.php [new file with mode: 0644]
mod/quiz/accessrule/seb/classes/template_controller.php [new file with mode: 0644]
mod/quiz/accessrule/seb/config.php [new file with mode: 0644]
mod/quiz/accessrule/seb/db/access.php [new file with mode: 0644]
mod/quiz/accessrule/seb/db/caches.php [new file with mode: 0644]
mod/quiz/accessrule/seb/db/install.php [new file with mode: 0644]
mod/quiz/accessrule/seb/db/install.xml [new file with mode: 0644]
mod/quiz/accessrule/seb/db/upgrade.php [moved from mod/quiz/accessrule/safebrowser/lang/en/quizaccess_safebrowser.php with 53% similarity]
mod/quiz/accessrule/seb/lang/en/quizaccess_seb.php [new file with mode: 0644]
mod/quiz/accessrule/seb/lib.php [new file with mode: 0644]
mod/quiz/accessrule/seb/rule.php [new file with mode: 0644]
mod/quiz/accessrule/seb/settings.php [new file with mode: 0644]
mod/quiz/accessrule/seb/template.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/behat/edit_form.feature [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/generator/behat_quizaccess_seb_generator.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/generator/lib.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/access_manager_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/backup_restore_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/base.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/config_key_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/event_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/helper_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/hideif_rule_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/link_generator_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/privacy_provider_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/property_list_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/quiz_settings_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/rule_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/JSON_unencrypted_mac_001.txt [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/encrypted.seb [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/simpleunencrypted.seb [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/simpleunencryptedwithoutoriginator.seb [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/unencrypted.seb [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/unencrypted_mac_001.seb [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/sample_data/unencrypted_win_223.seb [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/settings_provider_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/tests/phpunit/template_test.php [new file with mode: 0644]
mod/quiz/accessrule/seb/version.php [new file with mode: 0644]
mod/quiz/accessrule/timelimit/lang/en/quizaccess_timelimit.php
mod/quiz/backup/moodle2/restore_quiz_stepslib.php
mod/quiz/lang/en/quiz.php
mod/quiz/lib.php
mod/quiz/locallib.php
mod/quiz/tests/behat/attempt_begin.feature
mod/quiz/yui/build/moodle-mod_quiz-autosave/moodle-mod_quiz-autosave-min.js
mod/quiz/yui/build/moodle-mod_quiz-dragdrop/moodle-mod_quiz-dragdrop-debug.js
mod/quiz/yui/build/moodle-mod_quiz-dragdrop/moodle-mod_quiz-dragdrop-min.js
mod/quiz/yui/build/moodle-mod_quiz-dragdrop/moodle-mod_quiz-dragdrop.js
mod/quiz/yui/build/moodle-mod_quiz-modform/moodle-mod_quiz-modform-min.js
mod/quiz/yui/build/moodle-mod_quiz-questionchooser/moodle-mod_quiz-questionchooser-min.js
mod/quiz/yui/build/moodle-mod_quiz-quizbase/moodle-mod_quiz-quizbase-min.js
mod/quiz/yui/build/moodle-mod_quiz-toolboxes/moodle-mod_quiz-toolboxes-debug.js
mod/quiz/yui/build/moodle-mod_quiz-toolboxes/moodle-mod_quiz-toolboxes-min.js
mod/quiz/yui/build/moodle-mod_quiz-toolboxes/moodle-mod_quiz-toolboxes.js
mod/quiz/yui/build/moodle-mod_quiz-util-base/moodle-mod_quiz-util-base-min.js
mod/quiz/yui/build/moodle-mod_quiz-util-page/moodle-mod_quiz-util-page-min.js
mod/quiz/yui/build/moodle-mod_quiz-util-slot/moodle-mod_quiz-util-slot-min.js
mod/quiz/yui/src/dragdrop/js/resource.js
mod/quiz/yui/src/toolboxes/js/resource.js
mod/quiz/yui/src/toolboxes/js/section.js
mod/resource/tests/behat/display_resource.feature
mod/scorm/lang/en/scorm.php
mod/scorm/locallib.php
mod/scorm/tests/behat/completion_condition_require_status.feature
mod/scorm/tests/behat/multisco_review_mode.feature
mod/survey/lib.php
mod/upgrade.txt
mod/wiki/lib.php
mod/wiki/tests/behat/reset_wiki_comments_tags_files.feature
mod/workshop/lib.php
mod/workshop/tests/behat/file_type_restriction.feature
npm-shrinkwrap.json
package.json
pix/i/contentbank.png [new file with mode: 0644]
pix/i/contentbank.svg [new file with mode: 0644]
portfolio/googledocs/lib.php
portfolio/googledocs/upgrade.txt [new file with mode: 0644]
privacy/classes/tests/request/content_writer.php
question/format/aiken/tests/behat/aiken_import.feature
question/format/gift/format.php
question/format/gift/tests/giftformat_test.php
question/type/ddimageortext/amd/build/question.min.js
question/type/ddimageortext/amd/build/question.min.js.map
question/type/ddimageortext/lang/en/qtype_ddimageortext.php
question/type/ddmarker/amd/build/form.min.js
question/type/ddmarker/amd/build/form.min.js.map
question/type/ddmarker/amd/build/question.min.js
question/type/ddmarker/amd/build/question.min.js.map
question/type/ddmarker/amd/build/shapes.min.js
question/type/ddmarker/amd/build/shapes.min.js.map
question/type/ddmarker/amd/src/form.js
question/type/ddmarker/amd/src/question.js
question/type/ddmarker/amd/src/shapes.js
question/type/ddmarker/lang/en/qtype_ddmarker.php
question/type/ddmarker/renderer.php
question/type/ddmarker/styles.css
question/type/ddmarker/tests/behat/behat_qtype_ddmarker.php
question/type/ddmarker/tests/behat/preview.feature
question/type/ddmarker/tests/walkthrough_test.php
question/type/ddwtos/amd/build/ddwtos.min.js
question/type/ddwtos/amd/build/ddwtos.min.js.map
question/yui/build/moodle-question-chooser/moodle-question-chooser-min.js
question/yui/build/moodle-question-preview/moodle-question-preview-min.js
question/yui/build/moodle-question-searchform/moodle-question-searchform-min.js
report/configlog/classes/output/report_table.php
report/configlog/lang/en/report_configlog.php
report/configlog/tests/behat/view_report.feature
report/eventlist/yui/build/moodle-report_eventlist-eventfilter/moodle-report_eventlist-eventfilter-min.js
report/loglive/yui/build/moodle-report_loglive-fetchlogs/moodle-report_loglive-fetchlogs-min.js
repository/filepicker.js
repository/tests/behat/edit_file.feature [new file with mode: 0644]
repository/tests/behat/select_file.feature [new file with mode: 0644]
tag/tests/behat/delete_tag.feature
theme/boost/amd/build/carousel.min.js
theme/boost/amd/build/carousel.min.js.map
theme/boost/amd/build/collapse.min.js
theme/boost/amd/build/collapse.min.js.map
theme/boost/amd/build/dropdown.min.js
theme/boost/amd/build/dropdown.min.js.map
theme/boost/amd/build/modal.min.js
theme/boost/amd/build/modal.min.js.map
theme/boost/amd/build/popover.min.js
theme/boost/amd/build/popover.min.js.map
theme/boost/amd/build/sanitizer.min.js
theme/boost/amd/build/sanitizer.min.js.map
theme/boost/amd/build/scrollspy.min.js
theme/boost/amd/build/scrollspy.min.js.map
theme/boost/amd/build/tether.min.js
theme/boost/amd/build/tether.min.js.map
theme/boost/amd/build/toast.min.js
theme/boost/amd/build/toast.min.js.map
theme/boost/amd/build/tooltip.min.js
theme/boost/amd/build/tooltip.min.js.map
theme/boost/scss/moodle/admin.scss
theme/boost/scss/moodle/chat.scss
theme/boost/scss/moodle/core.scss
theme/boost/scss/moodle/course.scss
theme/boost/scss/moodle/grade.scss
theme/boost/scss/moodle/message.scss
theme/boost/scss/moodle/print.scss
theme/boost/scss/moodle/tables.scss
theme/boost/scss/moodle/undo.scss
theme/boost/style/moodle.css
theme/boost/templates/navbar-secure.mustache
theme/boost/tests/behat/settingstabs.feature
theme/boost/tests/behat/tour_filter.feature
theme/classic/style/moodle.css
theme/classic/templates/navbar-secure.mustache
theme/upgrade.txt
user/action_redir.php
user/amd/build/participants.min.js
user/amd/build/participants.min.js.map
user/amd/build/repository.min.js [new file with mode: 0644]
user/amd/build/repository.min.js.map [new file with mode: 0644]
user/amd/build/status_field.min.js
user/amd/build/status_field.min.js.map
user/amd/src/participants.js
user/amd/src/repository.js [new file with mode: 0644]
user/amd/src/status_field.js
user/classes/table/participants.php
user/classes/table/participants_search.php [new file with mode: 0644]
user/index.php
user/tests/behat/course_preference.feature
user/tests/behat/custom_profile_fields.feature
user/tests/behat/filter_idnumber.feature
user/tests/behat/filter_participants.feature
user/tests/behat/set_default_homepage.feature
user/tests/behat/view_participants.feature
user/tests/table/participants_search_test.php [new file with mode: 0644]
version.php

index 2ef8a38..b9c0b6a 100644 (file)
@@ -65,6 +65,7 @@ lib/php-jwt/
 lib/babel-polyfill/
 lib/polyfills/
 lib/emoji-data/
+lib/plist/
 media/player/videojs/amd/src/video-lazy.js
 media/player/videojs/amd/src/Youtube-lazy.js
 media/player/videojs/videojs/
index 9439956..50de756 100644 (file)
@@ -3,6 +3,8 @@
     "Feature": 0,
     "Background": 2,
     "Scenario": 2,
+    "Examples": 4,
+    "example": 6,
     "Step": 4,
     "given": 4,
     "and": 4
@@ -14,7 +16,9 @@
   "no-multiple-empty-lines": "on",
   "no-partially-commented-tag-lines": "on",
   "no-trailing-spaces": "on",
-  "no-unamed-features": "on",
-  "no-unamed-scenarios": "on",
-  "no-scenario-outlines-without-examples": "on"
+  "no-unnamed-features": "on",
+  "no-unnamed-scenarios": "on",
+  "no-scenario-outlines-without-examples": "on",
+  "no-examples-in-scenarios": "on",
+  "new-line-at-eof": ["on", "yes"]
 }
diff --git a/.nvmrc b/.nvmrc
index 7796292..01f1a56 100644 (file)
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v8.16.1
+v14.0.0
index f00e696..5d9e5c1 100644 (file)
@@ -66,6 +66,7 @@ lib/php-jwt/
 lib/babel-polyfill/
 lib/polyfills/
 lib/emoji-data/
+lib/plist/
 media/player/videojs/amd/src/video-lazy.js
 media/player/videojs/amd/src/Youtube-lazy.js
 media/player/videojs/videojs/
index 245d7fc..f60032e 100644 (file)
@@ -18,7 +18,7 @@ services:
 
 php:
     # We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
-    - 7.3
+    - 7.4
     - 7.2
 
 addons:
@@ -48,11 +48,11 @@ jobs:
     fast_finish: true
 
     include:
-          # Run mysql only on 7.3 - it's just too slow
-        - php: 7.3
+          # Run mysql only on highest - it's just too slow
+        - php: 7.4
           env: DB=mysqli   TASK=PHPUNIT
-          # Run grunt/npm install on highest version ('node' is an alias for the latest node.js version.)
-        - php: 7.2
+          # Run grunt/npm install on highest version too ('node' is an alias for the latest node.js version.)
+        - php: 7.4
           env: DB=none     TASK=GRUNT   NVM_VERSION='lts/carbon'
 
 cache:
index 657bd77..a7b728f 100644 (file)
@@ -149,6 +149,7 @@ module.exports = function(grunt) {
     const watchmanClient = new watchman.Client();
     const fs = require('fs');
     const ComponentList = require(path.resolve('GruntfileComponents.js'));
+    const sass = require('node-sass');
 
     // Verify the node version is new enough.
     var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
@@ -358,6 +359,7 @@ module.exports = function(grunt) {
                 }
             },
             options: {
+                implementation: sass,
                 includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
             }
         },
@@ -527,23 +529,28 @@ module.exports = function(grunt) {
         const options = grunt.config('gherkinlint.options');
 
         // Grab the gherkin-lint linter and required scaffolding.
-        const linter = require('gherkin-lint/src/linter.js');
-        const featureFinder = require('gherkin-lint/src/feature-finder.js');
-        const configParser = require('gherkin-lint/src/config-parser.js');
-        const formatter = require('gherkin-lint/src/formatters/stylish.js');
+        const linter = require('gherkin-lint/dist/linter.js');
+        const featureFinder = require('gherkin-lint/dist/feature-finder.js');
+        const configParser = require('gherkin-lint/dist/config-parser.js');
+        const formatter = require('gherkin-lint/dist/formatters/stylish.js');
 
         // Run the linter.
-        const results = linter.lint(
+        return linter.lint(
             featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
             configParser.getConfiguration(configParser.defaultConfigFileName)
-        );
-
-        // Print the results out uncondtionally.
-        formatter.printResults(results);
-
-        // Report on the results.
-        // The done function takes a bool whereby a falsey statement causes the task to fail.
-        done(results.every(result => result.errors.length === 0));
+        )
+        .then(results => {
+            // Print the results out uncondtionally.
+            formatter.printResults(results);
+
+            return results;
+        })
+        .then(results => {
+            // Report on the results.
+            // The done function takes a bool whereby a falsey statement causes the task to fail.
+            return results.every(result => result.errors.length === 0);
+        })
+        .then(done); // eslint-disable-line promise/no-callback-in-promise
     };
 
     tasks.startup = function() {
diff --git a/admin/cli/adhoc_task.php b/admin/cli/adhoc_task.php
new file mode 100644 (file)
index 0000000..b0ed21d
--- /dev/null
@@ -0,0 +1,122 @@
+<?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/>.
+
+/**
+ * Task executor for adhoc tasks.
+ *
+ * @package    core
+ * @subpackage cli
+ * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+
+require(__DIR__ . '/../../config.php');
+require_once("{$CFG->libdir}/clilib.php");
+require_once("{$CFG->libdir}/cronlib.php");
+
+list($options, $unrecognized) = cli_get_params(
+    [
+        'execute' => false,
+        'help' => false,
+        'keep-alive' => 0,
+        'showsql' => false,
+        'showdebugging' => false,
+        'ignorelimits' => false,
+    ], [
+        'h' => 'help',
+        'e' => 'execute',
+        'k' => 'keep-alive',
+        'i' => 'ignorelimits',
+    ]
+);
+
+if ($unrecognized) {
+    $unrecognized = implode("\n  ", $unrecognized);
+    cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
+}
+
+if ($options['help'] or empty($options['execute'])) {
+    $help = <<<EOT
+Ad hoc cron tasks.
+
+Options:
+ -h, --help                Print out this help
+     --showsql             Show sql queries before they are executed
+     --showdebugging       Show developer level debugging information
+ -e, --execute             Run all queued adhoc tasks
+ -k, --keep-alive=N        Keep this script alive for N seconds and poll for new adhoc tasks
+ -i  --ignorelimits        Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
+
+Example:
+\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
+
+EOT;
+
+    echo $help;
+    die;
+}
+
+if ($options['showdebugging']) {
+    set_debugging(DEBUG_DEVELOPER, true);
+}
+
+if ($options['showsql']) {
+    $DB->set_debug(true);
+}
+
+if (CLI_MAINTENANCE) {
+    echo "CLI maintenance mode active, cron execution suspended.\n";
+    exit(1);
+}
+
+if (moodle_needs_upgrading()) {
+    echo "Moodle upgrade pending, cron execution suspended.\n";
+    exit(1);
+}
+
+if (empty($options['execute'])) {
+    exit(0);
+}
+if (empty($options['keep-alive'])) {
+    $options['keep-alive'] = 0;
+}
+
+if (!empty($CFG->showcronsql)) {
+    $DB->set_debug(true);
+}
+if (!empty($CFG->showcrondebugging)) {
+    set_debugging(DEBUG_DEVELOPER, true);
+}
+
+$checklimits = empty($options['ignorelimits']);
+
+core_php_time_limit::raise();
+
+// Increase memory limit.
+raise_memory_limit(MEMORY_EXTRA);
+
+// Emulate normal session - we use admin account by default.
+cron_setup_user();
+
+$humantimenow = date('r', time());
+$keepalive = (int)$options['keep-alive'];
+
+\core\local\cli\shutdown::script_supports_graceful_exit();
+
+mtrace("Server Time: {$humantimenow}\n");
+cron_run_adhoc_tasks(time(), $keepalive, $checklimits);
index 7f56b92..35045ca 100644 (file)
@@ -124,7 +124,12 @@ if ($options['unset'] || $options['set'] !== null) {
         cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
     }
 
-    set_config($options['name'], $options['set'], $options['component']);
+    $new = $options['set'];
+    $old = get_config($options['component'], $options['name']);
+    if ($new !== $old) {
+        set_config($options['name'], $options['set'], $options['component']);
+        add_to_config_log($options['name'], $old, $new, $options['component']);
+    }
     exit(0);
 }
 
diff --git a/admin/cli/scheduled_task.php b/admin/cli/scheduled_task.php
new file mode 100644 (file)
index 0000000..f825f46
--- /dev/null
@@ -0,0 +1,151 @@
+<?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/>.
+
+/**
+ * CLI task execution.
+ *
+ * @package    core
+ * @subpackage cli
+ * @copyright  2014 Petr Skoda
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+
+require(__DIR__ . '/../../config.php');
+require_once("$CFG->libdir/clilib.php");
+require_once("$CFG->libdir/cronlib.php");
+
+list($options, $unrecognized) = cli_get_params(
+    array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
+    array('h' => 'help')
+);
+
+if ($unrecognized) {
+    $unrecognized = implode("\n  ", $unrecognized);
+    cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
+}
+
+if ($options['help'] or (!$options['list'] and !$options['execute'])) {
+    $help =
+    "Scheduled cron tasks.
+
+    Options:
+    --execute=\\some\\task  Execute scheduled task manually
+    --list                List all scheduled tasks
+    --showsql             Show sql queries before they are executed
+    --showdebugging       Show developer level debugging information
+    -h, --help            Print out this help
+
+    Example:
+    \$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
+
+    ";
+
+    echo $help;
+    die;
+}
+
+if ($options['showdebugging']) {
+    set_debugging(DEBUG_DEVELOPER, true);
+}
+
+if ($options['showsql']) {
+    $DB->set_debug(true);
+}
+if ($options['list']) {
+    cli_heading("List of scheduled tasks ($CFG->wwwroot)");
+
+    $shorttime = get_string('strftimedatetimeshort');
+
+    $tasks = \core\task\manager::get_all_scheduled_tasks();
+    echo str_pad(get_string('scheduledtasks', 'tool_task'), 50, ' ') . ' ' . str_pad(get_string('runpattern', 'tool_task'), 17, ' ')
+        . ' ' . str_pad(get_string('lastruntime', 'tool_task'), 40, ' ') . get_string('nextruntime', 'tool_task') . "\n";
+    foreach ($tasks as $task) {
+        $class = '\\' . get_class($task);
+        $schedule = $task->get_minute() . ' '
+            . $task->get_hour() . ' '
+            . $task->get_day() . ' '
+            . $task->get_day_of_week() . ' '
+            . $task->get_month() . ' '
+            . $task->get_day_of_week();
+        $nextrun = $task->get_next_run_time();
+        $lastrun = $task->get_last_run_time();
+
+        $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
+        $plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled();
+
+        if ($plugindisabled) {
+            $nextrun = get_string('plugindisabled', 'tool_task');
+        } else if ($task->get_disabled()) {
+            $nextrun = get_string('taskdisabled', 'tool_task');
+        } else if ($nextrun > time()) {
+            $nextrun = userdate($nextrun);
+        } else {
+            $nextrun = get_string('asap', 'tool_task');
+        }
+
+        if ($lastrun) {
+            $lastrun = userdate($lastrun);
+        } else {
+            $lastrun = get_string('never');
+        }
+
+        echo str_pad($class, 50, ' ') . ' ' . str_pad($schedule, 17, ' ') .
+            ' ' . str_pad($lastrun, 40, ' ') . ' ' . $nextrun . "\n";
+    }
+    exit(0);
+}
+
+if ($execute = $options['execute']) {
+    if (!$task = \core\task\manager::get_scheduled_task($execute)) {
+        mtrace("Task '$execute' not found");
+        exit(1);
+    }
+
+    if (moodle_needs_upgrading()) {
+        mtrace("Moodle upgrade pending, cannot execute tasks.");
+        exit(1);
+    }
+
+    // Increase memory limit.
+    raise_memory_limit(MEMORY_EXTRA);
+
+    // Emulate normal session - we use admin account by default.
+    cron_setup_user();
+
+    // Execute the task.
+    \core\local\cli\shutdown::script_supports_graceful_exit();
+    $cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
+    if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
+        mtrace('Cannot obtain cron lock');
+        exit(129);
+    }
+    if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
+        $cronlock->release();
+        mtrace('Cannot obtain task lock');
+        exit(130);
+    }
+
+    $task->set_lock($lock);
+    if (!$task->is_blocking()) {
+        $cronlock->release();
+    } else {
+        $task->set_cron_lock($cronlock);
+    }
+
+    cron_run_inner_scheduled_task($task);
+}
index 5931a26..45f46a5 100644 (file)
@@ -361,14 +361,15 @@ class core_admin_renderer extends plugin_renderer_base {
         $output = '';
 
         if ($checker->enabled()) {
-            $output .= $this->container_start('checkforupdates');
+            $output .= $this->container_start('checkforupdates mb-4');
             $output .= $this->single_button(
                 new moodle_url($reloadurl, array('fetchupdates' => 1)),
                 get_string('checkforupdates', 'core_plugin')
             );
             if ($timefetched = $checker->get_last_timefetched()) {
                 $timefetched = userdate($timefetched, get_string('strftimedatetime', 'core_langconfig'));
-                $output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched), 'lasttimefetched');
+                $output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched),
+                    'lasttimefetched small text-muted mt-1');
             }
             $output .= $this->container_end();
         }
@@ -1045,7 +1046,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 $displayname = new html_table_cell(
                     $icon.
                     html_writer::span($plugin->displayname, 'pluginname').
-                    html_writer::div($plugin->get_dir(), 'plugindir')
+                    html_writer::div($plugin->get_dir(), 'plugindir text-muted small')
                 );
 
                 $versiondb = new html_table_cell($plugin->versiondb);
@@ -1082,7 +1083,7 @@ class core_admin_renderer extends plugin_renderer_base {
                         break;
                     case core_plugin_manager::PLUGIN_STATUS_NODB:
                     case core_plugin_manager::PLUGIN_STATUS_UPTODATE:
-                        $statusclass .= $dependenciesok ? '' : 'badge-warning';
+                        $statusclass .= $dependenciesok ? 'badge-light' : 'badge-warning';
                         break;
                 }
                 $status = html_writer::span(get_string('status_' . $statuscode, 'core_plugin'), $statusclass);
@@ -1092,7 +1093,7 @@ class core_admin_renderer extends plugin_renderer_base {
                         new moodle_url($this->page->url, array('abortinstall' => $plugin->component)),
                         get_string('cancelinstallone', 'core_plugin'),
                         'post',
-                        array('class' => 'actionbutton cancelinstallone')
+                        array('class' => 'actionbutton cancelinstallone d-block mt-1')
                     );
                 }
 
@@ -1101,7 +1102,7 @@ class core_admin_renderer extends plugin_renderer_base {
                         new moodle_url($this->page->url, array('abortupgrade' => $plugin->component)),
                         get_string('cancelupgradeone', 'core_plugin'),
                         'post',
-                        array('class' => 'actionbutton cancelupgradeone')
+                        array('class' => 'actionbutton cancelupgradeone d-block mt-1')
                     );
                 }
 
@@ -1174,7 +1175,7 @@ class core_admin_renderer extends plugin_renderer_base {
             }
         }
 
-        $out .= $this->output->container_start('actions');
+        $out .= $this->output->container_start('actions mb-2');
 
         $installableupdates = $pluginman->filter_installable($pluginman->available_updates());
         if ($installableupdates) {
@@ -1182,7 +1183,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 new moodle_url($this->page->url, array('installupdatex' => 1)),
                 get_string('updateavailableinstallall', 'core_admin', count($installableupdates)),
                 'post',
-                array('class' => 'singlebutton updateavailableinstallall')
+                array('class' => 'singlebutton updateavailableinstallall mr-1')
             );
         }
 
@@ -1191,7 +1192,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 new moodle_url($this->page->url, array('abortinstallx' => 1)),
                 get_string('cancelinstallall', 'core_plugin', count($installabortable)),
                 'post',
-                array('class' => 'singlebutton cancelinstallall')
+                array('class' => 'singlebutton cancelinstallall mr-1')
             );
         }
 
@@ -1200,15 +1201,17 @@ class core_admin_renderer extends plugin_renderer_base {
                 new moodle_url($this->page->url, array('abortupgradex' => 1)),
                 get_string('cancelupgradeall', 'core_plugin', count($upgradeabortable)),
                 'post',
-                array('class' => 'singlebutton cancelupgradeall')
+                array('class' => 'singlebutton cancelupgradeall mr-1')
             );
         }
 
         $out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 0)),
-            get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge'));
+            get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge badge-light'),
+            'btn btn-link mr-1');
 
         $out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 1)),
-            get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge'));
+            get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge badge-light'),
+            'btn btn-link mr-1');
 
         $out .= $this->output->container_end(); // End of .actions container.
         $out .= $this->output->container_end(); // End of #plugins-check-info container.
@@ -1276,12 +1279,13 @@ class core_admin_renderer extends plugin_renderer_base {
             }
         }
 
-        $out  = $this->output->container_start('plugins-check-dependencies');
+        $out  = $this->output->container_start('plugins-check-dependencies mb-4');
 
         if ($unavailable or $unknown) {
             $out .= $this->output->heading(get_string('misdepsunavail', 'core_plugin'));
             if ($unknown) {
-                $out .= $this->output->notification(get_string('misdepsunknownlist', 'core_plugin', implode(', ', $unknown)));
+                $out .= $this->output->render((new \core\output\notification(get_string('misdepsunknownlist', 'core_plugin',
+                    implode(', ', $unknown))))->set_show_closebutton(false));
             }
             if ($unavailable) {
                 $unavailablelist = array();
@@ -1295,18 +1299,18 @@ class core_admin_renderer extends plugin_renderer_base {
                     }
                     $unavailablelist[] = $unavailablelistitem;
                 }
-                $out .= $this->output->notification(get_string('misdepsunavaillist', 'core_plugin',
-                    implode(', ', $unavailablelist)));
+                $out .= $this->output->render((new \core\output\notification(get_string('misdepsunavaillist', 'core_plugin',
+                    implode(', ', $unavailablelist))))->set_show_closebutton(false));
             }
-            $out .= $this->output->container_start('plugins-check-dependencies-actions');
+            $out .= $this->output->container_start('plugins-check-dependencies-actions mb-4');
             $out .= ' '.html_writer::link(new moodle_url('/admin/tool/installaddon/'),
-                get_string('dependencyuploadmissing', 'core_plugin'));
+                get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-secondary'));
             $out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
         }
 
         if ($available) {
             $out .= $this->output->heading(get_string('misdepsavail', 'core_plugin'));
-            $out .= $this->output->container_start('plugins-check-dependencies-actions');
+            $out .= $this->output->container_start('plugins-check-dependencies-actions mb-2');
 
             $installable = $pluginman->filter_installable($available);
             if ($installable) {
@@ -1314,12 +1318,13 @@ class core_admin_renderer extends plugin_renderer_base {
                     new moodle_url($this->page->url, array('installdepx' => 1)),
                     get_string('dependencyinstallmissing', 'core_plugin', count($installable)),
                     'post',
-                    array('class' => 'singlebutton dependencyinstallmissing')
+                    array('class' => 'singlebutton dependencyinstallmissing d-inline-block mr-1')
                 );
             }
 
             $out .= html_writer::div(html_writer::link(new moodle_url('/admin/tool/installaddon/'),
-                get_string('dependencyuploadmissing', 'core_plugin')), 'dependencyuploadmissing');
+                get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-link')),
+                'dependencyuploadmissing d-inline-block mr-1');
 
             $out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
 
@@ -1360,7 +1365,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 if ($CFG->branch == str_replace('.', '', $moodle->release)) {
                     $supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-success');
                 } else {
-                    $supportedmoodles[] = html_writer::span($moodle->release, 'label');
+                    $supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-light');
                 }
             }
 
@@ -1374,7 +1379,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 }
                 $info = html_writer::div(
                     get_string('requiredby', 'core_plugin', implode(', ', $requriedby)),
-                    'requiredby'
+                    'requiredby mb-1'
                 );
             } else {
                 $info = '';
@@ -1385,35 +1390,36 @@ class core_admin_renderer extends plugin_renderer_base {
             $info .= html_writer::div(
                 html_writer::link('https://moodle.org/plugins/view.php?plugin='.$plugin->component,
                     get_string('misdepinfoplugin', 'core_plugin')),
-                'misdepinfoplugin'
+                'misdepinfoplugin d-inline-block mr-3 mb-1'
             );
 
             $info .= html_writer::div(
                 html_writer::link('https://moodle.org/plugins/pluginversion.php?id='.$plugin->version->id,
                     get_string('misdepinfoversion', 'core_plugin')),
-                'misdepinfoversion'
+                'misdepinfoversion d-inline-block mr-3 mb-1'
             );
 
-            $info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')), 'misdepdownload');
+            $info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')),
+                'misdepdownload d-inline-block mr-3 mb-1');
 
             if ($pluginman->is_remote_plugin_installable($plugin->component, $plugin->version->version, $reason)) {
                 $info .= $this->output->single_button(
                     new moodle_url($this->page->url, array('installdep' => $plugin->component)),
                     get_string('dependencyinstall', 'core_plugin'),
                     'post',
-                    array('class' => 'singlebutton dependencyinstall')
+                    array('class' => 'singlebutton dependencyinstall mr-3 mb-1')
                 );
             } else {
                 $reasonhelp = $this->info_remote_plugin_not_installable($reason);
                 if ($reasonhelp) {
-                    $info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall');
+                    $info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall d-inline-block mr-3 mb-1');
                 }
             }
 
             $info .= $this->output->container_end(); // End of .actions container.
 
             $table->data[] = array(
-                html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component'),
+                html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component text-muted small'),
                 $plugin->version->release,
                 $plugin->version->version,
                 implode(' ', $supportedmoodles),
@@ -1461,7 +1467,7 @@ class core_admin_renderer extends plugin_renderer_base {
         foreach ($requirements as $reqname => $reqinfo) {
             if ($reqname === 'core') {
                 if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
-                    $class = 'requires-ok';
+                    $class = 'requires-ok text-muted';
                     $label = '';
                 } else {
                     $class = 'requires-failed';
@@ -1490,7 +1496,7 @@ class core_admin_renderer extends plugin_renderer_base {
 
                 if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
                     $label = '';
-                    $class = 'requires-ok';
+                    $class = 'requires-ok text-muted';
 
                 } else if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_MISSING) {
                     if ($reqinfo->availability == $pluginman::REQUIREMENT_AVAILABLE) {
@@ -1544,13 +1550,14 @@ class core_admin_renderer extends plugin_renderer_base {
             return '';
         }
 
-        $out = html_writer::tag('ul', implode("\n", $requires));
+        $out = html_writer::tag('ul', implode("\n", $requires), array('class' => 'm-0'));
 
         if ($displayuploadlink) {
             $out .= html_writer::div(
                 html_writer::link(
                     new moodle_url('/admin/tool/installaddon/'),
-                    get_string('dependencyuploadmissing', 'core_plugin')
+                    get_string('dependencyuploadmissing', 'core_plugin'),
+                    array('class' => 'btn btn-secondary btn-sm m-1')
                 ),
                 'dependencyuploadmissing'
             );
@@ -1560,7 +1567,8 @@ class core_admin_renderer extends plugin_renderer_base {
             $out .= html_writer::div(
                 html_writer::link(
                     new moodle_url($this->page->url, array('sesskey' => sesskey(), 'fetchupdates' => 1)),
-                    get_string('checkforupdates', 'core_plugin')
+                    get_string('checkforupdates', 'core_plugin'),
+                    array('class' => 'btn btn-secondary btn-sm m-1')
                 ),
                 'checkforupdates'
             );
index c9d406a..4aa50b4 100644 (file)
@@ -25,6 +25,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
     $temp->add(new admin_setting_configcheckbox('allowcohortthemes',  new lang_string('allowcohortthemes', 'admin'), new lang_string('configallowcohortthemes', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('allowthemechangeonurl',  new lang_string('allowthemechangeonurl', 'admin'), new lang_string('configallowthemechangeonurl', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('allowuserblockhiding', new lang_string('allowuserblockhiding', 'admin'), new lang_string('configallowuserblockhiding', 'admin'), 1));
+    $temp->add(new admin_setting_configcheckbox('langmenuinsecurelayout',
+        new lang_string('langmenuinsecurelayout', 'admin'),
+        new lang_string('langmenuinsecurelayout_desc', 'admin'), 0));
+    $temp->add(new admin_setting_configcheckbox('logininfoinsecurelayout',
+        new lang_string('logininfoinsecurelayout', 'admin'),
+        new lang_string('logininfoinsecurelayout_desc', 'admin'), 0));
     $temp->add(new admin_setting_configtextarea('custommenuitems', new lang_string('custommenuitems', 'admin'),
         new lang_string('configcustommenuitems', 'admin'), '', PARAM_RAW, '50', '10'));
     $temp->add(new admin_setting_configtextarea(
index 841b72b..8936f7c 100644 (file)
@@ -235,6 +235,11 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
             new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
             array('value' => 1, 'locked' => 0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), array('value'=>1, 'locked'=>0)));
+    $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_contentbankcontent',
+        new lang_string('generalcontentbankcontent', 'backup'),
+        new lang_string('configgeneralcontentbankcontent', 'backup'),
+        ['value' => 1, 'locked' => 0])
+    );
 
     $ADMIN->add('backups', $temp);
 
@@ -256,6 +261,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
             new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
             array('value' => 1, 'locked' => 0)));
     $temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), array('value'=>1, 'locked'=>0)));
+    $temp->add(new admin_setting_configcheckbox_with_lock(
+        'backup/backup_import_contentbankcontent',
+        new lang_string('generalcontentbankcontent', 'backup'),
+        new lang_string('configgeneralcontentbankcontent', 'backup'),
+        ['value' => 1, 'locked' => 0])
+    );
 
     $ADMIN->add('backups', $temp);
 
@@ -375,6 +386,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_groups', new lang_string('generalgroups', 'backup'),
             new lang_string('configgeneralgroups', 'backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), 1));
+    $temp->add(new admin_setting_configcheckbox(
+        'backup/backup_auto_contentbankcontent',
+        new lang_string('generalcontentbankcontent', 'backup'),
+        new lang_string('configgeneralcontentbankcontent', 'backup'),
+        1)
+    );
 
     //$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
     //$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
@@ -435,6 +452,9 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
     $temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_competencies',
         new lang_string('generalcompetencies', 'backup'),
         new lang_string('configrestorecompetencies', 'backup'), array('value' => 1, 'locked' => 0)));
+    $temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_contentbankcontent',
+        new lang_string('generalcontentbankcontent', 'backup'),
+        new lang_string('configrestorecontentbankcontent', 'backup'), array('value' => 1, 'locked' => 0)));
 
     // Restore defaults when merging into another course.
     $temp->add(new admin_setting_heading('mergerestoredefaults', new lang_string('mergerestoredefaults', 'backup'), ''));
index f8a5ceb..46206fc 100644 (file)
@@ -10,7 +10,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $temp = new admin_settingpage('experimentalsettings', new lang_string('experimentalsettings', 'admin'));
     //TODO: Re-enable cc-import once re-implemented in 2.0.x
     //$temp->add(new admin_setting_configcheckbox('enableimsccimport', new lang_string('enable_cc_import', 'imscc'), new lang_string('enable_cc_import_description', 'imscc'), 0));
-    $temp->add(new admin_setting_configcheckbox('enablesafebrowserintegration', new lang_string('enablesafebrowserintegration', 'admin'), new lang_string('configenablesafebrowserintegration', 'admin'), 0));
 
     $temp->add(new admin_setting_configcheckbox('dndallowtextandlinks', new lang_string('dndallowtextandlinks', 'admin'), new lang_string('configdndallowtextandlinks', 'admin'), 0));
 
index 3b9302d..a512853 100644 (file)
@@ -33,7 +33,7 @@ $ADMIN->add('h5p', new admin_externalpage('h5pmanagelibraries', get_string('h5pm
     new moodle_url('/h5p/libraries.php'), ['moodle/site:config', 'moodle/h5p:updatelibraries']));
 
 // H5P settings.
-$defaulth5plib = \core_h5p\local\library\autoloader::get_default_handler();
+$defaulth5plib = \core_h5p\local\library\autoloader::get_default_handler_library();
 if (!empty($defaulth5plib)) {
     // As for now this page only has this setting, it will be hidden if there isn't any H5P libraries handler defined.
     $settings = new admin_settingpage('h5psettings', new lang_string('h5psettings', 'core_h5p'));
index 51e7960..c11b613 100644 (file)
@@ -115,4 +115,4 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
     And I set the field "id_department" to "red"
     And I press "Add filter"
     And I should see "User One"
-    And I should not see "User Two"
\ No newline at end of file
+    And I should not see "User Two"
index 697a214..6520ca2 100644 (file)
Binary files a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js and b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js differ
index b00dbac..e71b3c8 100644 (file)
Binary files a/admin/tool/lp/amd/build/menubar.min.js and b/admin/tool/lp/amd/build/menubar.min.js differ
index 209a5c7..6c52abb 100644 (file)
Binary files a/admin/tool/lp/amd/build/menubar.min.js.map and b/admin/tool/lp/amd/build/menubar.min.js.map differ
index 25b8682..2ef194d 100644 (file)
Binary files a/admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder-min.js and b/admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder-min.js differ
index 8daab15..fd0b465 100644 (file)
@@ -24,7 +24,7 @@
 
 $string['classname'] = 'Class name';
 $string['component'] = 'Component';
-$string['configmessageinboundhost'] = 'The address of the server that Moodle should check mail against. To specify a non-default port, use [server]:[port], for example mail.example.com:587. If a port isn\'t specified, the default port for the type of mail server will be used.';
+$string['configmessageinboundhost'] = 'The address of the server that Moodle should check mail against. To specify a non-default port, use [server]:[port], for example mail.example.com:993. If a port isn\'t specified, the default port for the type of mail server will be used.';
 $string['defaultexpiration'] = 'Default address expiry period';
 $string['defaultexpiration_help'] = 'When an email address is generated by the handler, it can be set to automatically expire after a period of time, so that it can no longer be used. It is advisable to set an expiry period.';
 $string['description'] = 'Description';
index 568eb35..e95cf83 100644 (file)
@@ -31,6 +31,8 @@ use moodle_url;
 use moodle_exception;
 use lang_string;
 use curl;
+use core_qrcode;
+use stdClass;
 
 /**
  * API exposed by tool_mobile, to be used mostly by external functions and the plugin settings.
@@ -49,6 +51,16 @@ class api {
     const LOGIN_VIA_EMBEDDED_BROWSER = 3;
     /** @var int seconds an auto-login key will expire. */
     const LOGIN_KEY_TTL = 60;
+    /** @var string URL of the Moodle Apps Portal */
+    const MOODLE_APPS_PORTAL_URL = 'https://apps.moodle.com';
+    /** @var int seconds a QR login key will expire. */
+    const LOGIN_QR_KEY_TTL = 600;
+    /** @var int QR code disabled value */
+    const QR_CODE_DISABLED = 0;
+    /** @var int QR code type URL value */
+    const QR_CODE_URL = 1;
+    /** @var int QR code type login value */
+    const QR_CODE_LOGIN = 2;
 
     /**
      * Returns a list of Moodle plugins supporting the mobile app.
@@ -334,6 +346,7 @@ class api {
 
     /**
      * Creates an auto-login key for the current user, this key is restricted by time and ip address.
+     * This key is used for automatically login the user in the site when the Moodle app opens the site in a mobile browser.
      *
      * @return string the key
      * @since Moodle 3.2
@@ -349,6 +362,24 @@ class api {
         return create_user_key('tool_mobile', $USER->id, null, $iprestriction, $validuntil);
     }
 
+    /**
+     * Creates a QR login key for the current user, this key is restricted by time and ip address.
+     * This key is used for automatically login the user in the site when the user scans a QR code in the Moodle app.
+     *
+     * @return string the key
+     * @since Moodle 3.9
+     */
+    public static function get_qrlogin_key() {
+        global $USER;
+        // Delete previous keys.
+        delete_user_key('tool_mobile', $USER->id);
+
+        // Create a new key.
+        $iprestriction = getremoteaddr(null);
+        $validuntil = time() + self::LOGIN_QR_KEY_TTL;
+        return create_user_key('tool_mobile', $USER->id, null, $iprestriction, $validuntil);
+    }
+
     /**
      * Get a list of the Mobile app features.
      *
@@ -602,4 +633,31 @@ class api {
 
         return $warnings;
     }
+
+    /**
+     * Generates a QR code with the site URL or for automatic login from the mobile app.
+     *
+     * @param  stdClass $mobilesettings tool_mobile settings
+     * @return string base64 data image contents, null if qr disabled
+     */
+    public static function generate_login_qrcode(stdClass $mobilesettings) {
+        global $CFG, $USER;
+
+        if ($mobilesettings->qrcodetype == static::QR_CODE_DISABLED) {
+            return null;
+        }
+
+        $urlscheme = !empty($mobilesettings->forcedurlscheme) ? $mobilesettings->forcedurlscheme : 'moodlemobile';
+        $data = $urlscheme . '://' . $CFG->wwwroot;
+
+        if ($mobilesettings->qrcodetype == static::QR_CODE_LOGIN) {
+            $qrloginkey = static::get_qrlogin_key();
+            $data .= '?qrlogin=' . $qrloginkey . '&userid=' . $USER->id;
+        }
+
+        $qrcode = new core_qrcode($data);
+        $imagedata = 'data:image/png;base64,' . base64_encode($qrcode->getBarcodePngData(5, 5));
+
+        return $imagedata;
+    }
 }
index fe1dad0..fa13085 100644 (file)
@@ -39,6 +39,7 @@ use context_system;
 use moodle_exception;
 use moodle_url;
 use core_text;
+use core_user;
 use coding_exception;
 
 /**
@@ -593,4 +594,102 @@ class external extends external_api {
              )
         ]);
     }
+
+    /**
+     * Returns description of get_tokens_for_qr_login() parameters.
+     *
+     * @return external_function_parameters
+     * @since  Moodle 3.9
+     */
+    public static function get_tokens_for_qr_login_parameters() {
+        return new external_function_parameters (
+            [
+                'qrloginkey' => new external_value(PARAM_ALPHANUMEXT, 'The user key for validating the request.'),
+                'userid' => new external_value(PARAM_INT, 'The user the key belongs to.'),
+            ]
+        );
+    }
+
+    /**
+     * Returns a WebService token (and private token) for QR login
+     *
+     * @param string $qrloginkey the user key generated and embedded into the QR code for validating the request
+     * @param int $userid the user the key belongs to
+     * @return array with the tokens and warnings
+     * @since  Moodle 3.9
+     */
+    public static function get_tokens_for_qr_login($qrloginkey, $userid) {
+        global $PAGE, $DB;
+
+        $params = self::validate_parameters(self::get_tokens_for_qr_login_parameters(),
+            ['qrloginkey' => $qrloginkey, 'userid' => $userid]);
+
+        $context = context_system::instance();
+        // We need this to make work the format text functions.
+        $PAGE->set_context($context);
+
+        $qrcodetype = get_config('tool_mobile', 'qrcodetype');
+        if ($qrcodetype != api::QR_CODE_LOGIN) {
+            throw new moodle_exception('qrcodedisabled', 'tool_mobile');
+        }
+
+        // Only requests from the Moodle mobile or desktop app. This enhances security to avoid any type of XSS attack.
+        // This code goes intentionally here and not inside the check_autologin_prerequisites() function because it
+        // is used by other PHP scripts that can be opened in any browser.
+        if (!\core_useragent::is_moodle_app()) {
+            throw new moodle_exception('apprequired', 'tool_mobile');
+        }
+        api::check_autologin_prerequisites($params['userid']);  // Checks https, avoid site admins using this...
+
+        // Validate and delete the key.
+        $key = validate_user_key($params['qrloginkey'], 'tool_mobile', null);
+        delete_user_key('tool_mobile', $params['userid']);
+
+        // Double check key belong to user.
+        if ($key->userid != $params['userid']) {
+            throw new moodle_exception('invalidkey');
+        }
+
+        // Key validated, check user.
+        $user = core_user::get_user($key->userid, '*', MUST_EXIST);
+        core_user::require_active_user($user, true, true);
+
+        // Generate WS tokens.
+        \core\session\manager::set_user($user);
+
+        // Check if the service exists and is enabled.
+        $service = $DB->get_record('external_services', ['shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE, 'enabled' => 1]);
+        if (empty($service)) {
+            // will throw exception if no token found
+            throw new moodle_exception('servicenotavailable', 'webservice');
+        }
+
+        // Get an existing token or create a new one.
+        $token = external_generate_token_for_current_user($service);
+        $privatetoken = $token->privatetoken; // Save it here, the next function removes it.
+        external_log_token_request($token);
+
+        $result = [
+            'token' => $token->token,
+            'privatetoken' => $privatetoken ?: '',
+            'warnings' => [],
+        ];
+        return $result;
+    }
+
+    /**
+     * Returns description of get_tokens_for_qr_login() result value.
+     *
+     * @return external_description
+     * @since  Moodle 3.9
+     */
+    public static function get_tokens_for_qr_login_returns() {
+        return new external_single_structure(
+            [
+                'token' => new external_value(PARAM_ALPHANUM, 'A valid WebService token for the official mobile app service.'),
+                'privatetoken' => new external_value(PARAM_ALPHANUM, 'Private token used for auto-login processes.'),
+                'warnings' => new external_warnings(),
+            ]
+        );
+    }
 }
index d53f7b4..530267a 100644 (file)
@@ -78,5 +78,14 @@ $functions = array(
         'type'        => 'write',
         'services'    => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
     ),
-);
 
+    'tool_mobile_get_tokens_for_qr_login' => array(
+        'classname'   => 'tool_mobile\external',
+        'methodname'  => 'get_tokens_for_qr_login',
+        'description' => 'Returns a WebService token (and private token) for QR login.',
+        'type'        => 'read',
+        'services'    => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+        'ajax'          => true,
+        'loginrequired' => false,
+    ),
+);
index 092f7da..789cfd2 100644 (file)
@@ -91,10 +91,20 @@ $string['mobilecssurl'] = 'CSS';
 $string['mobilefeatures'] = 'Mobile features';
 $string['mobilenotificationsdisabledwarning'] = 'Mobile notifications are not enabled. They should be enabled in Notification settings.';
 $string['mobilesettings'] = 'Mobile settings';
+$string['moodleappsportalfeatureswarning'] = 'Please note that some features may be restricted depending on your Moodle app subscription. For details, visit the <a href="{$a}" target="_blank">Moodle Apps Portal</a>.';
 $string['oauth2identityproviders'] = 'OAuth 2 identity providers';
 $string['offlineuse'] = 'Offline use';
 $string['pluginname'] = 'Moodle app tools';
 $string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
+$string['qrcodedisabled'] = 'Access via QR code disabled';
+$string['qrcodeformobileappaccess'] = 'QR code for mobile app access';
+$string['qrcodeformobileapploginabout'] = 'Scan the QR code with your mobile app and you will be automatically logged in. The QR code will expire in {$a} minutes.';
+$string['qrcodeformobileappurlabout'] = 'Scan the QR code with your mobile app to fill in the site URL in your app.';
+$string['qrsiteadminsnotallowed'] = 'For security reasons login via QR code is not allowed for site administrators or if you are logged in as another user.';
+$string['qrcodetype'] = 'QR code access';
+$string['qrcodetype_desc'] = 'A QR code can be provided for mobile app users to scan and either have the site URL filled in or be automatically logged in without having to enter their credentials.';
+$string['qrcodetypeurl'] = 'QR code with site URL';
+$string['qrcodetypelogin'] = 'QR code with automatic login';
 $string['readingthisemailgettheapp'] = 'Reading this in an email? <a href="{$a}">Download the mobile app and receive notifications on your mobile device</a>.';
 $string['remoteaddons'] = 'Remote add-ons';
 $string['selfsignedoruntrustedcertificatewarning'] = 'It seems that the HTTPS certificate is self-signed or not trusted. The mobile app will only work with trusted sites.';
@@ -107,3 +117,4 @@ $string['getmoodleonyourmobile'] = 'Get the mobile app';
 $string['privacy:metadata:preference:tool_mobile_autologin_request_last'] = 'The date of the last auto-login key request. Between each request 6 minutes are required.';
 $string['privacy:metadata:core_userkey'] = 'User\'s keys used to create auto-login key for the current user.';
 $string['responsivemainmenuitems'] = 'Responsive menu items';
+$string['viewqrcode'] = 'View QR code';
index 74b3c0b..43d6cc2 100644 (file)
@@ -126,24 +126,64 @@ function tool_mobile_myprofile_navigation(\core_user\output\myprofile\tree $tree
         return;
     }
 
-    if (!$url = tool_mobile_create_app_download_url()) {
-        return;
+    $newnodes = [];
+    $mobilesettings = get_config('tool_mobile');
+
+    // Check if we should display a QR code.
+    if (!empty($mobilesettings->qrcodetype)) {
+        $mobileqr = null;
+        $qrcodeforappstr = get_string('qrcodeformobileappaccess', 'tool_mobile');
+
+        if ($mobilesettings->qrcodetype == tool_mobile\api::QR_CODE_LOGIN && is_https()) {
+
+            if (is_siteadmin() || \core\session\manager::is_loggedinas()) {
+                $mobileqr = get_string('qrsiteadminsnotallowed', 'tool_mobile');
+            } else {
+                $qrcodeimg = tool_mobile\api::generate_login_qrcode($mobilesettings);
+
+                $minutes = tool_mobile\api::LOGIN_QR_KEY_TTL / MINSECS;
+                $mobileqr = html_writer::tag('p', get_string('qrcodeformobileapploginabout', 'tool_mobile', $minutes));
+                $mobileqr .= html_writer::link('#qrcode', get_string('viewqrcode', 'tool_mobile'),
+                    ['class' => 'btn btn-primary mt-2', 'data-toggle' => 'collapse',
+                    'role' => 'button', 'aria-expanded' => 'false']);
+                $mobileqr .= html_writer::div(html_writer::img($qrcodeimg, $qrcodeforappstr), 'collapse mt-4', ['id' => 'qrcode']);
+            }
+
+        } else if ($mobilesettings->qrcodetype == tool_mobile\api::QR_CODE_URL) {
+            $qrcodeimg = tool_mobile\api::generate_login_qrcode($mobilesettings);
+
+            $mobileqr = get_string('qrcodeformobileappurlabout', 'tool_mobile');
+            $mobileqr .= html_writer::div(html_writer::img($qrcodeimg, $qrcodeforappstr));
+        }
+
+        if ($mobileqr) {
+            $newnodes[] = new core_user\output\myprofile\node('mobile', 'mobileappqr', $qrcodeforappstr, null, null, $mobileqr);
+        }
     }
 
+    // Check if the user is using the app, encouraging him to use it otherwise.
     $userhastoken = tool_mobile_user_has_token($user->id);
-
-    $mobilecategory = new core_user\output\myprofile\category('mobile', get_string('mobileapp', 'tool_mobile'),
-            'loginactivity');
-    $tree->add_category($mobilecategory);
+    $mobilestrconnected = null;
 
     if ($userhastoken) {
-        $mobilestr = get_string('mobileappconnected', 'tool_mobile');
-    } else {
-        $mobilestr = get_string('mobileappenabled', 'tool_mobile', $url->out());
+        $mobilestrconnected = get_string('mobileappconnected', 'tool_mobile');
+    } else if ($url = tool_mobile_create_app_download_url()) {
+         $mobilestrconnected = get_string('mobileappenabled', 'tool_mobile', $url->out());
     }
 
-    $node = new  core_user\output\myprofile\node('mobile', 'mobileappnode', $mobilestr, null);
-    $tree->add_node($node);
+    if ($mobilestrconnected) {
+        $newnodes[] = new core_user\output\myprofile\node('mobile', 'mobileappnode', $mobilestrconnected, null);
+    }
+
+    // Add nodes, if any.
+    if (!empty($newnodes)) {
+        $mobilecat = new core_user\output\myprofile\category('mobile', get_string('mobileapp', 'tool_mobile'), 'loginactivity');
+        $tree->add_category($mobilecat);
+
+        foreach ($newnodes as $node) {
+            $tree->add_node($node);
+        }
+    }
 }
 
 /**
index a9cdbcf..732bd71 100644 (file)
@@ -50,8 +50,17 @@ if ($hassiteconfig) {
 
     // Show only mobile settings if the mobile service is enabled.
     if (!empty($CFG->enablemobilewebservice)) {
+        // General notification about limited features due to app restrictions.
+        $notify = new \core\output\notification(
+            get_string('moodleappsportalfeatureswarning', 'tool_mobile', tool_mobile\api::MOODLE_APPS_PORTAL_URL),
+            \core\output\notification::NOTIFY_WARNING);
+        $featuresnotice = $OUTPUT->render($notify);
+
         // Type of login.
         $temp = new admin_settingpage('mobileauthentication', new lang_string('mobileauthentication', 'tool_mobile'));
+
+        $temp->add(new admin_setting_heading('tool_mobile/moodleappsportalfeaturesauth', '', $featuresnotice));
+
         $options = array(
             tool_mobile\api::LOGIN_VIA_APP => new lang_string('loginintheapp', 'tool_mobile'),
             tool_mobile\api::LOGIN_VIA_BROWSER => new lang_string('logininthebrowser', 'tool_mobile'),
@@ -61,6 +70,15 @@ if ($hassiteconfig) {
                     new lang_string('typeoflogin', 'tool_mobile'),
                     new lang_string('typeoflogin_desc', 'tool_mobile'), 1, $options));
 
+        $options = [
+            tool_mobile\api::QR_CODE_DISABLED => new lang_string('qrcodedisabled', 'tool_mobile'),
+            tool_mobile\api::QR_CODE_URL => new lang_string('qrcodetypeurl', 'tool_mobile'),
+            tool_mobile\api::QR_CODE_LOGIN => new lang_string('qrcodetypelogin', 'tool_mobile'),
+        ];
+        $temp->add(new admin_setting_configselect('tool_mobile/qrcodetype',
+                    new lang_string('qrcodetype', 'tool_mobile'),
+                    new lang_string('qrcodetype_desc', 'tool_mobile'), tool_mobile\api::QR_CODE_LOGIN, $options));
+
         $temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
                     new lang_string('forcedurlscheme_key', 'tool_mobile'),
                     new lang_string('forcedurlscheme', 'tool_mobile'), 'moodlemobile', PARAM_NOTAGS));
@@ -74,6 +92,8 @@ if ($hassiteconfig) {
         // Appearance related settings.
         $temp = new admin_settingpage('mobileappearance', new lang_string('mobileappearance', 'tool_mobile'));
 
+        $temp->add(new admin_setting_heading('tool_mobile/moodleappsportalfeaturesappearance', '', $featuresnotice));
+
         $temp->add(new admin_setting_configtext('mobilecssurl', new lang_string('mobilecssurl', 'tool_mobile'),
                     new lang_string('configmobilecssurl', 'tool_mobile'), '', PARAM_URL));
 
@@ -106,6 +126,8 @@ if ($hassiteconfig) {
         // Features related settings.
         $temp = new admin_settingpage('mobilefeatures', new lang_string('mobilefeatures', 'tool_mobile'));
 
+        $temp->add(new admin_setting_heading('tool_mobile/moodleappsportalfeatures', '', $featuresnotice));
+
         $temp->add(new admin_setting_heading('tool_mobile/logout',
                     new lang_string('logout'), ''));
 
index 4d9a07d..18721a2 100644 (file)
@@ -78,15 +78,7 @@ class tool_mobile_api_testcase extends externallib_advanced_testcase {
         $CFG->debugdisplay = 1;
         set_config('debugauthdb', 1, 'auth_db');
         set_config('debugdb', 1, 'enrol_database');
-        $expectedissues = array('nohttpsformobilewarning', 'invaliduserquotawarning', 'adodbdebugwarning', 'displayerrorswarning',
-            'mobilenotificationsdisabledwarning');
-
-        $processors = get_message_processors();
-        foreach ($processors as $processor => $status) {
-            if ($processor == 'airnotifier' && $status->enabled) {
-                unset($expectedissues['mobilenotificationsdisabledwarning']);
-            }
-        }
+        $expectedissues = array('nohttpsformobilewarning', 'invaliduserquotawarning', 'adodbdebugwarning', 'displayerrorswarning');
 
         $issues = api::get_potential_config_issues();
         $this->assertCount(count($expectedissues), $issues);
index 9534f05..7b05175 100644 (file)
@@ -600,4 +600,129 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         $expected = format_text($expected, $course->summaryformat, ['para' => false, 'filter' => true]);
         $this->assertEquals($expected, $data->courses[0]->summary);
     }
+
+    /*
+     * Test get_tokens_for_qr_login.
+     */
+    public function test_get_tokens_for_qr_login() {
+        global $DB, $CFG, $USER;
+
+        $this->resetAfterTest(true);
+
+        $user = $this->getDataGenerator()->create_user();
+        $this->setUser($user);
+
+        $qrloginkey = api::get_qrlogin_key();
+
+        // Generate new tokens, the ones we expect to receive.
+        $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
+        $token = external_generate_token_for_current_user($service);
+
+        // Fake the app.
+        core_useragent::instance(true, 'Mozilla/5.0 (Linux; Android 7.1.1; Moto G Play Build/NPIS26.48-43-2; wv) ' .
+                'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36 MoodleMobile');
+
+        $result = external::get_tokens_for_qr_login($qrloginkey, $USER->id);
+        $result = external_api::clean_returnvalue(external::get_tokens_for_qr_login_returns(), $result);
+
+        $this->assertEmpty($result['warnings']);
+        $this->assertEquals($token->token, $result['token']);
+        $this->assertEquals($token->privatetoken, $result['privatetoken']);
+
+        // Now, try with an invalid key.
+        $this->expectException('moodle_exception');
+        $this->expectExceptionMessage(get_string('invalidkey', 'error'));
+        $result = external::get_tokens_for_qr_login(random_string('64'), $user->id);
+    }
+
+    /**
+     * Test get_tokens_for_qr_login missing QR code enabled.
+     */
+    public function test_get_tokens_for_qr_login_missing_enableqr() {
+        global $CFG, $USER;
+        $this->resetAfterTest(true);
+        $this->setAdminUser();
+
+        set_config('qrcodetype', tool_mobile\api::QR_CODE_DISABLED, 'tool_mobile');
+
+        $this->expectExceptionMessage(get_string('qrcodedisabled', 'tool_mobile'));
+        $result = external::get_tokens_for_qr_login('', $USER->id);
+    }
+
+    /**
+     * Test get_tokens_for_qr_login missing ws.
+     */
+    public function test_get_tokens_for_qr_login_missing_ws() {
+        global $CFG;
+        $this->resetAfterTest(true);
+
+        $user = $this->getDataGenerator()->create_user();
+        $this->setUser($user);
+
+        // Fake the app.
+        core_useragent::instance(true, 'Mozilla/5.0 (Linux; Android 7.1.1; Moto G Play Build/NPIS26.48-43-2; wv) ' .
+            'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36 MoodleMobile');
+
+        // Need to disable webservices to verify that's checked.
+        $CFG->enablewebservices = 0;
+        $CFG->enablemobilewebservice = 0;
+
+        $this->setAdminUser();
+        $this->expectException('moodle_exception');
+        $this->expectExceptionMessage(get_string('enablewsdescription', 'webservice'));
+        $result = external::get_tokens_for_qr_login('', $user->id);
+    }
+
+    /**
+     * Test get_tokens_for_qr_login missing https.
+     */
+    public function test_get_tokens_for_qr_login_missing_https() {
+        global $CFG, $USER;
+
+        // Fake the app.
+        core_useragent::instance(true, 'Mozilla/5.0 (Linux; Android 7.1.1; Moto G Play Build/NPIS26.48-43-2; wv) ' .
+            'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36 MoodleMobile');
+
+        // Need to simulate a non HTTPS site here.
+        $CFG->wwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
+
+        $this->resetAfterTest(true);
+        $this->setAdminUser();
+
+        $this->expectException('moodle_exception');
+        $this->expectExceptionMessage(get_string('httpsrequired', 'tool_mobile'));
+        $result = external::get_tokens_for_qr_login('', $USER->id);
+    }
+
+    /**
+     * Test get_tokens_for_qr_login missing admin.
+     */
+    public function test_get_tokens_for_qr_login_missing_admin() {
+        global $CFG, $USER;
+
+        $this->resetAfterTest(true);
+        $this->setAdminUser();
+
+        // Fake the app.
+        core_useragent::instance(true, 'Mozilla/5.0 (Linux; Android 7.1.1; Moto G Play Build/NPIS26.48-43-2; wv) ' .
+            'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36 MoodleMobile');
+
+        $this->expectException('moodle_exception');
+        $this->expectExceptionMessage(get_string('autologinnotallowedtoadmins', 'tool_mobile'));
+        $result = external::get_tokens_for_qr_login('', $USER->id);
+    }
+
+    /**
+     * Test get_tokens_for_qr_login missing app_request.
+     */
+    public function test_get_tokens_for_qr_login_missing_app_request() {
+        global $CFG, $USER;
+
+        $this->resetAfterTest(true);
+  &n