Merge branch 'MDL-64761-master' of git://github.com/dpalou/moodle
authorSara Arjona <sara@moodle.com>
Wed, 27 Feb 2019 14:36:18 +0000 (15:36 +0100)
committerSara Arjona <sara@moodle.com>
Wed, 27 Feb 2019 14:36:18 +0000 (15:36 +0100)
686 files changed:
.gitignore
admin/cli/install_database.php
admin/index.php
admin/renderer.php
admin/settings.php
admin/settings/subsystems.php
admin/templates/setting.mustache
admin/templates/setting_configcolourpicker.mustache
admin/templates/setting_configduration.mustache
admin/templates/setting_configfile.mustache
admin/templates/setting_configmultiselect.mustache
admin/templates/setting_configmultiselect_optgroup.mustache
admin/templates/setting_configselect.mustache
admin/templates/setting_configselect_optgroup.mustache
admin/templates/setting_configtext.mustache
admin/templates/setting_configtextarea.mustache
admin/templates/setting_configtime.mustache
admin/templates/setting_courselist_frontpage.mustache
admin/templates/setting_description.mustache
admin/templates/setting_devicedetectregex.mustache
admin/templates/setting_emoticons.mustache
admin/templates/setting_gradecat_combo.mustache
admin/templates/settings.mustache
admin/templates/settings_search_results.mustache
admin/tests/behat/behat_admin.php
admin/tool/analytics/classes/output/invalid_analysables.php
admin/tool/analytics/classes/output/models_list.php
admin/tool/analytics/lang/en/tool_analytics.php
admin/tool/analytics/templates/invalid_analysables.mustache
admin/tool/behat/cli/util.php
admin/tool/behat/cli/util_single_run.php
admin/tool/behat/lang/en/tool_behat.php
admin/tool/behat/tests/behat/manipulate_forms.feature
admin/tool/behat/tests/fixtures/core/behat_test_context_1.php
admin/tool/behat/tests/fixtures/core/behat_test_context_2.php
admin/tool/behat/tests/fixtures/theme/defaulttheme/behat_theme_defaulttheme_test_context_1.php
admin/tool/behat/tests/fixtures/theme/nofeatures/behat_theme_nofeatures_behat_test_context_2.php
admin/tool/behat/tests/fixtures/theme/nofeatures/behat_theme_nofeatures_test_context_1.php
admin/tool/behat/tests/fixtures/theme/withfeatures/behat_theme_withfeatures_behat_test_context_1.php
admin/tool/behat/tests/fixtures/theme/withfeatures/behat_theme_withfeatures_test_context_2.php
admin/tool/behat/tests/manager_util_test.php
admin/tool/behat/upgrade.txt
admin/tool/filetypes/edit_form.php
admin/tool/langimport/classes/locale.php [new file with mode: 0644]
admin/tool/langimport/index.php
admin/tool/langimport/lang/en/tool_langimport.php
admin/tool/langimport/tests/locale_test.php [new file with mode: 0644]
admin/tool/lp/classes/external.php
admin/tool/lp/classes/external/user_competency_summary_in_course_exporter.php
admin/tool/lp/classes/output/course_competencies_page.php
admin/tool/lp/templates/course_competencies_page.mustache
admin/tool/lp/templates/progress_bar.mustache
admin/tool/lp/templates/user_competency_summary_in_course.mustache
admin/tool/lp/tests/behat/plan_crud.feature
admin/tool/mobile/classes/api.php
admin/tool/mobile/db/upgrade.php [new file with mode: 0644]
admin/tool/mobile/version.php
admin/tool/task/tests/behat/clear_fail_delay.feature
admin/tool/task/tests/behat/manage_tasks.feature
admin/tool/uploadcourse/classes/base_form.php
admin/tool/uploadcourse/classes/step2_form.php
admin/tool/uploaduser/user_form.php
admin/tool/usertours/amd/build/managesteps.min.js
admin/tool/usertours/amd/build/managetours.min.js
admin/tool/usertours/amd/src/managesteps.js
admin/tool/usertours/amd/src/managetours.js
admin/tool/usertours/classes/helper.php
admin/tool/usertours/classes/local/target/block.php
admin/tool/usertours/classes/local/target/selector.php
admin/tool/usertours/classes/local/target/unattached.php
admin/tool/usertours/templates/tourstep.mustache
admin/tool/xmldb/actions/add_persistent_mandatory/add_persistent_mandatory.class.php [new file with mode: 0644]
admin/tool/xmldb/actions/edit_table/edit_table.class.php
admin/tool/xmldb/lang/en/tool_xmldb.php
auth/cas/auth.php
auth/cas/cas_form.html [deleted file]
auth/cas/lang/en/auth_cas.php
auth/cas/lang/en/deprecated.txt [new file with mode: 0644]
auth/cas/lib.php [new file with mode: 0644]
auth/cas/settings.php
auth/cas/version.php
auth/ldap/auth.php
auth/ldap/lang/en/auth_ldap.php
auth/mnet/classes/privacy/provider.php
auth/oauth2/classes/privacy/provider.php
auth/shibboleth/auth.php
auth/shibboleth/index_form.html [deleted file]
auth/shibboleth/lang/en/auth_shibboleth.php
auth/shibboleth/login.php
auth/shibboleth/templates/login_form.mustache [new file with mode: 0644]
auth/tests/behat/behat_auth.php
badges/criteria/award_criteria_activity.php
badges/tests/behat/criteria_activity.feature [new file with mode: 0644]
blocks/admin_bookmarks/tests/behat/bookmark_admin_pages.feature
blocks/community/classes/privacy/provider.php
blocks/html/classes/privacy/provider.php
blocks/login/block_login.php
blocks/myoverview/amd/build/view.min.js
blocks/myoverview/amd/src/view.js
blocks/myoverview/lang/en/block_myoverview.php
blocks/myoverview/lang/en/deprecated.txt
blocks/myoverview/templates/nav-grouping-selector.mustache
blocks/myoverview/templates/placeholders.mustache
blocks/recentlyaccessedcourses/amd/build/main.min.js
blocks/recentlyaccessedcourses/amd/src/main.js
blocks/recentlyaccessedcourses/classes/output/main.php
blocks/recentlyaccessedcourses/lang/en/block_recentlyaccessedcourses.php
blocks/recentlyaccessedcourses/templates/course-card.mustache [new file with mode: 0644]
blocks/recentlyaccessedcourses/templates/main.mustache
blocks/recentlyaccessedcourses/templates/recentlyaccessedcourses-view.mustache
blocks/rss_client/classes/privacy/provider.php
blocks/search_forums/templates/search_form.mustache
blocks/settings/renderer.php
blocks/settings/templates/search_form.mustache [moved from theme/boost/templates/block_settings/search_form.mustache with 100% similarity]
blocks/starredcourses/amd/build/main.min.js
blocks/starredcourses/amd/src/main.js
blocks/starredcourses/lang/en/block_starredcourses.php
blocks/starredcourses/templates/no-courses.mustache
blocks/starredcourses/templates/placeholder-course.mustache [deleted file]
blocks/starredcourses/templates/view-cards.mustache [deleted file]
blocks/starredcourses/templates/view.mustache
blocks/tests/behat/behat_blocks.php
cache/classes/loaders.php
cache/tests/cache_test.php
cache/tests/fixtures/lib.php
calendar/templates/minicalendar_day_link.mustache
competency/classes/api.php
competency/tests/api_test.php
completion/classes/privacy/provider.php
completion/classes/progress.php
completion/tests/privacy_test.php
composer.json
config-dist.php
course/classes/deletecategory_form.php
course/classes/management_renderer.php
course/completion.js
course/lib.php
course/modlib.php
course/moodleform_mod.php
course/renderer.php
course/templates/course_search_form.mustache [moved from theme/boost/templates/course_search_form.mustache with 100% similarity]
course/templates/coursecard.mustache [new file with mode: 0644]
course/templates/coursecards.mustache
course/templates/no-courses.mustache [moved from blocks/recentlyaccessedcourses/templates/no-courses.mustache with 79% similarity]
course/templates/placeholder-course.mustache [moved from blocks/recentlyaccessedcourses/templates/placeholder-course.mustache with 91% similarity]
course/templates/view-cards.mustache [moved from blocks/recentlyaccessedcourses/templates/view-cards.mustache with 95% similarity]
course/tests/behat/app_courselist.feature [new file with mode: 0644]
course/tests/behat/behat_course.php
course/tests/behat/view_subfolders_inline.feature
enrol/classes/privacy/provider.php
enrol/locallib.php
enrol/manual/amd/build/form-potential-user-selector.min.js
enrol/manual/amd/src/form-potential-user-selector.js
enrol/manual/classes/enrol_users_form.php
enrol/manual/tests/behat/quickenrolment.feature
enrol/renderer.php
enrol/self/tests/self_test.php
enrol/tests/course_enrolment_manager_test.php
enrol/upgrade.txt
enrol/yui/otherusersmanager/otherusersmanager.js
files/renderer.php
grade/edit/tree/calculation.php
grade/grading/form/guide/templates/comment_chooser.mustache
grade/report/history/classes/output/renderer.php
grade/report/history/templates/user_button.mustache [moved from theme/boost/templates/gradereport_history/user_button.mustache with 100% similarity]
grade/report/singleview/templates/bulk_insert.mustache
grade/report/singleview/templates/button.mustache
grade/report/singleview/templates/dropdown_attribute.mustache
grade/report/singleview/templates/text_attribute.mustache
grade/tests/behat/behat_grade.php
grade/tests/importlib_test.php
grades/templates/edit_tree.mustache [moved from theme/boost/templates/core_grades/edit_tree.mustache with 100% similarity]
grades/templates/weight_field.mustache [moved from theme/boost/templates/core_grades/weight_field.mustache with 100% similarity]
grades/templates/weight_override_field.mustache [moved from theme/boost/templates/core_grades/weight_override_field.mustache with 100% similarity]
group/externallib.php
group/tests/externallib_test.php
install/lang/eu/admin.php
install/lang/eu/install.php
install/lang/hr/admin.php
install/lang/ja/install.php
lang/en/admin.php
lang/en/competency.php
lang/en/enrol.php
lang/en/message.php
lib/accesslib.php
lib/adminlib.php
lib/amd/build/checkbox-toggleall.min.js [new file with mode: 0644]
lib/amd/build/icon_system_fontawesome.min.js
lib/amd/build/paged_content_paging_bar.min.js
lib/amd/build/showhidesettings.min.js [new file with mode: 0644]
lib/amd/build/storagewrapper.min.js
lib/amd/src/checkbox-toggleall.js [new file with mode: 0644]
lib/amd/src/icon_system_fontawesome.js
lib/amd/src/paged_content_paging_bar.js
lib/amd/src/showhidesettings.js [new file with mode: 0644]
lib/amd/src/storagewrapper.js
lib/behat/behat_base.php
lib/behat/classes/behat_command.php
lib/behat/classes/behat_config_util.php
lib/behat/classes/behat_context_helper.php
lib/behat/core_behat_file_helper.php [moved from lib/behat/behat_files.php with 94% similarity]
lib/behat/form_field/behat_form_field.php
lib/classes/analytics/analyser/courses.php
lib/classes/analytics/analyser/site_courses.php
lib/classes/message/manager.php
lib/classes/output/icon_system_fontawesome.php
lib/cronlib.php
lib/db/messages.php
lib/db/upgrade.php
lib/editor/atto/plugins/media/tests/behat/media.feature
lib/form/amd/build/showadvanced.min.js [new file with mode: 0644]
lib/form/amd/src/showadvanced.js [new file with mode: 0644]
lib/form/modgrade.php
lib/form/yui/build/moodle-form-showadvanced/moodle-form-showadvanced-debug.js [deleted file]
lib/form/yui/build/moodle-form-showadvanced/moodle-form-showadvanced-min.js [deleted file]
lib/form/yui/build/moodle-form-showadvanced/moodle-form-showadvanced.js [deleted file]
lib/form/yui/src/showadvanced/build.json [deleted file]
lib/form/yui/src/showadvanced/js/showadvanced.js [deleted file]
lib/form/yui/src/showadvanced/meta/showadvanced.json [deleted file]
lib/formslib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/phpmailer/README_MOODLE.txt
lib/phpmailer/src/PHPMailer.php
lib/phpunit/classes/arraydataset.php
lib/requirejs/moodle-config.js
lib/templates/action_menu.mustache
lib/templates/action_menu_link.mustache
lib/templates/action_menu_trigger.mustache
lib/templates/auth_digital_minor_page.mustache
lib/templates/auth_verify_age_location_page.mustache
lib/templates/availability_info.mustache
lib/templates/block.mustache [moved from theme/boost/templates/core/block.mustache with 100% similarity]
lib/templates/chooser.mustache
lib/templates/columns-1to1to1.mustache
lib/templates/columns-1to2.mustache
lib/templates/columns-2to1.mustache
lib/templates/custom_menu_item.mustache [moved from theme/boost/templates/core/custom_menu_item.mustache with 100% similarity]
lib/templates/dataformat_selector.mustache
lib/templates/filemanager_confirmdialog.mustache [moved from theme/boost/templates/core/filemanager_confirmdialog.mustache with 100% similarity]
lib/templates/filemanager_default_searchform.mustache [moved from theme/boost/templates/core/filemanager_default_searchform.mustache with 100% similarity]
lib/templates/filemanager_fileselect.mustache [moved from theme/boost/templates/core/filemanager_fileselect.mustache with 100% similarity]
lib/templates/filemanager_loginform.mustache [moved from theme/boost/templates/core/filemanager_loginform.mustache with 100% similarity]
lib/templates/filemanager_modal_generallayout.mustache [moved from theme/boost/templates/core/filemanager_modal_generallayout.mustache with 100% similarity]
lib/templates/filemanager_page_generallayout.mustache [moved from theme/boost/templates/core/filemanager_page_generallayout.mustache with 100% similarity]
lib/templates/filemanager_processexistingfile.mustache [moved from theme/boost/templates/core/filemanager_processexistingfile.mustache with 100% similarity]
lib/templates/filemanager_processexistingfilemultiple.mustache [moved from theme/boost/templates/core/filemanager_processexistingfilemultiple.mustache with 100% similarity]
lib/templates/filemanager_selectlayout.mustache [moved from theme/boost/templates/core/filemanager_selectlayout.mustache with 100% similarity]
lib/templates/filemanager_uploadform.mustache [moved from theme/boost/templates/core/filemanager_uploadform.mustache with 100% similarity]
lib/templates/form_autocomplete_input.mustache
lib/templates/form_autocomplete_selection.mustache
lib/templates/full_header.mustache [moved from theme/boost/templates/header.mustache with 100% similarity]
lib/templates/help_icon.mustache
lib/templates/initials_bar.mustache
lib/templates/loginform.mustache
lib/templates/modal.mustache
lib/templates/modal_backdrop.mustache
lib/templates/navbar.mustache [moved from theme/boost/templates/core/navbar.mustache with 97% similarity]
lib/templates/notification_error.mustache
lib/templates/notification_info.mustache
lib/templates/notification_success.mustache
lib/templates/notification_warning.mustache
lib/templates/pix_icon_fontawesome.mustache
lib/templates/preferences_groups.mustache [moved from theme/boost/templates/core/preferences_groups.mustache with 100% similarity]
lib/templates/progress_bar.mustache
lib/templates/select_time.mustache
lib/templates/settings_link_page.mustache
lib/templates/settings_link_page_single.mustache
lib/templates/signup_form_layout.mustache
lib/templates/single_button.mustache
lib/templates/skip_links.mustache
lib/templates/tabtree.mustache [moved from theme/boost/templates/core/tabtree.mustache with 100% similarity]
lib/templates/url_select.mustache
lib/tests/behat/app_behat_runtime.js [new file with mode: 0644]
lib/tests/behat/behat_action_menu.php
lib/tests/behat/behat_app.php [new file with mode: 0644]
lib/tests/behat/behat_deprecated.php
lib/tests/behat/behat_hooks.php
lib/tests/behat/behat_navigation.php
lib/tests/moodlelib_test.php
lib/tests/outputcomponents_test.php
lib/tests/weblib_test.php
lib/typo3/class.t3lib_div.php
lib/typo3/readme_moodle.txt
lib/upgrade.txt
lib/weblib.php
login/change_password_form.php
login/forgot_password_form.php
message/amd/build/message_area.min.js [deleted file]
message/amd/build/message_area_actions.min.js [deleted file]
message/amd/build/message_area_contacts.min.js [deleted file]
message/amd/build/message_area_events.min.js [deleted file]
message/amd/build/message_area_messages.min.js [deleted file]
message/amd/build/message_area_profile.min.js [deleted file]
message/amd/build/message_area_search.min.js [deleted file]
message/amd/build/message_area_tabs.min.js [deleted file]
message/amd/build/message_drawer.min.js
message/amd/build/message_drawer_router.min.js
message/amd/build/message_drawer_view_contact.min.js
message/amd/build/message_drawer_view_contacts.min.js
message/amd/build/message_drawer_view_contacts_section_contacts.min.js
message/amd/build/message_drawer_view_conversation.min.js
message/amd/build/message_drawer_view_group_info.min.js
message/amd/build/message_drawer_view_overview.min.js
message/amd/build/message_drawer_view_overview_section.min.js
message/amd/build/message_drawer_view_search.min.js
message/amd/build/message_drawer_view_settings.min.js
message/amd/build/message_preferences.min.js [deleted file]
message/amd/build/message_user_button.min.js [new file with mode: 0644]
message/amd/build/notification_processor_settings.min.js
message/amd/build/preferences_notifications_list_controller.min.js
message/amd/build/preferences_processor_form.min.js
message/amd/src/message_area.js [deleted file]
message/amd/src/message_area_actions.js [deleted file]
message/amd/src/message_area_contacts.js [deleted file]
message/amd/src/message_area_events.js [deleted file]
message/amd/src/message_area_messages.js [deleted file]
message/amd/src/message_area_profile.js [deleted file]
message/amd/src/message_area_search.js [deleted file]
message/amd/src/message_area_tabs.js [deleted file]
message/amd/src/message_drawer.js
message/amd/src/message_drawer_router.js
message/amd/src/message_drawer_view_contact.js
message/amd/src/message_drawer_view_contacts.js
message/amd/src/message_drawer_view_contacts_section_contacts.js
message/amd/src/message_drawer_view_conversation.js
message/amd/src/message_drawer_view_group_info.js
message/amd/src/message_drawer_view_overview.js
message/amd/src/message_drawer_view_overview_section.js
message/amd/src/message_drawer_view_search.js
message/amd/src/message_drawer_view_settings.js
message/amd/src/message_preferences.js [deleted file]
message/amd/src/message_user_button.js [new file with mode: 0644]
message/amd/src/notification_processor_settings.js
message/amd/src/preferences_notifications_list_controller.js
message/amd/src/preferences_processor_form.js
message/classes/api.php
message/classes/helper.php
message/classes/output/messagearea/contact.php
message/classes/output/messagearea/contacts.php
message/classes/output/messagearea/message.php
message/classes/output/messagearea/message_area.php
message/classes/output/messagearea/message_search_results.php [deleted file]
message/classes/output/messagearea/messages.php
message/classes/output/messagearea/profile.php
message/classes/output/messagearea/user_search_results.php
message/externallib.php
message/index.php
message/lib.php
message/output/airnotifier/classes/privacy/provider.php
message/pendingcontactrequests.php [deleted file]
message/templates/message_area.mustache [deleted file]
message/templates/message_area_contact.mustache [deleted file]
message/templates/message_area_contacts.mustache [deleted file]
message/templates/message_area_contacts_area.mustache [deleted file]
message/templates/message_area_message.mustache [deleted file]
message/templates/message_area_message_search_results.mustache [deleted file]
message/templates/message_area_messages_area.mustache [deleted file]
message/templates/message_area_profile.mustache [deleted file]
message/templates/message_area_response.mustache [deleted file]
message/templates/message_area_user_search_results.mustache [deleted file]
message/templates/message_drawer.mustache
message/templates/message_drawer_view_conversation_body_message.mustache
message/templates/message_drawer_view_conversation_footer_content.mustache
message/templates/message_drawer_view_overview_body.mustache
message/templates/message_drawer_view_overview_footer.mustache [moved from theme/boost/templates/core_admin/setting_configfile.mustache with 57% similarity]
message/templates/message_drawer_view_overview_section.mustache
message/templates/message_index.mustache [new file with mode: 0644]
message/templates/message_preferences.mustache [deleted file]
message/templates/message_preferences_component.mustache [deleted file]
message/templates/message_preferences_notification_processor.mustache [deleted file]
message/templates/preferences_processor.mustache
message/tests/behat/message_admin_settings.feature [new file with mode: 0644]
message/tests/externallib_test.php
message/tests/privacy_provider_test.php
message/upgrade.txt
mod/assign/amd/build/grading_navigation_user_info.min.js
mod/assign/amd/src/grading_navigation_user_info.js
mod/assign/classes/event/base.php
mod/assign/classes/event/remove_submission_form_viewed.php [new file with mode: 0644]
mod/assign/classes/task/cron_task.php [new file with mode: 0644]
mod/assign/db/tasks.php [new file with mode: 0644]
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/editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/globals.js
mod/assign/gradingbatchoperationsform.php
mod/assign/gradingtable.php
mod/assign/lang/en/assign.php
mod/assign/lib.php
mod/assign/locallib.php
mod/assign/renderer.php
mod/assign/submission/file/locallib.php
mod/assign/submission/onlinetext/locallib.php
mod/assign/submissionplugin.php
mod/assign/templates/grading_actions.mustache
mod/assign/templates/grading_navigation.mustache
mod/assign/templates/grading_navigation_user_selector.mustache
mod/assign/tests/behat/allow_another_attempt.feature
mod/assign/tests/behat/edit_student_submission.feature
mod/assign/tests/behat/page_titles.feature [new file with mode: 0644]
mod/assign/tests/behat/remove_submission.feature [new file with mode: 0644]
mod/assign/tests/events_test.php
mod/assign/upgrade.txt
mod/assign/version.php
mod/book/edit.php
mod/book/edit_form.php
mod/book/lang/en/book.php
mod/book/locallib.php
mod/book/tests/behat/create_chapters.feature
mod/book/tests/behat/reorganize_chapters.feature
mod/book/tests/behat/show_hide_chapters.feature
mod/book/tool/print/classes/output/print_book_chapter_page.php [new file with mode: 0644]
mod/book/tool/print/classes/output/print_book_page.php [new file with mode: 0644]
mod/book/tool/print/classes/output/renderer.php [new file with mode: 0644]
mod/book/tool/print/index.php
mod/book/tool/print/locallib.php
mod/book/tool/print/print.css
mod/book/tool/print/templates/print_book.mustache [new file with mode: 0644]
mod/book/tool/print/templates/print_book_chapter.mustache [new file with mode: 0644]
mod/chat/lib.php
mod/chat/tests/lib_test.php
mod/data/lib.php
mod/feedback/amd/build/edit.min.js
mod/feedback/amd/src/edit.js
mod/forum/index.php
mod/forum/lib.php
mod/forum/post.php
mod/forum/templates/big_search_form.mustache
mod/forum/templates/quick_search_form.mustache
mod/forum/tests/behat/app_basic_usage.feature [new file with mode: 0644]
mod/forum/tests/behat/posts_ordering_general.feature
mod/forum/tests/lib_test.php
mod/glossary/lib.php
mod/glossary/tests/lib_test.php
mod/glossary/view.php
mod/lesson/lib.php
mod/lesson/locallib.php
mod/lesson/tests/lib_test.php
mod/lesson/tests/locallib_test.php
mod/lti/service/gradebookservices/classes/local/service/gradebookservices.php
mod/quiz/accessrule/timelimit/rule.php
mod/quiz/accessrule/timelimit/tests/rule_test.php
mod/quiz/amd/build/repaginate.min.js [new file with mode: 0644]
mod/quiz/amd/src/repaginate.js [new file with mode: 0644]
mod/quiz/attemptlib.php
mod/quiz/classes/output/edit_renderer.php
mod/quiz/classes/task/legacy_quiz_accessrules_cron.php [moved from message/classes/output/renderer.php with 54% similarity]
mod/quiz/classes/task/legacy_quiz_reports_cron.php [moved from theme/boost/classes/output/gradereport_history_renderer.php with 58% similarity]
mod/quiz/classes/task/update_overdue_attempts.php [new file with mode: 0644]
mod/quiz/db/tasks.php [new file with mode: 0644]
mod/quiz/lang/en/quiz.php
mod/quiz/lib.php
mod/quiz/report/statistics/classes/task/quiz_statistics_cleanup.php [new file with mode: 0644]
mod/quiz/report/statistics/db/tasks.php [new file with mode: 0644]
mod/quiz/report/statistics/lang/en/quiz_statistics.php
mod/quiz/report/statistics/lib.php
mod/quiz/report/statistics/version.php
mod/quiz/tests/attempt_test.php
mod/quiz/tests/behat/behat_mod_quiz.php
mod/quiz/tests/lib_test.php
mod/quiz/upgrade.txt
mod/quiz/version.php
mod/quiz/yui/build/moodle-mod_quiz-repaginate/moodle-mod_quiz-repaginate-debug.js [deleted file]
mod/quiz/yui/build/moodle-mod_quiz-repaginate/moodle-mod_quiz-repaginate-min.js [deleted file]
mod/quiz/yui/build/moodle-mod_quiz-repaginate/moodle-mod_quiz-repaginate.js [deleted file]
mod/quiz/yui/src/repaginate/build.json [deleted file]
mod/quiz/yui/src/repaginate/js/repaginate.js [deleted file]
mod/quiz/yui/src/repaginate/meta/repaginate.json [deleted file]
mod/scorm/lib.php
mod/scorm/locallib.php
mod/scorm/tests/lib_test.php
mod/wiki/lib.php
mod/wiki/version.php
mod/workshop/lib.php
mod/workshop/mod_form.php
mod/workshop/tests/behat/grade_to_pass.feature
portfolio/classes/privacy/provider.php
privacy/classes/local/request/moodle_content_writer.php
question/amd/build/qbankmanager.min.js [new file with mode: 0644]
question/amd/src/qbankmanager.js [new file with mode: 0644]
question/behaviour/adaptive/tests/walkthrough_test.php
question/behaviour/behaviourbase.php
question/behaviour/interactivecountback/tests/walkthrough_test.php
question/behaviour/manualgraded/tests/walkthrough_test.php
question/category_class.php
question/classes/bank/checkbox_column.php
question/classes/bank/tags_action_column.php
question/classes/bank/view.php
question/engine/lib.php
question/engine/tests/helpers.php
question/engine/tests/questionutils_test.php
question/renderer.php
question/tests/behat/question_categories.feature
question/tests/behat/question_categories_idnumber.feature
question/tests/behat/select_questions.feature [new file with mode: 0644]
question/type/ddimageortext/amd/build/question.min.js
question/type/ddimageortext/amd/src/question.js
question/type/ddimageortext/edit_ddimageortext_form.php
question/type/ddmarker/amd/build/question.min.js
question/type/ddmarker/amd/src/question.js
question/type/ddwtos/tests/behat/edit.feature
question/type/essay/backup/moodle2/restore_qtype_essay_plugin.class.php
question/type/essay/tests/restore_test.php [new file with mode: 0644]
question/type/gapselect/edit_form_base.php
question/type/gapselect/lang/en/qtype_gapselect.php
question/type/gapselect/renderer.php
question/type/gapselect/rendererbase.php
question/type/gapselect/tests/helper.php
question/type/gapselect/tests/walkthrough_test.php
question/type/match/tests/walkthrough_test.php
question/type/multianswer/tests/walkthrough_test.php
question/type/numerical/renderer.php
question/type/numerical/styles.css
question/type/numerical/tests/walkthrough_test.php
question/type/randomsamatch/tests/walkthrough_test.php
question/yui/build/moodle-question-qbankmanager/moodle-question-qbankmanager-debug.js [deleted file]
question/yui/build/moodle-question-qbankmanager/moodle-question-qbankmanager-min.js [deleted file]
question/yui/build/moodle-question-qbankmanager/moodle-question-qbankmanager.js [deleted file]
question/yui/src/qbankmanager/build.json [deleted file]
question/yui/src/qbankmanager/js/qbankmanager.js [deleted file]
question/yui/src/qbankmanager/meta/qbankmanager.json [deleted file]
report/completion/index.php
report/insights/templates/insight.mustache
report/insights/templates/insight_details.mustache
report/insights/templates/insights_list.mustache
report/progress/index.php
report/security/locallib.php
repository/classes/privacy/provider.php
repository/equella/lib.php
repository/onedrive/classes/privacy/provider.php
repository/tests/behat/behat_filepicker.php
repository/upload/tests/behat/behat_repository_upload.php
theme/boost/amd/build/drawer.min.js
theme/boost/amd/src/drawer.js
theme/boost/classes/output/core/files_renderer.php [deleted file]
theme/boost/classes/output/core_renderer.php
theme/boost/classes/output/core_renderer_maintenance.php [deleted file]
theme/boost/layout/columns2.php
theme/boost/scss/moodle/blocks.scss
theme/boost/scss/moodle/core.scss
theme/boost/scss/moodle/forms.scss
theme/boost/scss/moodle/message.scss
theme/boost/style/moodle.css
theme/boost/templates/block_search_forums/search_form.mustache [deleted file]
theme/boost/templates/columns1.mustache
theme/boost/templates/columns2.mustache
theme/boost/templates/core/action_menu_trigger.mustache [deleted file]
theme/boost/templates/core/auth_digital_minor_page.mustache [deleted file]
theme/boost/templates/core/auth_verify_age_location_page.mustache [deleted file]
theme/boost/templates/core/availability_info.mustache [deleted file]
theme/boost/templates/core/help_icon.mustache [deleted file]
theme/boost/templates/core/loginform.mustache [deleted file]
theme/boost/templates/core/settings_link_page.mustache [deleted file]
theme/boost/templates/core/signup_form_layout.mustache [deleted file]
theme/boost/templates/core_admin/setting_configduration.mustache [deleted file]
theme/boost/templates/core_admin/setting_configmultiselect_optgroup.mustache [deleted file]
theme/boost/templates/core_admin/setting_configtime.mustache [deleted file]
theme/boost/templates/core_calendar/minicalendar_day_link.mustache [deleted file]
theme/boost/templates/core_form/element-password.mustache
theme/boost/templates/flat_navigation.mustache
theme/boost/templates/footer.mustache
theme/boost/templates/gradereport_singleview/button.mustache [deleted file]
theme/boost/templates/login.mustache
theme/boost/templates/maintenance.mustache
theme/boost/templates/mod_forum/quick_search_form.mustache [deleted file]
theme/boost/templates/navbar-secure.mustache
theme/boost/templates/secure.mustache
theme/boost/tests/behat/behat_theme_boost_behat_blocks.php [deleted file]
theme/boost/tests/behat/behat_theme_boost_behat_navigation.php [deleted file]
theme/boost/upgrade.txt
theme/boost/version.php
theme/bootstrapbase/less/moodle/admin.less
theme/bootstrapbase/less/moodle/blocks.less
theme/bootstrapbase/less/moodle/bs4-compat.less
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/forms.less
theme/bootstrapbase/less/moodle/message.less
theme/bootstrapbase/less/moodle/responsive.less
theme/bootstrapbase/renderers.php
theme/bootstrapbase/renderers/block_settings_renderer.php [moved from theme/boost/classes/output/block_settings_renderer.php with 60% similarity]
theme/bootstrapbase/renderers/core/course_renderer.php [moved from theme/boost/classes/output/core/course_renderer.php with 62% similarity]
theme/bootstrapbase/renderers/core/files_renderer.php [new file with mode: 0644]
theme/bootstrapbase/renderers/core_course/management/renderer.php [moved from theme/boost/classes/output/core_course/management/renderer.php with 56% similarity]
theme/bootstrapbase/renderers/core_question/bank_renderer.php [moved from theme/boost/classes/output/core_question/bank_renderer.php with 62% similarity]
theme/bootstrapbase/renderers/core_renderer.php
theme/bootstrapbase/renderers/gradereport_history_renderer.php [new file with mode: 0644]
theme/bootstrapbase/style/moodle.css
theme/bootstrapbase/templates/block_search_forums/search_form.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/action_menu.mustache [moved from theme/boost/templates/core/action_menu.mustache with 55% similarity]
theme/bootstrapbase/templates/core/action_menu_item.mustache [moved from theme/boost/templates/core/action_menu_item.mustache with 100% similarity]
theme/bootstrapbase/templates/core/action_menu_link.mustache [moved from theme/boost/templates/core/action_menu_link.mustache with 88% similarity]
theme/bootstrapbase/templates/core/action_menu_trigger.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/auth_digital_minor_page.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/auth_verify_age_location_page.mustache [moved from blocks/myoverview/templates/no-courses.mustache with 58% similarity]
theme/bootstrapbase/templates/core/chooser.mustache [moved from theme/boost/templates/core/chooser.mustache with 94% similarity]
theme/bootstrapbase/templates/core/columns-1to1to1.mustache [moved from theme/boost/templates/core/columns-1to1to1.mustache with 86% similarity]
theme/bootstrapbase/templates/core/columns-1to2.mustache [moved from theme/boost/templates/core/columns-1to2.mustache with 88% similarity]
theme/bootstrapbase/templates/core/columns-2to1.mustache [moved from theme/boost/templates/core/columns-2to1.mustache with 88% similarity]
theme/bootstrapbase/templates/core/dataformat_selector.mustache [moved from theme/boost/templates/core/dataformat_selector.mustache with 68% similarity]
theme/bootstrapbase/templates/core/form_autocomplete_input.mustache [moved from theme/boost/templates/core/form_autocomplete_input.mustache with 83% similarity]
theme/bootstrapbase/templates/core/form_autocomplete_selection.mustache [moved from theme/boost/templates/core/form_autocomplete_selection.mustache with 83% similarity]
theme/bootstrapbase/templates/core/help_icon.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/initials_bar.mustache [moved from theme/boost/templates/core/initials_bar.mustache with 75% similarity]
theme/bootstrapbase/templates/core/loginform.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/modal.mustache [moved from theme/boost/templates/core/modal.mustache with 53% similarity]
theme/bootstrapbase/templates/core/modal_backdrop.mustache [moved from theme/boost/templates/core/modal_backdrop.mustache with 91% similarity]
theme/bootstrapbase/templates/core/notification_error.mustache [moved from theme/boost/templates/core/notification_error.mustache with 84% similarity]
theme/bootstrapbase/templates/core/notification_info.mustache [moved from theme/boost/templates/core/notification_info.mustache with 88% similarity]
theme/bootstrapbase/templates/core/notification_success.mustache [moved from theme/boost/templates/core/notification_success.mustache with 88% similarity]
theme/bootstrapbase/templates/core/notification_warning.mustache [moved from theme/boost/templates/core/notification_warning.mustache with 88% similarity]
theme/bootstrapbase/templates/core/progress_bar.mustache [moved from theme/boost/templates/core/progress_bar.mustache with 67% similarity]
theme/bootstrapbase/templates/core/select_time.mustache [moved from theme/boost/templates/core/select_time.mustache with 92% similarity]
theme/bootstrapbase/templates/core/settings_link_page.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/settings_link_page_single.mustache [moved from theme/boost/templates/core/settings_link_page_single.mustache with 96% similarity]
theme/bootstrapbase/templates/core/signup_form_layout.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core/single_button.mustache [moved from theme/boost/templates/core/single_button.mustache with 97% similarity]
theme/bootstrapbase/templates/core/skip_links.mustache [moved from theme/boost/templates/core/skip_links.mustache with 60% similarity]
theme/bootstrapbase/templates/core_admin/setting.mustache [moved from theme/boost/templates/core_admin/setting.mustache with 50% similarity]
theme/bootstrapbase/templates/core_admin/setting_configcolourpicker.mustache [moved from theme/boost/templates/core_admin/setting_configcolourpicker.mustache with 67% similarity]
theme/bootstrapbase/templates/core_admin/setting_configduration.mustache [moved from theme/boost/templates/core_admin/setting_configselect.mustache with 53% similarity]
theme/bootstrapbase/templates/core_admin/setting_configfile.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core_admin/setting_configmultiselect.mustache [moved from theme/boost/templates/core_admin/setting_configmultiselect.mustache with 60% similarity]
theme/bootstrapbase/templates/core_admin/setting_configmultiselect_optgroup.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core_admin/setting_configselect.mustache [moved from theme/boost/templates/core_admin/setting_configselect_optgroup.mustache with 62% similarity]
theme/bootstrapbase/templates/core_admin/setting_configselect_optgroup.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core_admin/setting_configtext.mustache [moved from theme/boost/templates/core_admin/setting_configtext.mustache with 52% similarity]
theme/bootstrapbase/templates/core_admin/setting_configtextarea.mustache [moved from theme/boost/templates/core_admin/setting_configtextarea.mustache with 56% similarity]
theme/bootstrapbase/templates/core_admin/setting_configtime.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/core_admin/setting_courselist_frontpage.mustache [moved from theme/boost/templates/core_admin/setting_courselist_frontpage.mustache with 57% similarity]
theme/bootstrapbase/templates/core_admin/setting_description.mustache [moved from theme/boost/templates/core_admin/setting_description.mustache with 85% similarity]
theme/bootstrapbase/templates/core_admin/setting_devicedetectregex.mustache [moved from theme/boost/templates/core_admin/setting_devicedetectregex.mustache with 69% similarity]
theme/bootstrapbase/templates/core_admin/setting_emoticons.mustache [moved from theme/boost/templates/core_admin/setting_emoticons.mustache with 80% similarity]
theme/bootstrapbase/templates/core_admin/setting_gradecat_combo.mustache [moved from theme/boost/templates/core_admin/setting_gradecat_combo.mustache with 69% similarity]
theme/bootstrapbase/templates/core_admin/settings.mustache [moved from theme/boost/templates/core_admin/settings.mustache with 62% similarity]
theme/bootstrapbase/templates/core_admin/settings_search_results.mustache [moved from theme/boost/templates/core_admin/settings_search_results.mustache with 91% similarity]
theme/bootstrapbase/templates/core_message/message_drawer.mustache
theme/bootstrapbase/templates/core_message/message_drawer_view_conversation_body_message.mustache
theme/bootstrapbase/templates/core_message/message_drawer_view_conversation_footer_content.mustache
theme/bootstrapbase/templates/core_message/message_drawer_view_overview_section.mustache
theme/bootstrapbase/templates/core_message/message_index.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/gradereport_singleview/bulk_insert.mustache [moved from theme/boost/templates/gradereport_singleview/bulk_insert.mustache with 92% similarity]
theme/bootstrapbase/templates/gradereport_singleview/button.mustache [moved from message/templates/message_area_messages.mustache with 89% similarity]
theme/bootstrapbase/templates/gradereport_singleview/dropdown_attribute.mustache [moved from theme/boost/templates/gradereport_singleview/dropdown_attribute.mustache with 89% similarity]
theme/bootstrapbase/templates/gradereport_singleview/text_attribute.mustache [moved from theme/boost/templates/gradereport_singleview/text_attribute.mustache with 89% similarity]
theme/bootstrapbase/templates/gradingform_guide/comment_chooser.mustache [moved from theme/boost/templates/gradingform_guide/comment_chooser.mustache with 87% similarity]
theme/bootstrapbase/templates/mod_assign/grading_actions.mustache [moved from theme/boost/templates/mod_assign/grading_actions.mustache with 75% similarity]
theme/bootstrapbase/templates/mod_assign/grading_navigation.mustache [moved from theme/boost/templates/mod_assign/grading_navigation.mustache with 90% similarity]
theme/bootstrapbase/templates/mod_assign/grading_navigation_user_selector.mustache [moved from theme/boost/templates/mod_assign/grading_navigation_user_selector.mustache with 57% similarity]
theme/bootstrapbase/templates/mod_forum/big_search_form.mustache [moved from theme/boost/templates/mod_forum/big_search_form.mustache with 64% similarity]
theme/bootstrapbase/templates/mod_forum/quick_search_form.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/tool_lp/progress_bar.mustache [moved from theme/boost/templates/tool_lp/progress_bar.mustache with 69% similarity]
theme/bootstrapbase/templates/tool_usertours/tourstep.mustache [moved from theme/boost/templates/tool_usertours/tourstep.mustache with 66% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_action_menu.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_action_menu.php with 71% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_admin.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_admin.php with 68% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_blocks.php [new file with mode: 0644]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_course.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_course.php with 68% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_deprecated.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_deprecated.php with 59% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_filepicker.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_filepicker.php with 57% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_grade.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_grade.php with 72% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_mod_quiz.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_mod_quiz.php with 79% similarity]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_navigation.php [new file with mode: 0644]
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_repository_upload.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_repository_upload.php with 74% similarity]
theme/bootstrapbase/tests/behat/blacklist.json [new file with mode: 0644]
theme/bootstrapbase/tests/behat/theme_bootstrapbase_behat_file_helper.php [moved from theme/boost/tests/behat/behat_theme_boost_behat_files.php with 73% similarity]
theme/bootstrapbase/upgrade.txt
theme/bootstrapbase/version.php
theme/upgrade.txt
user/classes/privacy/provider.php
user/editadvanced_form.php
user/editlib.php
user/language_form.php
user/lib.php
user/profile/field/checkbox/classes/privacy/provider.php
user/profile/field/datetime/classes/privacy/provider.php
user/profile/field/menu/classes/privacy/provider.php
user/profile/field/text/classes/privacy/provider.php
user/profile/field/textarea/classes/privacy/provider.php
user/tests/behat/behat_user.php
user/tests/behat/input-purpose.feature [new file with mode: 0644]
version.php
webservice/classes/privacy/provider.php

index 1dab0f7..b96359f 100644 (file)
@@ -9,10 +9,18 @@
 #
 # See gitignore(5) man page for more details
 #
+
+# Swap files (vim)
+[._]*.s[a-v][a-z]
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+# Temporary files including undo
+*~
+#
 /config.php
 /lib/editor/tinymce/extra/tools/temp/
-*~
-*.swp
 /tags
 /TAGS
 /cscope.*
index 0dd6122..8b5fe93 100644 (file)
@@ -82,11 +82,6 @@ require_once($CFG->libdir.'/installlib.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/componentlib.class.php');
 
-// make sure no tables are installed yet
-if ($DB->get_tables() ) {
-    cli_error(get_string('clitablesexist', 'install'));
-}
-
 $CFG->early_install_lang = true;
 get_string_manager(true);
 
@@ -109,12 +104,17 @@ list($options, $unrecognized) = cli_get_params(
     )
 );
 
-
+// We show help text even if tables are installed.
 if ($options['help']) {
     echo $help;
     die;
 }
 
+// Make sure no tables are installed yet.
+if ($DB->get_tables() ) {
+    cli_error(get_string('clitablesexist', 'install'));
+}
+
 if (!$options['agree-license']) {
     cli_error('You have to agree to the license. --help prints out the help'); // TODO: localize
 }
index e04c319..c34a437 100644 (file)
@@ -823,9 +823,11 @@ if (isset($SESSION->pluginuninstallreturn)) {
 // Print default admin page with notifications.
 $errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED');
 
-// We make the assumption that at least one schedule task should run once per day.
-$lastcron = $DB->get_field_sql('SELECT MAX(lastruntime) FROM {task_scheduled}');
+$lastcron = get_config('tool_task', 'lastcronstart');
 $cronoverdue = ($lastcron < time() - 3600 * 24);
+$lastcroninterval = get_config('tool_task', 'lastcroninterval');
+$expectedfrequency = $CFG->expectedcronfrequency ?? 200;
+$croninfrequent = !$cronoverdue && ($lastcroninterval > $expectedfrequency || $lastcron < time() - $expectedfrequency);
 $dbproblems = $DB->diagnose();
 $maintenancemode = !empty($CFG->maintenance_enabled);
 
@@ -886,4 +888,4 @@ $output = $PAGE->get_renderer('core', 'admin');
 echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
                                        $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
                                        $registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
-                                       $mobileconfigured, $overridetossl, $invalidforgottenpasswordurl);
+                                       $mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent);
index da59ef6..57eaa0e 100644 (file)
@@ -281,6 +281,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * @param bool $mobileconfigured Whether the mobile web services have been enabled
      * @param bool $overridetossl Whether or not ssl is being forced.
      * @param bool $invalidforgottenpasswordurl Whether the forgotten password URL does not link to a valid URL.
+     * @param bool $croninfrequent If true, warn that cron hasn't run in the past few minutes
      *
      * @return string HTML to output.
      */
@@ -288,7 +289,7 @@ class core_admin_renderer extends plugin_renderer_base {
             $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
             $buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0,
             $themedesignermode = false, $devlibdir = false, $mobileconfigured = false,
-            $overridetossl = false, $invalidforgottenpasswordurl = false) {
+            $overridetossl = false, $invalidforgottenpasswordurl = false, $croninfrequent = false) {
         global $CFG;
         $output = '';
 
@@ -302,6 +303,7 @@ class core_admin_renderer extends plugin_renderer_base {
         $output .= $this->display_errors_warning($errorsdisplayed);
         $output .= $this->buggy_iconv_warning($buggyiconvnomb);
         $output .= $this->cron_overdue_warning($cronoverdue);
+        $output .= $this->cron_infrequent_warning($croninfrequent);
         $output .= $this->db_problems($dbproblems);
         $output .= $this->maintenance_mode_warning($maintenancemode);
         $output .= $this->overridetossl_warning($overridetossl);
@@ -614,6 +616,24 @@ class core_admin_renderer extends plugin_renderer_base {
                 $this->help_icon('cron', 'admin'));
     }
 
+    /**
+     * Render an appropriate message if cron is not being run frequently (recommended every minute).
+     *
+     * @param bool $croninfrequent
+     * @return string HTML to output.
+     */
+    public function cron_infrequent_warning(bool $croninfrequent) : string {
+        global $CFG;
+
+        if (!$croninfrequent) {
+            return '';
+        }
+
+        $expectedfrequency = $CFG->expectedcronfrequency ?? 200;
+        return $this->warning(get_string('croninfrequent', 'admin', $expectedfrequency) . '&nbsp;' .
+                $this->help_icon('cron', 'admin'));
+    }
+
     /**
      * Render an appropriate message if there are any problems with the DB set-up.
      * @param bool $dbproblems
index ecd2455..0872e03 100644 (file)
@@ -156,4 +156,11 @@ $PAGE->requires->yui_module('moodle-core-formchangechecker',
 );
 $PAGE->requires->string_for_js('changesmadereallygoaway', 'moodle');
 
+if ($settingspage->has_dependencies()) {
+    $opts = [
+        'dependencies' => $settingspage->get_dependencies_for_javascript()
+    ];
+    $PAGE->requires->js_call_amd('core/showhidesettings', 'init', [$opts]);
+}
+
 echo $OUTPUT->footer();
index a108b42..b559de3 100644 (file)
@@ -21,6 +21,12 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
         0)
     );
 
+    $optionalsubsystems->add(new admin_setting_configcheckbox('messagingdefaultpressenter',
+        new lang_string('messagingdefaultpressenter', 'admin'),
+        new lang_string('configmessagingdefaultpressenter', 'admin'),
+        1)
+    );
+
     $options = array(
         DAYSECS => new lang_string('secondstotime86400'),
         WEEKSECS => new lang_string('secondstotime604800'),
index ed17246..af78e7e 100644 (file)
@@ -29,6 +29,7 @@
     * element - The Element HTML
     * forceltr - Force this element to be displayed LTR
     * default - Default value
+    * dependenton - optional message listing the settings this one is dependent on
 
     Example context (json):
     {
         "default": "Default value"
     }
 }}
-<div class="form-item clearfix" id="{{id}}">
-    <div class="form-label">
+{{!
+    Setting.
+}}
+<div class="form-item row" id="{{id}}">
+    <div class="form-label col-sm-3 text-sm-right">
         <label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
             {{{title}}}
             {{#override}}
                 <div class="form-warning">{{warning}}</div>
             {{/warning}}
         </label>
-        <span class="form-shortname">{{{name}}}</span>
+        <span class="form-shortname d-block small text-muted">{{{name}}}</span>
     </div>
-    <div class="form-setting">
+    <div class="form-setting col-sm-9">
         {{#error}}
             <div><span class="error">{{error}}</span></div>
         {{/error}}
         {{{element}}}
         {{#default}}
-            <div class="form-defaultinfo {{#forceltr}}text-ltr{{/forceltr}}">{{{default}}}</div>
+            <div class="form-defaultinfo text-muted {{#forceltr}}text-ltr{{/forceltr}}">{{{default}}}</div>
         {{/default}}
+        <div class="form-description mt-3">{{{description}}}</div>
+        {{#dependenton}}<div class="form-dependenton mb-4 text-muted">{{{.}}}</div>{{/dependenton}}
     </div>
-    <div class="form-description">{{{description}}}</div>
 </div>
index eb8c487..3de5aac 100644 (file)
         "haspreviewconfig": false
     }
 }}
+{{!
+    Setting configcolourpicker.
+}}
 <div class="form-colourpicker defaultsnext">
     <div class="admin_colourpicker clearfix">
         {{#icon}}
             {{>core/pix_icon}}
         {{/icon}}
     </div>
-    <input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="text-ltr">
+    <input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="form-control text-ltr">
     {{#haspreviewconfig}}
         <input type="button" id="{{id}}_preview" value={{#quote}}{{#str}}preview{{/str}}{{/quote}} class="admin_colourpicker_preview">
     {{/haspreviewconfig}}
index 3bad98c..d2faa4a 100644 (file)
         "options": [ { "name": "Minutes", "value": "mins", "selected": true } ]
     }
 }}
+{{!
+    Setting configduration.
+}}
 <div class="form-duration defaultsnext">
-    <input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="text-ltr">
-    <label class="accesshide" for="{{id}}u">{{#str}}durationunits, admin{{/str}}</label>
-    <select id="{{id}}u" name="{{name}}[u]">
-        {{#options}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
-        {{/options}}
-    </select>
+    <div class="form-inline">
+        <input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr">
+        <label class="sr-only" for="{{id}}u">{{#str}}durationunits, admin{{/str}}</label>
+        <select id="{{id}}u" name="{{name}}[u]" class="form-control">
+            {{#options}}
+                <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
+            {{/options}}
+        </select>
+    </div>
 </div>
 
index f249fe6..1f0b5d5 100644 (file)
         "valid": false
     }
 }}
+{{!
+    Setting configfile.
+}}
 <div class="form-file defaultsnext">
-    <input type="text" name="{{name}}" id="{{id}}" size="{{size}}" value="{{value}}" class="text-ltr" {{#readonly}}readonly{{/readonly}}>
-    {{#showvalidity}}
-        {{#valid}}
-            <span class="pathok">&#x2714;</span>
-        {{/valid}}
-        {{^valid}}
-            <span class="patherror">&#x2718;</span>
-        {{/valid}}
-    {{/showvalidity}}
+    <div class="form-inline">
+        <input type="text" name="{{name}}" id="{{id}}" size="{{size}}" value="{{value}}" class="form-control text-ltr" {{#readonly}}readonly{{/readonly}}>
+        {{#showvalidity}}
+            {{#valid}}
+                <span class="text-success">&#x2714;</span>
+            {{/valid}}
+            {{^valid}}
+                <span class="text-danger">&#x2718;</span>
+            {{/valid}}
+        {{/showvalidity}}
+    </div>
 </div>
 
index 7465a7b..49eb55c 100644 (file)
                      { "name": "Option 2", "value": "V", "selected": true } ]
     }
 }}
+{{!
+    Setting configmultiselect.
+}}
 <div class="form-select">
     <input type="hidden" name="{{name}}[xxxxx]" value="1">
-    <select id="{{id}}" name="{{name}}[]" size="{{size}}" multiple>
+    <select id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
         {{#options}}
             <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
         {{/options}}
index 9fa61c5..20d66e1 100644 (file)
         ]
     }
 }}
+{{!
+    Setting configmultiselect with optgroup support.
+}}
 <div class="form-select">
     <input type="hidden" name="{{name}}[xxxxx]" value="1">
-    <select id="{{id}}" name="{{name}}[]" size="{{size}}" multiple>
-        {{#options}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
-        {{/options}}
-        {{#optgroups}}
+    <select id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
+    {{#options}}
+        <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
+    {{/options}}
+    {{#optgroups}}
             <optgroup label="{{label}}">
                 {{#options}}
                     <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
index a90c260..9b6c6e1 100644 (file)
         ]
     }
 }}
+{{!
+    Setting configselect.
+}}
 <div class="form-select defaultsnext">
-    <select id="{{id}}" name="{{name}}">
+    <select id="{{id}}" name="{{name}}" class="custom-select">
         {{#options}}
             <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
         {{/options}}
index ea5da12..95f818b 100644 (file)
         ]
     }
 }}
+{{!
+    Setting configselect with optgroup support.
+}}
 <div class="form-select defaultsnext">
-    <select id="{{id}}" name="{{name}}">
+    <select id="{{id}}" name="{{name}}" class="custom-select">
         {{#options}}
             <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
         {{/options}}
@@ -66,3 +69,4 @@
     </select>
 </div>
 
+
index 236228a..a31f73a 100644 (file)
@@ -37,6 +37,9 @@
         "attributes": [ { "name": "readonly", "value": "readonly" } ]
     }
 }}
+{{!
+    Setting configtext.
+}}
 <div class="form-text defaultsnext">
-    <input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="{{#forceltr}}text-ltr{{/forceltr}}"{{#attributes}} {{name}}="{{value}}"{{/attributes}}>
+    <input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">
 </div>
index ec6ded3..002b0cd 100644 (file)
@@ -36,6 +36,9 @@
         "id": "test0"
     }
 }}
+{{!
+    Setting configtextarea.
+}}
 <div class="form-textarea">
-    <textarea rows="{{rows}}" cols="{{cols}}" id="{{id}}" name="{{name}}" spellcheck="true" class="{{#forceltr}}text-ltr{{/forceltr}}">{{value}}</textarea>
+    <textarea rows="{{rows}}" cols="{{cols}}" id="{{id}}" name="{{name}}" spellcheck="true" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">{{value}}</textarea>
 </div>
index b86b691..90d37b3 100644 (file)
         ]
     }
 }}
-<div class="form-time defaultsnext text-ltr">
-    <label class="accesshide" for="{{id}}h">{{#str}}hours{{/str}}</label>
-    <select id="{{id}}h" name="{{name}}[h]">
-        {{#hours}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
-        {{/hours}}
-    </select>:
-    <label class="accesshide" for="{{id}}m">{{#str}}minutes{{/str}}</label>
-    <select id="{{id}}m" name="{{name}}[m]">
-        {{#minutes}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
-        {{/minutes}}
-    </select>
+{{!
+    Setting configtime.
+}}
+<div class="form-time defaultsnext">
+    <div class="form-inline text-ltr">
+        <label class="sr-only" for="{{id}}h">{{#str}}hours{{/str}}</label>
+        <select id="{{id}}h" name="{{name}}[h]" class="custom-select">
+            {{#hours}}
+                <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
+            {{/hours}}
+        </select>:
+        <label class="sr-only" for="{{id}}m">{{#str}}minutes{{/str}}</label>
+        <select id="{{id}}m" name="{{name}}[m]" class="custom-select">
+            {{#minutes}}
+                <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
+            {{/minutes}}
+        </select>
+    </div>
 </div>
 
index 2fe18cc..ef89725 100644 (file)
         ]
     }
 }}
+{{!
+    Setting courselist_frontpage.
+}}
 <div class="form-group">
     {{#selects}}
-        <select id="{{id}}{{key}}" name="{{name}}[]" class="form-select">
+        <select id="{{id}}{{key}}" name="{{name}}[]" class="custom-select">
             {{#options}}
                 <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
             {{/options}}
index c6d0e57..09bda33 100644 (file)
 {{!
     Setting description.
 }}
-<div class="form-item form-horizontal clearfix">
-    <div class="form-label">
+<div class="form-item row">
+    <div class="form-label col-sm-3 text-sm-right">
         <label>
             {{{title}}}
         </label>
-        <span class="form-shortname ">{{{name}}}</span>
     </div>
-    <div class="controls felement fstatic">{{{description}}}</div>
-</div>
\ No newline at end of file
+    <div class="form-setting col-sm-9">
+        <div class="form-description">{{{description}}}</div>
+    </div>
+</div>
index cc88862..97f97f2 100644 (file)
         ]
     }
 }}
-<table class="generaltable">
+{{!
+    Setting devicedetectregex.
+}}
+<table class="table table-striped">
     <thead>
         <tr>
             <th>{{#str}}devicedetectregexexpression, admin{{/str}}</th>
         {{#expressions}}
             <tr>
                 <td class="c{{index}}">
-                    <input type="text" name="{{name}}[expression{{index}}]" class="form-text text-ltr" value="{{expression}}">
+                    <input type="text" name="{{name}}[expression{{index}}]" class="form-control" value="{{expression}}">
                 </td>
                 <td class="c{{index}}">
-                    <input type="text" name="{{name}}[value{{index}}]" class="form-text text-ltr" value="{{value}}">
+                    <input type="text" name="{{name}}[value{{index}}]" class="form-control" value="{{value}}">
                 </td>
             </tr>
         {{/expressions}}
index 4c36174..8a245dd 100644 (file)
@@ -32,6 +32,9 @@
         ]
     }
 }}
+{{!
+    Setting emoticons.
+}}
 <div class="form-group">
     <table id="emoticonsetting" class="admintable generaltable">
         <thead>
@@ -48,7 +51,7 @@
                 <tr>
                     {{#fields}}
                         <td class="c{{index}}">
-                            <input type="text" name="{{name}}[{{field}}]" class="form-text text-ltr" value="{{value}}">
+                            <input type="text" name="{{name}}[{{field}}]" class="form-text form-control text-ltr" value="{{value}}">
                         </td>
                     {{/fields}}
                     <td>
index d64d75f..9e71c27 100644 (file)
         "advanced": true
     }
 }}
+{{!
+    Setting configselect.
+}}
 <div class="form-group">
-    <select id="{{id}}" name="{{name}}[value]" class="form-select">
+    <select id="{{id}}" name="{{name}}[value]" class="form-select custom-select">
         {{#options}}
             <option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
         {{/options}}
index 0097305..0067f8e 100644 (file)
         "showsave": true
     }
 }}
+{{!
+    Settings.
+}}
 <form action="{{actionurl}}" method="post" id="adminsettings">
-    <div class="settingsform clearfix">
+    <div class="settingsform">
         {{#params}}
             <input type="hidden" name="{{name}}" value="{{value}}">
             <input type="hidden" name="action" value="save-settings">
         {{/title}}
         {{{settings}}}
         {{#showsave}}
-            <div class="form-buttons">
-                <input type="submit" class="form-submit" value={{#quote}}{{#str}}savechanges, admin{{/str}}{{/quote}}>
+            <div class="row">
+                <div class="offset-sm-3 col-sm-3">
+                    <button type="submit" class="btn btn-primary">{{#str}}savechanges, admin{{/str}}</button>
+                </div>
             </div>
         {{/showsave}}
     </div>
index df82b0f..6653154 100644 (file)
                 </fieldset>
             {{/results}}
             {{#showsave}}
-                <div class="form-buttons">
-                    <input type="submit" class="form-submit" value={{#quote}}{{#str}}savechanges, admin{{/str}}{{/quote}}>
+                <div class="row">
+                    <div class="offset-sm-3 col-sm-3">
+                        <button type="submit" class="btn btn-primary">{{#str}}savechanges, admin{{/str}}</button>
+                    </div>
                 </div>
             {{/showsave}}
         {{/hasresults}}
index 73ce572..b2fd070 100644 (file)
@@ -55,16 +55,12 @@ class behat_admin extends behat_base {
 
         foreach ($data as $label => $value) {
 
-            // We expect admin block to be visible, otherwise go to homepage.
-            if (!$this->getSession()->getPage()->find('css', '.block_settings')) {
-                $this->getSession()->visit($this->locate_path('/'));
-                $this->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
-            }
+            $this->execute('behat_navigation::i_select_from_flat_navigation_drawer', [get_string('administrationsite')]);
 
             // Search by label.
-            $searchbox = $this->find_field(get_string('searchinsettings', 'admin'));
+            $searchbox = $this->find_field(get_string('query', 'admin'));
             $searchbox->setValue($label);
-            $submitsearch = $this->find('css', 'form.adminsearchform input[type=submit]');
+            $submitsearch = $this->find('css', 'form input[type=submit][name=search]');
             $submitsearch->press();
 
             $this->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
@@ -78,21 +74,24 @@ class behat_admin extends behat_base {
 
             // Single element settings.
             try {
-                $fieldxpath = "//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]" .
-                    "[@id=//label[contains(normalize-space(.), $label)]/@for or " .
-                    "@id=//span[contains(normalize-space(.), $label)]/preceding-sibling::label[1]/@for]";
+                $fieldxpath = "//*[self::input | self::textarea | self::select]" .
+                        "[not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]" .
+                        "[@id=//label[contains(normalize-space(.), $label)]/@for or " .
+                        "@id=//span[contains(normalize-space(.), $label)]/preceding-sibling::label[1]/@for]";
                 $fieldnode = $this->find('xpath', $fieldxpath, $exception);
 
-                $formfieldtypenode = $this->find('xpath', $fieldxpath . "/ancestor::div[@class='form-setting']" .
-                    "/child::div[contains(concat(' ', @class, ' '),  ' form-')]/child::*/parent::div");
+                $formfieldtypenode = $this->find('xpath', $fieldxpath .
+                        "/ancestor::div[contains(concat(' ', @class, ' '), ' form-setting ')]" .
+                        "/child::div[contains(concat(' ', @class, ' '),  ' form-')]/child::*/parent::div");
 
             } catch (ElementNotFoundException $e) {
 
                 // Multi element settings, interacting only the first one.
-                $fieldxpath = "//*[label[normalize-space(.)= $label]|span[normalize-space(.)= $label]]/" .
-                    "ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-item ')]" .
-                    "/descendant::div[@class='form-group']/descendant::*[self::input | self::textarea | self::select]" .
-                    "[not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]";
+                $fieldxpath = "//*[label[contains(., $label)]|span[contains(., $label)]]" .
+                        "/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-item ')]" .
+                        "/descendant::div[contains(concat(' ', @class, ' '), ' form-group ')]" .
+                        "/descendant::*[self::input | self::textarea | self::select]" .
+                        "[not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]";
                 $fieldnode = $this->find('xpath', $fieldxpath);
 
                 // It is the same one that contains the type.
@@ -101,6 +100,7 @@ class behat_admin extends behat_base {
 
             // Getting the class which contains the field type.
             $classes = explode(' ', $formfieldtypenode->getAttribute('class'));
+            $type = false;
             foreach ($classes as $class) {
                 if (substr($class, 0, 5) == 'form-') {
                     $type = substr($class, 5);
index a5bda09..0bb3902 100644 (file)
@@ -153,6 +153,12 @@ class invalid_analysables implements \renderable, \templatable {
             $data->analysables[] = $obj;
         }
 
+        if (empty($data->analysables)) {
+            $data->noanalysables = [
+                'message' => get_string('noinvalidanalysables', 'tool_analytics'),
+                'announce' => true,
+            ];
+        }
         return $data;
     }
 }
index cbd0a60..83e2755 100644 (file)
@@ -247,7 +247,7 @@ class models_list implements \renderable, \templatable {
             }
 
             // Clear model.
-            if (!empty($predictioncontexts)) {
+            if (!empty($predictioncontexts) || $model->is_trained()) {
                 $actionid = 'clear-' . $model->get_id();
                 $PAGE->requires->js_call_amd('tool_analytics/model', 'confirmAction', [$actionid, 'clear']);
                 $urlparams['action'] = 'clear';
index 8df2cc3..1c3bba2 100644 (file)
@@ -75,6 +75,7 @@ $string['nextpage'] = 'Next page';
 $string['nodatatoevaluate'] = 'There is no data to evaluate the model';
 $string['nodatatopredict'] = 'No new elements to get predictions for';
 $string['nodatatotrain'] = 'There is no new data that can be used for training';
+$string['noinvalidanalysables'] = 'This site does not contain any invalid analysable element.';
 $string['notdefined'] = 'Not yet defined';
 $string['pluginname'] = 'Analytic models';
 $string['predictionresults'] = 'Prediction results';
index c97dd6b..2b3ddd6 100644 (file)
 <div class="box">
     <h3>{{#str}}modelinvalidanalysables, tool_analytics, {{modelname}}{{/str}}</h3>
     <div>{{#str}}invalidanalysablesinfo, tool_analytics{{/str}}</div>
-    <div class="m-t-2 m-b-1">
-        <span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
-        <span>{{#next}}{{> core/single_button}}{{/next}}</span>
-    </div>
-    <table class="generaltable fullwidth">
-        <caption class="accesshide">{{#str}}invalidanalysablestable, tool_analytics{{/str}}</caption>
-        <thead>
-            <tr>
-                <th scope="col">{{#str}}name{{/str}}</th>
-                <th scope="col">{{#str}}invalidtraining, tool_analytics{{/str}}</th>
-                <th scope="col">{{#str}}invalidprediction, tool_analytics{{/str}}</th>
-            </tr>
-        </thead>
-        <tbody>
-        {{#analysables}}
-            <tr>
-                <td>{{{url}}}</td>
-                <td>{{validtraining}}</td>
-                <td>{{validprediction}}</td>
-            </tr>
-        {{/analysables}}
-        </tbody>
-    </table>
-    <div class="m-t-1 m-b-2">
-        <span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
-        <span>{{#next}}{{> core/single_button}}{{/next}}</span>
-    </div>
+    {{#noanalysables}}
+        <div class="m-t-2 m-b-1">
+            {{> core/notification_info}}
+        </div>
+    {{/noanalysables}}
+    {{^noanalysables}}
+        <div class="m-t-2 m-b-1">
+            <span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
+            <span>{{#next}}{{> core/single_button}}{{/next}}</span>
+        </div>
+        <table class="generaltable fullwidth">
+            <caption class="accesshide">{{#str}}invalidanalysablestable, tool_analytics{{/str}}</caption>
+            <thead>
+                <tr>
+                    <th scope="col">{{#str}}name{{/str}}</th>
+                    <th scope="col">{{#str}}invalidtraining, tool_analytics{{/str}}</th>
+                    <th scope="col">{{#str}}invalidprediction, tool_analytics{{/str}}</th>
+                </tr>
+            </thead>
+            <tbody>
+            {{#analysables}}
+                <tr>
+                    <td>{{{url}}}</td>
+                    <td>{{validtraining}}</td>
+                    <td>{{validprediction}}</td>
+                </tr>
+            {{/analysables}}
+            </tbody>
+        </table>
+        <div class="m-t-1 m-b-2">
+            <span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
+            <span>{{#next}}{{> core/single_button}}{{/next}}</span>
+        </div>
+    {{/noanalysables}}
 </div>
index e88125b..83a19af 100644 (file)
@@ -109,6 +109,17 @@ require_once(__DIR__ . '/../../../../lib/behat/lib.php');
 require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php');
 require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php');
 
+// Remove error handling overrides done in config.php. This is consistent with admin/tool/behat/cli/util_single_run.php.
+$CFG->debug = (E_ALL | E_STRICT);
+$CFG->debugdisplay = 1;
+error_reporting($CFG->debug);
+ini_set('display_errors', '1');
+ini_set('log_errors', '1');
+
+// Import the necessary libraries.
+require_once($CFG->libdir . '/setuplib.php');
+require_once($CFG->libdir . '/behat/classes/util.php');
+
 // For drop option check if parallel site.
 if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) {
     $options['parallel'] = behat_config_manager::get_behat_run_config_value('parallel');
index 2e98656..967fde3 100644 (file)
@@ -218,7 +218,7 @@ if ($options['install']) {
     // Run behat command to get steps in feature files.
     $featurestepscmd = behat_command::get_behat_command(true);
     $featurestepscmd .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
-    $featurestepscmd .= ' --dry-run --format=moodle_step_count';
+    $featurestepscmd .= ' --dry-run --format=moodle_stepcount';
     $processes = cli_execute_parallel(array($featurestepscmd), __DIR__ . "/../../../../");
     $status = print_update_step_output(array_pop($processes), $behatstepfile);
 
index f2cd279..88e3365 100644 (file)
@@ -24,6 +24,7 @@
 
 $string['aim'] = 'This administration tool helps developers and test writers to create .feature files describing Moodle\'s functionalities and run them automatically. Step definitions available for use in .feature files are listed below.';
 $string['allavailablesteps'] = 'All available step definitions';
+$string['errorapproot'] = '$CFG->behat_ionic_dirroot is not pointing to a valid Moodle Mobile developer install.';
 $string['errorbehatcommand'] = 'Error running behat CLI command. Try running "{$a} --help" manually from CLI to find out more about the problem.';
 $string['errorcomposer'] = 'Composer dependencies are not installed.';
 $string['errordataroot'] = '$CFG->behat_dataroot is not set or is invalid.';
index 85f52de..8e4f776 100644 (file)
@@ -28,6 +28,6 @@ Feature: Forms manipulation
     When I expand all fieldsets
     Then I should see "Close the quiz"
     And I should see "Group mode"
-    And I should see "Grouping"
+    And I should see "ID number"
     And I should not see "Show more..." in the "region-main" "region"
     And I should see "Show less..."
index 01c0396..c8819d6 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
+require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php');
 
 /**
  * Test context 1
index 0dbdbeb..9b423ae 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
+require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php');
 
 /**
  * Test context 2
index ff164cd..f0d851c 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
+require_once(__DIR__ . '/../../../../../../../lib/behat/behat_base.php');
 
 /**
  * Default Theme test context 1
index 710da0a..5db9807 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../behat_test_context_1.php');
+require_once(__DIR__ . '/../../core/behat_test_context_1.php');
 
 /**
  * Theme test context 1
@@ -33,6 +33,6 @@ require_once(__DIR__ . '/../behat_test_context_1.php');
  * @copyright  2016 Rajesh Taneja <rajesh@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class behat_theme_nofeatures_behat_test_context_1 extends behat_test_context_1 {
+class behat_theme_nofeatures_behat_test_context_2 extends behat_test_context_2 {
 
 }
\ No newline at end of file
index 87fe40c..2d8d121 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
+require_once(__DIR__ . '/../../../../../../../lib/behat/behat_base.php');
 
 /**
  * Theme test context 2
@@ -33,6 +33,6 @@ require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
  * @copyright  2016 Rajesh Taneja <rajesh@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class behat_theme_nofeatures_test_context_2 extends behat_base {
+class behat_theme_nofeatures_test_context_1 extends behat_base {
 
 }
\ No newline at end of file
index 3941071..1111532 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../behat_test_context_1.php');
+require_once(__DIR__ . '/../../core/behat_test_context_1.php');
 
 /**
  * Theme test context 1
index 23eedff..2265320 100644 (file)
@@ -24,7 +24,7 @@
 
 // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
 
-require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
+require_once(__DIR__ . '/../../../../../../../lib/behat/behat_base.php');
 
 /**
  * Theme test context 2
index 2d10776..98ccd03 100644 (file)
@@ -108,7 +108,6 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
             array('nofeatures', __DIR__.'/fixtures/theme/nofeatures'),
             array('defaulttheme', __DIR__.'/fixtures/theme/defaulttheme'),
         );
-
         // List of themes is const for test.
         if ($notheme) {
             $themelist = array('defaulttheme');
@@ -116,6 +115,13 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
             $themelist = array('withfeatures', 'nofeatures', 'defaulttheme');
         }
 
+        $thememap = [];
+        foreach ($themelist as $themename) {
+            $mock = $this->getMockBuilder('theme_config');
+            $mock->disableOriginalConstructor();
+            $thememap[] = [$themename, $mock->getMock()];
+        }
+
         $behatconfigutil->expects($this->any())
             ->method('get_list_of_themes')
             ->will($this->returnValue($themelist));
@@ -125,6 +131,11 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
             ->method('get_theme_test_directory')
             ->will($this->returnValueMap($map));
 
+        // Theme directory for testing.
+        $behatconfigutil->expects($this->any())
+                ->method('get_theme_config')
+                ->will($this->returnValueMap($thememap));
+
         $behatconfigutil->expects($this->any())
             ->method('get_default_theme')
             ->will($this->returnValue('defaulttheme'));
@@ -138,7 +149,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
     public function test_get_config_file_contents_with_single_run() {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
-        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme'));
+        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
@@ -177,7 +188,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
     public function test_get_config_file_contents_with_single_run_no_theme() {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
-        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme'));
+        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
@@ -231,7 +242,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
     public function test_get_config_file_contents_with_parallel_run() {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
-        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme'));
+        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
@@ -334,7 +345,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
     public function test_get_config_file_contents_with_parallel_run_optimize_tags() {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
-        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme'));
+        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
@@ -479,7 +490,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
         $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_blacklisted_tests_for_theme',
-            'get_default_theme'));
+            'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
@@ -543,7 +554,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
         $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_blacklisted_tests_for_theme',
-            'get_default_theme'));
+            'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
@@ -621,7 +632,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
     public function test_core_features_to_include_in_specified_theme() {
 
         $mockbuilder = $this->getMockBuilder('behat_config_util');
-        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme'));
+        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
 
         $behatconfigutil = $mockbuilder->getMock();
 
index 525aa94..36b1184 100644 (file)
@@ -1,5 +1,8 @@
 This files describes API changes in the tool_behat code.
 
+=== 3.7 ===
+* Behat will now look for behat step definitions in the current
+  theme and any parents the theme may have.
 === 2.7 ===
 * Constants behat_base::cap_allow, behat_base::cap_prevent and
   behat_base::cap_prohibit have been removed in favour of the
index f2c60aa..ed94462 100644 (file)
@@ -65,12 +65,12 @@ class tool_filetypes_form extends moodleform {
         $mform->addElement('text', 'description',  get_string('description', 'tool_filetypes'));
         $mform->setType('description', PARAM_TEXT);
         $mform->addHelpButton('description', 'description', 'tool_filetypes');
-        $mform->disabledIf('description', 'descriptiontype', 'ne', 'custom');
+        $mform->hideIf('description', 'descriptiontype', 'ne', 'custom');
 
         $mform->addElement('text', 'corestring',  get_string('corestring', 'tool_filetypes'));
         $mform->setType('corestring', PARAM_ALPHANUMEXT);
         $mform->addHelpButton('corestring', 'corestring', 'tool_filetypes');
-        $mform->disabledIf('corestring', 'descriptiontype', 'ne', 'lang');
+        $mform->hideIf('corestring', 'descriptiontype', 'ne', 'lang');
 
         $mform->addElement('checkbox', 'defaulticon',  get_string('defaulticon', 'tool_filetypes'));
         $mform->addHelpButton('defaulticon', 'defaulticon', 'tool_filetypes');
diff --git a/admin/tool/langimport/classes/locale.php b/admin/tool/langimport/classes/locale.php
new file mode 100644 (file)
index 0000000..69c43b6
--- /dev/null
@@ -0,0 +1,84 @@
+<?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/>.
+
+/**
+ * Helper class for the language import tool.
+ *
+ * @package    tool_langimport
+ * @copyright  2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_langimport;
+
+use coding_exception;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Helper class for the language import tool.
+ *
+ * @copyright  2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class locale {
+    /**
+     * Checks availability of locale on current operating system.
+     *
+     * @param string $langpackcode E.g.: en, es, fr, de.
+     * @return bool TRUE if the locale is available on OS.
+     * @throws coding_exception when $langpackcode parameter is a non-empty string.
+     */
+    public function check_locale_availability(string $langpackcode) : bool {
+        global $CFG;
+
+        if (empty($langpackcode)) {
+            throw new coding_exception('Invalid language pack code in \\'.__METHOD__.'() call, only non-empty string is allowed');
+        }
+
+        // Fetch the correct locale based on ostype.
+        if ($CFG->ostype === 'WINDOWS') {
+            $stringtofetch = 'localewin';
+        } else {
+            $stringtofetch = 'locale';
+        }
+
+        // Store current locale.
+        $currentlocale = $this->set_locale(LC_ALL, 0);
+
+        $locale = get_string_manager()->get_string($stringtofetch, 'langconfig', $a = null, $langpackcode);
+
+        // Try to set new locale.
+        $return = $this->set_locale(LC_ALL, $locale);
+
+        // Restore current locale.
+        $this->set_locale(LC_ALL, $currentlocale);
+
+        // If $return is not equal to false, it means that setlocale() succeed to change locale.
+        return $return !== false;
+    }
+
+    /**
+     * Wrap for the native PHP function setlocale().
+     *
+     * @param int $category Specifying the category of the functions affected by the locale setting.
+     * @param string $locale E.g.: en_AU.utf8, en_GB.utf8, es_ES.utf8, fr_FR.utf8, de_DE.utf8.
+     * @return string|false Returns the new current locale, or FALSE on error.
+     */
+    protected function set_locale(int $category = LC_ALL, string $locale = '0') {
+        return setlocale($category, $locale);
+    }
+}
index 92a09da..1180abc 100644 (file)
@@ -109,9 +109,16 @@ echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('langimport', 'tool_langimport'));
 
 $installedlangs = get_string_manager()->get_list_of_translations(true);
+$locale = new \tool_langimport\locale();
 
+$missinglocales = '';
 $missingparents = array();
-foreach ($installedlangs as $installedlang => $unused) {
+foreach ($installedlangs as $installedlang => $langpackname) {
+    // Check locale availability.
+    if (!$locale->check_locale_availability($installedlang)) {
+        $missinglocales .= '<li>'.$langpackname.'</li>';
+    }
+
     $parent = get_parent_language($installedlang);
     if (empty($parent)) {
         continue;
@@ -121,6 +128,14 @@ foreach ($installedlangs as $installedlang => $unused) {
     }
 }
 
+if (!empty($missinglocales)) {
+    // There is at least one missing locale.
+    $a = new stdClass();
+    $a->globallocale = moodle_getlocale();
+    $a->missinglocales = $missinglocales;
+    $controller->errors[] = get_string('langunsupported', 'tool_langimport', $a);
+}
+
 if ($availablelangs = $controller->availablelangs) {
     $remote = true;
 } else {
index faeb02c..27739ed 100644 (file)
@@ -37,6 +37,7 @@ $string['langpackupdateskipped'] = 'Update of \'{$a}\' language pack skipped';
 $string['langpackuptodate'] = 'Language pack \'{$a}\' is up-to-date';
 $string['langpackupdated'] = 'Language pack \'{$a}\' was successfully updated';
 $string['langpackupdatedevent'] = 'Language pack updated';
+$string['langunsupported'] = '<p>Your server does not seem to fully support the following languages:</p><ul>{$a->missinglocales}</ul><p>Instead, the global locale ({$a->globallocale}) will be used to format certain strings such as dates or numbers.</p>';
 $string['langupdatecomplete'] = 'Language pack update completed';
 $string['missingcfglangotherroot'] = 'Missing configuration value $CFG->langotherroot';
 $string['missinglangparent'] = 'Missing parent language <em>{$a->parent}</em> of <em>{$a->lang}</em>.';
diff --git a/admin/tool/langimport/tests/locale_test.php b/admin/tool/langimport/tests/locale_test.php
new file mode 100644 (file)
index 0000000..4d1ffef
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Tests for \tool_langimport\locale class.
+ *
+ * @package    tool_langimport
+ * @copyright  2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Tests for \tool_langimport\locale class.
+ *
+ * @copyright  2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class locale_testcase extends \advanced_testcase {
+    /**
+     * Test that \tool_langimport\locale::check_locale_availability() works as expected.
+     *
+     * @return void
+     */
+    public function test_check_locale_availability() {
+        // Create a mock of set_locale() method to simulate :
+        // - first setlocale() call which backup current locale
+        // - second setlocale() call which try to set new 'es' locale
+        // - third setlocale() call which restore locale.
+        $mock = $this->getMockBuilder(\tool_langimport\locale::class)
+            ->setMethods(['set_locale'])
+            ->getMock();
+        $mock->method('set_locale')->will($this->onConsecutiveCalls('en', 'es', 'en'));
+
+        // Test what happen when locale is available on system.
+        $result = $mock->check_locale_availability('en');
+        $this->assertTrue($result);
+
+        // Create a mock of set_locale() method to simulate :
+        // - first setlocale() call which backup current locale
+        // - second setlocale() call which fail to set new locale
+        // - third setlocale() call which restore locale.
+        $mock = $this->getMockBuilder(\tool_langimport\locale::class)
+            ->setMethods(['set_locale'])
+            ->getMock();
+        $mock->method('set_locale')->will($this->onConsecutiveCalls('en', false, 'en'));
+
+        // Test what happen when locale is not available on system.
+        $result = $mock->check_locale_availability('en');
+        $this->assertFalse($result);
+
+        // Test an invalid parameter.
+        $locale = new \tool_langimport\locale();
+        $this->expectException(coding_exception::class);
+        $locale->check_locale_availability('');
+    }
+}
index 77cf893..f798e7d 100644 (file)
@@ -420,6 +420,9 @@ class external extends external_api {
                     ))
                 ),
                 'comppath' => competency_path_exporter::get_read_structure(),
+                'plans' => new external_multiple_structure(
+                    plan_exporter::get_read_structure()
+                ),
             ))),
             'manageurl' => new external_value(PARAM_LOCALURL, 'Url to the manage competencies page.'),
         ));
index d1b7b7f..78ea24a 100644 (file)
@@ -26,11 +26,13 @@ defined('MOODLE_INTERNAL') || die();
 
 use core_competency\api;
 use core_competency\user_competency;
+use core_competency\external\plan_exporter;
 use core_course\external\course_module_summary_exporter;
 use core_course\external\course_summary_exporter;
 use context_course;
 use renderer_base;
 use stdClass;
+use moodle_url;
 
 /**
  * Class for exporting user competency data with additional related data in a plan.
@@ -62,7 +64,14 @@ class user_competency_summary_in_course_exporter extends \core\external\exporter
             'coursemodules' => array(
                 'type' => course_module_summary_exporter::read_properties_definition(),
                 'multiple' => true
-            )
+            ),
+            'plans' => array(
+                'type' => plan_exporter::read_properties_definition(),
+                'multiple' => true
+            ),
+            'pluginbaseurl' => [
+                'type' => PARAM_URL
+            ],
         );
     }
 
@@ -95,6 +104,16 @@ class user_competency_summary_in_course_exporter extends \core\external\exporter
         }
         $result->coursemodules = $exportedmodules;
 
+        // User learning plans.
+        $plans = api::list_plans_with_competency($this->related['user']->id, $this->related['competency']);
+        $exportedplans = array();
+        foreach ($plans as $plan) {
+            $planexporter = new plan_exporter($plan, array('template' => $plan->get_template()));
+            $exportedplans[] = $planexporter->export($output);
+        }
+        $result->plans = $exportedplans;
+        $result->pluginbaseurl = (new moodle_url('/admin/tool/lp'))->out(true);
+
         return (array) $result;
     }
 }
index eaf7d34..218d8a5 100644 (file)
@@ -41,6 +41,7 @@ use core_competency\external\course_competency_exporter;
 use core_competency\external\course_competency_settings_exporter;
 use core_competency\external\user_competency_course_exporter;
 use core_competency\external\user_competency_exporter;
+use core_competency\external\plan_exporter;
 use tool_lp\external\competency_path_exporter;
 use tool_lp\external\course_competency_statistics_exporter;
 use core_course\external\course_module_summary_exporter;
@@ -113,6 +114,7 @@ class course_competencies_page implements renderable, templatable {
         $data->courseid = $this->courseid;
         $data->pagecontextid = $this->context->id;
         $data->competencies = array();
+        $data->pluginbaseurl = (new moodle_url('/admin/tool/lp'))->out(true);
 
         $gradable = is_enrolled($this->context, $USER, 'moodle/competency:coursecompetencygradable');
         if ($gradable) {
@@ -154,12 +156,21 @@ class course_competencies_page implements renderable, templatable {
                 'context' => $context
             ]);
 
+            // User learning plans.
+            $plans = api::list_plans_with_competency($USER->id, $competency);
+            $exportedplans = array();
+            foreach ($plans as $plan) {
+                $planexporter = new plan_exporter($plan, array('template' => $plan->get_template()));
+                $exportedplans[] = $planexporter->export($output);
+            }
+
             $onerow = array(
                 'competency' => $compexporter->export($output),
                 'coursecompetency' => $ccexporter->export($output),
                 'ruleoutcomeoptions' => $ccoutcomeoptions,
                 'coursemodules' => $exportedmodules,
-                'comppath' => $pathexporter->export($output)
+                'comppath' => $pathexporter->export($output),
+                'plans' => $exportedplans
             );
             if ($gradable) {
                 $foundusercompetencycourse = false;
index eaa0f43..6d89b20 100644 (file)
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 }}
 {{!
+    @template tool_lp/course_competencies_page
+
     Course competencies template.
 
     For a full list of the context for this template see the course_competencies_page renderable.
+
+    This template includes ajax functionality, so it cannot be shown in the template library.
 }}
 <div data-region="coursecompetenciespage">
     <div data-region="actions" class="clearfix">
@@ -66,7 +70,7 @@
         <div class="clearfix"></div>
         {{/canmanagecoursecompetencies}}
         {{#competency}}
-            <a href="{{pluginbaseurl}}user_competency_in_course.php?courseid={{courseid}}&competencyid={{competency.id}}&userid={{gradableuserid}}"
+            <a href="{{pluginbaseurl}}/user_competency_in_course.php?courseid={{courseid}}&competencyid={{competency.id}}&userid={{gradableuserid}}"
                    id="competency-info-link-{{competency.id}}"
                    title="{{#str}}viewdetails, tool_lp{{/str}}">
                 <p><strong>{{{competency.shortname}}} <em>{{competency.idnumber}}</em></strong></p>
         {{/canmanagecoursecompetencies}}
         <div data-region="coursecompetencyactivities">
         <p>
-        <ul class="inline list-inline">
+        <strong>{{#str}}activities{{/str}}</strong>
+        <ul class="inline list-inline p-2">
         {{#coursemodules}}
             <li class="list-inline-item"><a href="{{url}}"><img src="{{iconurl}}"> {{name}} </a></li>
         {{/coursemodules}}
         {{^coursemodules}}
-            <li class="list-inline-item"><span class="alert">{{#str}}noactivities, tool_lp{{/str}}</span></li>
+            <li class="list-inline-item">{{#str}}noactivities, tool_lp{{/str}}</li>
         {{/coursemodules}}
         </ul>
         </p>
         </div>
+        <div data-region="learningplans">
+        <p>
+        <strong>{{#str}}userplans, core_competency{{/str}}</strong>
+        <ul class="inline list-inline p-2">
+        {{#plans}}
+            <li class="list-inline-item"><a href="{{pluginbaseurl}}/plan.php?id={{id}}">{{{name}}}</a></li>
+        {{/plans}}
+        {{^plans}}
+            <li class="list-inline-item">{{#str}}nouserplanswithcompetency, core_competency{{/str}}</li>
+        {{/plans}}
+        </ul>
+        </p>
+        </div>
     </td>
     </tr>
 {{/competencies}}
index 118f761..b7029db 100644 (file)
@@ -20,7 +20,6 @@
     Moodle progress bar template for tool_lp.
 
     The purpose of this template is to render a progress bar with a brief description.
-    Inherits core/columns-1to2.
 
     Classes required for JS:
     * none
     }
 
 }}
-<div class="row-fluid rtl-compatible">
-    <div class="span4">
-        <div class="progresstext">
-            {{$progresstext}}{{progresstextvalue}}{{/progresstext}}
-        </div>
-    </div>
-    <div class="span8">
-        <div class="progress">
-            <div class="bar" style="width: {{$percentage}}{{percentagevalue}}{{/percentage}}%;" role="progressbar" aria-valuenow="{{$percentage}}{{percentagevalue}}{{/percentage}}" aria-valuemin="0" aria-valuemax="100">
-                {{$percentlabel}}{{percentlabelvalue}}{{/percentlabel}}
-            </div>
-        </div>
-    </div>
+<div id="progress-{{uniqid}}">
+    {{$progresstext}}{{progresstextvalue}}{{/progresstext}}
 </div>
+<progress class="progress" aria-describedby="progress-{{uniqid}}"
+    value="{{$percentage}}{{percentagevalue}}{{/percentage}}" max="100"></progress>
index 22cf96d..ce80bbb 100644 (file)
         </dd>
         {{/user}}
         {{/displayuser}}
+        <dt>{{#str}}userplans, competency{{/str}}</dt>
+        <dd>
+        <p>
+        <ul class="inline list-inline">
+        {{#plans}}
+            <li class="list-inline-item"><a href="{{pluginbaseurl}}/plan.php?id={{id}}">{{{name}}}</a></li>
+        {{/plans}}
+        {{^plans}}
+            <li>{{#str}}nouserplanswithcompetency, competency{{/str}}</li>
+        {{/plans}}
+        </ul>
+        </p>
+        </dd>
         {{#usercompetencycourse}}
         <dt>{{#str}}proficient, tool_lp{{/str}}</dt>
         <dd>
index d2ca869..0fbbfd1 100644 (file)
@@ -130,3 +130,35 @@ Feature: Manage plearning plan
     When I click on "Delete" "button" in the "Confirm" "dialogue"
     And I wait until the page is ready
     Then I should not see "Science plan Year-4"
+
+  Scenario: See a learning plan from a course
+    Given the following lp "plans" exist:
+      | name | user | description |
+      | Science plan Year-manage | admin | science plan description |
+    And the following lp "frameworks" exist:
+      | shortname | idnumber |
+      | Framework 1 | sc-y-2 |
+    And the following lp "competencies" exist:
+      | shortname | framework |
+      | comp1 | sc-y-2 |
+      | comp2 | sc-y-2 |
+    And I follow "Learning plans"
+    And I should see "Science plan Year-manage"
+    And I follow "Science plan Year-manage"
+    And I should see "Add competency"
+    And I press "Add competency"
+    And "Competency picker" "dialogue" should be visible
+    And I select "comp1" of the competency tree
+    When I click on "Add" "button" in the "Competency picker" "dialogue"
+    Then "comp1" "table_row" should exist
+    And I create a course with:
+      | Course full name | New course fullname |
+      | Course short name | New course shortname |
+    And I follow "New course fullname"
+    And I follow "Competencies"
+    And I press "Add competencies to course"
+    And "Competency picker" "dialogue" should be visible
+    And I select "comp1" of the competency tree
+    And I click on "Add" "button" in the "Competency picker" "dialogue"
+    And I should see "Learning plans"
+    And I should see "Science plan Year-manage"
index 71cf2bb..bd49699 100644 (file)
@@ -356,7 +356,7 @@ class api {
         $mobileplugins = self::get_plugins_supporting_mobile();
         foreach ($mobileplugins as $plugin) {
             $displayname = core_plugin_manager::instance()->plugin_name($plugin['component']) . " - " . $plugin['addon'];
-            $remoteaddonslist['remoteAddOn_' . $plugin['component'] . '_' . $plugin['addon']] = $displayname;
+            $remoteaddonslist['sitePlugin_' . $plugin['component'] . '_' . $plugin['addon']] = $displayname;
 
         }
 
diff --git a/admin/tool/mobile/db/upgrade.php b/admin/tool/mobile/db/upgrade.php
new file mode 100644 (file)
index 0000000..73748aa
--- /dev/null
@@ -0,0 +1,46 @@
+<?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/>.
+
+/**
+ * Mobile app support.
+ *
+ * @package    tool_mobile
+ * @copyright  2019 The Open University
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot . '/lib/upgradelib.php');
+
+/**
+ * Upgrade the plugin.
+ *
+ * @param int $oldversion
+ * @return bool always true
+ */
+function xmldb_tool_mobile_upgrade($oldversion) {
+    global $CFG;
+
+    if ($oldversion < 2019021100) {
+        $disabledfeatures = get_config('tool_mobile', 'disabledfeatures');
+        $disabledfeatures = str_replace('remoteAddOn_', 'sitePlugin_', $disabledfeatures);
+        set_config('disabledfeatures', $disabledfeatures, 'tool_mobile');
+        upgrade_plugin_savepoint(true, 2019021100, 'tool', 'mobile');
+    }
+
+    return true;
+}
index 4584e2d..bc7dc20 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 defined('MOODLE_INTERNAL') || die();
-$plugin->version   = 2018120300; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->version   = 2019021100; // The current plugin version (Date: YYYYMMDDXX).
 $plugin->requires  = 2018112800; // Requires this Moodle version.
 $plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
 $plugin->dependencies = array(
index bfa0e8d..aaa36d9 100644 (file)
@@ -7,7 +7,7 @@ Feature: Clear scheduled task fail delay
   Background:
     Given the scheduled task "\core\task\send_new_user_passwords_task" has a fail delay of "60" seconds
     And I log in as "admin"
-    And I navigate to "Server > Scheduled tasks" in site administration
+    And I navigate to "Server > Tasks > Scheduled tasks" in site administration
 
   Scenario: Clear fail delay
     When I click on "Clear" "text" in the "Send new user passwords" "table_row"
index 1f0a9df..4da19e5 100644 (file)
@@ -6,7 +6,7 @@ Feature: Manage scheduled tasks
 
   Background:
     Given I log in as "admin"
-    And I navigate to "Server > Scheduled tasks" in site administration
+    And I navigate to "Server > Tasks > Scheduled tasks" in site administration
 
   Scenario: Disable scheduled task
     When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
index 868fe6a..38aa6be 100644 (file)
@@ -72,26 +72,26 @@ class tool_uploadcourse_base_form extends moodleform {
         );
         $mform->addElement('select', 'options[updatemode]', get_string('updatemode', 'tool_uploadcourse'), $choices);
         $mform->setDefault('options[updatemode]', tool_uploadcourse_processor::UPDATE_NOTHING);
-        $mform->disabledIf('options[updatemode]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
-        $mform->disabledIf('options[updatemode]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
+        $mform->hideIf('options[updatemode]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
+        $mform->hideIf('options[updatemode]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
         $mform->addHelpButton('options[updatemode]', 'updatemode', 'tool_uploadcourse');
 
         $mform->addElement('selectyesno', 'options[allowdeletes]', get_string('allowdeletes', 'tool_uploadcourse'));
         $mform->setDefault('options[allowdeletes]', 0);
-        $mform->disabledIf('options[allowdeletes]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
-        $mform->disabledIf('options[allowdeletes]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
+        $mform->hideIf('options[allowdeletes]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
+        $mform->hideIf('options[allowdeletes]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
         $mform->addHelpButton('options[allowdeletes]', 'allowdeletes', 'tool_uploadcourse');
 
         $mform->addElement('selectyesno', 'options[allowrenames]', get_string('allowrenames', 'tool_uploadcourse'));
         $mform->setDefault('options[allowrenames]', 0);
-        $mform->disabledIf('options[allowrenames]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
-        $mform->disabledIf('options[allowrenames]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
+        $mform->hideIf('options[allowrenames]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
+        $mform->hideIf('options[allowrenames]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
         $mform->addHelpButton('options[allowrenames]', 'allowrenames', 'tool_uploadcourse');
 
         $mform->addElement('selectyesno', 'options[allowresets]', get_string('allowresets', 'tool_uploadcourse'));
         $mform->setDefault('options[allowresets]', 0);
-        $mform->disabledIf('options[allowresets]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
-        $mform->disabledIf('options[allowresets]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
+        $mform->hideIf('options[allowresets]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
+        $mform->hideIf('options[allowresets]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
         $mform->addHelpButton('options[allowresets]', 'allowresets', 'tool_uploadcourse');
     }
 
index 89ee15d..58c39d4 100644 (file)
@@ -57,8 +57,8 @@ class tool_uploadcourse_step2_form extends tool_uploadcourse_base_form {
             'maxlength="100" size="20"');
         $mform->setType('options[shortnametemplate]', PARAM_RAW);
         $mform->addHelpButton('options[shortnametemplate]', 'shortnametemplate', 'tool_uploadcourse');
-        $mform->disabledIf('options[shortnametemplate]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE);
-        $mform->disabledIf('options[shortnametemplate]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_UPDATE_ONLY);
+        $mform->hideIf('options[shortnametemplate]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE);
+        $mform->hideIf('options[shortnametemplate]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_UPDATE_ONLY);
 
         // Restore file is not in the array options on purpose, because formslib can't handle it!
         $contextid = $this->_customdata['contextid'];
@@ -73,8 +73,8 @@ class tool_uploadcourse_step2_form extends tool_uploadcourse_base_form {
 
         $mform->addElement('selectyesno', 'options[reset]', get_string('reset', 'tool_uploadcourse'));
         $mform->setDefault('options[reset]', 0);
-        $mform->disabledIf('options[reset]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
-        $mform->disabledIf('options[reset]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
+        $mform->hideIf('options[reset]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_NEW);
+        $mform->hideIf('options[reset]', 'options[mode]', 'eq', tool_uploadcourse_processor::MODE_CREATE_ALL);
         $mform->disabledIf('options[reset]', 'options[allowresets]', 'eq', 0);
         $mform->addHelpButton('options[reset]', 'reset', 'tool_uploadcourse');
 
index c0eb764..558f324 100644 (file)
@@ -95,7 +95,7 @@ class admin_uploaduser_form2 extends moodleform {
         $choices = array(0 => get_string('infilefield', 'auth'), 1 => get_string('createpasswordifneeded', 'auth'));
         $mform->addElement('select', 'uupasswordnew', get_string('uupasswordnew', 'tool_uploaduser'), $choices);
         $mform->setDefault('uupasswordnew', 1);
-        $mform->disabledIf('uupasswordnew', 'uutype', 'eq', UU_USER_UPDATE);
+        $mform->hideIf('uupasswordnew', 'uutype', 'eq', UU_USER_UPDATE);
 
         $choices = array(UU_UPDATE_NOCHANGES    => get_string('nochanges', 'tool_uploaduser'),
                          UU_UPDATE_FILEOVERRIDE => get_string('uuupdatefromfile', 'tool_uploaduser'),
@@ -103,16 +103,16 @@ class admin_uploaduser_form2 extends moodleform {
                          UU_UPDATE_MISSING      => get_string('uuupdatemissing', 'tool_uploaduser'));
         $mform->addElement('select', 'uuupdatetype', get_string('uuupdatetype', 'tool_uploaduser'), $choices);
         $mform->setDefault('uuupdatetype', UU_UPDATE_NOCHANGES);
-        $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDNEW);
-        $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDINC);
+        $mform->hideIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDNEW);
+        $mform->hideIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDINC);
 
         $choices = array(0 => get_string('nochanges', 'tool_uploaduser'), 1 => get_string('update'));
         $mform->addElement('select', 'uupasswordold', get_string('uupasswordold', 'tool_uploaduser'), $choices);
         $mform->setDefault('uupasswordold', 0);
-        $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDNEW);
-        $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDINC);
-        $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 0);
-        $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 3);
+        $mform->hideIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDNEW);
+        $mform->hideIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDINC);
+        $mform->hideIf('uupasswordold', 'uuupdatetype', 'eq', 0);
+        $mform->hideIf('uupasswordold', 'uuupdatetype', 'eq', 3);
 
         $choices = array(UU_PWRESET_WEAK => get_string('usersweakpassword', 'tool_uploaduser'),
                          UU_PWRESET_NONE => get_string('none'),
@@ -125,18 +125,18 @@ class admin_uploaduser_form2 extends moodleform {
 
         $mform->addElement('selectyesno', 'uuallowrenames', get_string('allowrenames', 'tool_uploaduser'));
         $mform->setDefault('uuallowrenames', 0);
-        $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDNEW);
-        $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDINC);
+        $mform->hideIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDNEW);
+        $mform->hideIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDINC);
 
         $mform->addElement('selectyesno', 'uuallowdeletes', get_string('allowdeletes', 'tool_uploaduser'));
         $mform->setDefault('uuallowdeletes', 0);
-        $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDNEW);
-        $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDINC);
+        $mform->hideIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDNEW);
+        $mform->hideIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDINC);
 
         $mform->addElement('selectyesno', 'uuallowsuspends', get_string('allowsuspends', 'tool_uploaduser'));
         $mform->setDefault('uuallowsuspends', 1);
-        $mform->disabledIf('uuallowsuspends', 'uutype', 'eq', UU_USER_ADDNEW);
-        $mform->disabledIf('uuallowsuspends', 'uutype', 'eq', UU_USER_ADDINC);
+        $mform->hideIf('uuallowsuspends', 'uutype', 'eq', UU_USER_ADDNEW);
+        $mform->hideIf('uuallowsuspends', 'uutype', 'eq', UU_USER_ADDINC);
 
         if (!empty($CFG->allowaccountssameemail)) {
             $mform->addElement('selectyesno', 'uunoemailduplicates', get_string('uunoemailduplicates', 'tool_uploaduser'));
@@ -209,14 +209,14 @@ class admin_uploaduser_form2 extends moodleform {
         $mform->addElement('text', 'username', get_string('uuusernametemplate', 'tool_uploaduser'), 'size="20"');
         $mform->setType('username', PARAM_RAW); // No cleaning here. The process verifies it later.
         $mform->addRule('username', get_string('requiredtemplate', 'tool_uploaduser'), 'required', null, 'client');
-        $mform->disabledIf('username', 'uutype', 'eq', UU_USER_ADD_UPDATE);
-        $mform->disabledIf('username', 'uutype', 'eq', UU_USER_UPDATE);
+        $mform->hideIf('username', 'uutype', 'eq', UU_USER_ADD_UPDATE);
+        $mform->hideIf('username', 'uutype', 'eq', UU_USER_UPDATE);
         $mform->setForceLtr('username');
 
         $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"');
         $mform->setType('email', PARAM_RAW); // No cleaning here. The process verifies it later.
-        $mform->disabledIf('email', 'uutype', 'eq', UU_USER_ADD_UPDATE);
-        $mform->disabledIf('email', 'uutype', 'eq', UU_USER_UPDATE);
+        $mform->hideIf('email', 'uutype', 'eq', UU_USER_ADD_UPDATE);
+        $mform->hideIf('email', 'uutype', 'eq', UU_USER_UPDATE);
         $mform->setForceLtr('email');
 
         // only enabled and known to work plugins
index 886c250..3771835 100644 (file)
Binary files a/admin/tool/usertours/amd/build/managesteps.min.js and b/admin/tool/usertours/amd/build/managesteps.min.js differ
index 9c9e2e6..75c7d1b 100644 (file)
Binary files a/admin/tool/usertours/amd/build/managetours.min.js and b/admin/tool/usertours/amd/build/managetours.min.js differ
index ba52019..420b89e 100644 (file)
@@ -18,6 +18,7 @@ function($, str, notification) {
          */
         removeStep: function(e) {
             e.preventDefault();
+            var targetUrl = $(e.currentTarget).attr('href');
             str.get_strings([
                 {
                     key:        'confirmstepremovaltitle',
@@ -35,11 +36,15 @@ function($, str, notification) {
                     key:        'no',
                     component:  'moodle'
                 }
-            ]).done(function(s) {
-                notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
-                    window.location = $(this).attr('href');
-                }, e.currentTarget));
-            });
+            ])
+            .then(function(s) {
+                notification.confirm(s[0], s[1], s[2], s[3], function() {
+                    window.location = targetUrl;
+                });
+
+                return;
+            })
+            .catch();
         },
 
         /**
index f5c601a..f6d3237 100644 (file)
@@ -18,7 +18,7 @@ function($, ajax, str, notification) {
          */
         removeTour: function(e) {
             e.preventDefault();
-
+            var targetUrl = $(e.currentTarget).attr('href');
             str.get_strings([
                 {
                     key:        'confirmtourremovaltitle',
@@ -36,11 +36,15 @@ function($, ajax, str, notification) {
                     key:        'no',
                     component:  'moodle'
                 }
-            ]).done(function(s) {
-                notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
-                    window.location = $(this).attr('href');
-                }, e.currentTarget));
-            });
+            ])
+            .then(function(s) {
+                notification.confirm(s[0], s[1], s[2], s[3], function() {
+                    window.location = targetUrl;
+                });
+
+                return;
+            })
+            .catch();
         },
 
         /**
index 14a96e0..1e4cdbb 100644 (file)
@@ -497,6 +497,12 @@ class helper {
             return;
         }
 
+        if (in_array($PAGE->pagelayout, ['maintenance', 'print', 'redirect'])) {
+            // Do not try to show user tours inside iframe, in maintenance mode,
+            // when printing, or during redirects.
+            return;
+        }
+
         if (self::$bootstrapped) {
             return;
         }
index ffbd787..3f38f0a 100644 (file)
@@ -101,7 +101,7 @@ class block extends base {
      * @param   MoodleQuickForm $mform      The form to add configuration to.
      */
     public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
-        $mform->disabledIf('targetvalue_block', 'targettype', 'noteq',
+        $mform->hideIf('targetvalue_block', 'targettype', 'noteq',
                 \tool_usertours\target::get_target_constant_for_class(get_class()));
     }
 
index ae6f2fc..3e3fd58 100644 (file)
@@ -91,7 +91,7 @@ class selector extends base {
      * @param   MoodleQuickForm $mform      The form to add configuration to.
      */
     public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
-        $mform->disabledIf('targetvalue_selector', 'targettype', 'noteq',
+        $mform->hideIf('targetvalue_selector', 'targettype', 'noteq',
                 \tool_usertours\target::get_target_constant_for_class(get_class()));
     }
 
index 6a4b078..696efe5 100644 (file)
@@ -84,7 +84,7 @@ class unattached extends base {
         $myvalue = \tool_usertours\target::get_target_constant_for_class(get_class());
 
         foreach (array_keys(self::$forcedsettings) as $settingname) {
-            $mform->disabledIf($settingname, 'targettype', 'eq', $myvalue);
+            $mform->hideIf($settingname, 'targettype', 'eq', $myvalue);
         }
     }
 
index a4fb976..192fec4 100644 (file)
     }
 
 }}
-<div class="modal" data-role="flexitour-step">
-    <div data-role="arrow"></div>
+<div class="modal-dialog" role="document" data-role="flexitour-step">
+  <div class="modal-content">
+    <div class="tooltip-arrow" data-role="arrow"></div>
     <div class="modal-header">
-      <button type="button" class="close" data-dismiss="modal" aria-hidden="true" data-role="end">&times;</button>
-      <h3 data-placeholder="title"></h3>
+      <h5 class="modal-title" data-placeholder="title"></h5>
+      <button type="button" class="close" data-dismiss="modal" aria-label="Close" data-role="end">
+        <span aria-hidden="true">&times;</span>
+      </button>
+
+    </div>
+    <div class="modal-body" data-placeholder="body">
     </div>
-    <div class="modal-body" data-placeholder="body"></div>
     <div class="modal-footer">
-        <div class="btn-group">
-            <button href="#" class="btn" data-role="previous">{{# str }} previous, moodle {{/ str }}</button>
-            <button href="#" class="btn btn-primary" data-role="next">{{# str }} next, moodle {{/ str }}</button>
-        </div>
-        <button class="btn" data-role="end"> {{# str }} endtour, tool_usertours {{/ str }} </button>
+      <button type="button" class="btn btn-secondary" data-role="previous">{{# str }} previous, moodle {{/ str }}</button>
+      <button type="button" class="btn btn-primary" data-role="next">{{# str }} next, moodle {{/ str }}</button>
+      <button class="btn btn-secondary" data-role="end"> {{# str }} endtour, tool_usertours {{/ str }} </button>
     </div>
+  </div>
 </div>
diff --git a/admin/tool/xmldb/actions/add_persistent_mandatory/add_persistent_mandatory.class.php b/admin/tool/xmldb/actions/add_persistent_mandatory/add_persistent_mandatory.class.php
new file mode 100644 (file)
index 0000000..a323c1e
--- /dev/null
@@ -0,0 +1,154 @@
+<?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/>.
+
+/**
+ * @package    tool_xmldb
+ * @copyright  2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Add the mandatory fields for persistent to the table.
+ *
+ * @package    tool_xmldb
+ * @copyright  2019 Michael Aherne
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class add_persistent_mandatory extends XMLDBAction {
+
+    function init() {
+
+        parent::init();
+
+        // Get needed strings.
+        $this->loadStrings(array(
+            'addpersistent' => 'tool_xmldb',
+            'persistentfieldsconfirm' => 'tool_xmldb',
+            'persistentfieldscomplete' => 'tool_xmldb',
+            'persistentfieldsexist' => 'tool_xmldb',
+            'back' => 'core'
+        ));
+
+    }
+
+    function getTitle() {
+        return $this->str['addpersistent'];
+    }
+
+    function invoke() {
+
+        parent::invoke();
+
+        $this->does_generate = ACTION_GENERATE_HTML;
+
+        global $CFG, $XMLDB, $OUTPUT;
+
+        $dir = required_param('dir', PARAM_PATH);
+        $dirpath = $CFG->dirroot . $dir;
+
+        if (empty($XMLDB->dbdirs)) {
+            return false;
+        }
+
+        if (!empty($XMLDB->editeddirs)) {
+            $editeddir = $XMLDB->editeddirs[$dirpath];
+            $structure = $editeddir->xml_file->getStructure();
+        }
+
+        $tableparam = required_param('table', PARAM_ALPHANUMEXT);
+
+        /** @var xmldb_table $table */
+        $table = $structure->getTable($tableparam);
+
+        $result = true;
+        // Launch postaction if exists (leave this here!)
+        if ($this->getPostAction() && $result) {
+            return $this->launch($this->getPostAction());
+        }
+
+        $confirm = optional_param('confirm', false, PARAM_BOOL);
+
+        $fields = ['usermodified', 'timecreated', 'timemodified'];
+        $existing = [];
+        foreach ($fields as $field) {
+            if ($table->getField($field)) {
+                $existing[] = $field;
+            }
+        }
+
+        $returnurl = new \moodle_url('/admin/tool/xmldb/index.php', [
+            'table' => $tableparam,
+            'dir' => $dir,
+            'action' => 'edit_table'
+        ]);
+
+        $backbutton = html_writer::link($returnurl, '[' . $this->str['back'] . ']');
+        $actionbuttons = html_writer::tag('p', $backbutton, ['class' => 'centerpara buttons']);
+
+        if (!$confirm) {
+
+            if (!empty($existing)) {
+
+                $message = html_writer::span($this->str['persistentfieldsexist']);
+                $message .= html_writer::alist($existing);
+                $this->output .= $OUTPUT->notification($message);
+
+                if (count($existing) == count($fields)) {
+                    $this->output .= $actionbuttons;
+                    return true;
+                }
+            }
+
+            $confirmurl = new \moodle_url('/admin/tool/xmldb/index.php', [
+                'table' => $tableparam,
+                'dir' => $dir,
+                'action' => 'add_persistent_mandatory',
+                'sesskey' => sesskey(),
+                'confirm' => '1'
+            ]);
+
+            $message = html_writer::span($this->str['persistentfieldsconfirm']);
+            $message .= html_writer::alist(array_diff($fields, $existing));
+            $this->output .= $OUTPUT->confirm($message, $confirmurl, $returnurl);
+
+        } else {
+
+            $fieldsadded = [];
+            foreach ($fields as $field) {
+                if (!in_array($field, $existing)) {
+                    $fieldsadded[] = $field;
+                    $table->add_field($field, XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, null, 0);
+                }
+            }
+
+            if (!$table->getKey('usermodified')) {
+                $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
+            }
+
+            $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+            $structure->setChanged(true);
+
+            $message = html_writer::span($this->str['persistentfieldscomplete']);
+            $message .= html_writer::alist(array_diff($fields, $existing));
+            $this->output .= $OUTPUT->notification($message, 'success');
+
+            $this->output .= $actionbuttons;
+        }
+
+        return $result;
+    }
+
+}
index 5cd4bcd..aa82f99 100644 (file)
@@ -44,6 +44,7 @@ class edit_table extends XMLDBAction {
 
         // Get needed strings
         $this->loadStrings(array(
+            'addpersistent' => 'tool_xmldb',
             'change' => 'tool_xmldb',
             'vieworiginal' => 'tool_xmldb',
             'viewedited' => 'tool_xmldb',
@@ -177,6 +178,15 @@ class edit_table extends XMLDBAction {
         $b .= '<a href="index.php?action=view_table_sql&amp;table=' . $tableparam . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' .$this->str['viewsqlcode'] . ']</a>';
         // The view php code button
         $b .= '&nbsp;<a href="index.php?action=view_table_php&amp;table=' . $tableparam . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['viewphpcode'] . ']</a>';
+        // The add persistent fields button.
+        $url = new \moodle_url('/admin/tool/xmldb/index.php', [
+            'action' => 'add_persistent_mandatory',
+            'sesskey' => sesskey(),
+            'table' => $tableparam,
+            'dir'=> str_replace($CFG->dirroot, '', $dirpath)
+        ]);
+        $b .= '&nbsp;' . \html_writer::link($url, '[' . $this->str['addpersistent'] . ']');
+
         // The save button (if possible)
         if ($cansavenow) {
             $b .= '&nbsp;<a href="index.php?action=save_xml_file&amp;sesskey=' . sesskey() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '&amp;time=' . time() . '&amp;unload=false&amp;postaction=edit_table&amp;table=' . $tableparam . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['save'] . ']</a>';
index d531a86..d2efeab 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 $string['actual'] = 'Actual';
+$string['addpersistent'] = 'Add mandatory persistent fields';
 $string['aftertable'] = 'After table:';
 $string['back'] = 'Back';
 $string['backtomainview'] = 'Back to main';
@@ -169,6 +170,9 @@ $string['numberincorrectwholepart'] = 'Too big whole number part for number fiel
 $string['pendingchanges'] = 'Note: You have performed changes to this file. They can be saved at any moment.';
 $string['pendingchangescannotbesaved'] = 'There are changes in this file but they cannot be saved! Please verify that both the directory and the "install.xml" within it have write permissions for the web server.';
 $string['pendingchangescannotbesavedreload'] = 'There are changes in this file but they cannot be saved! Please verify that both the directory and the "install.xml" within it have write permissions for the web server. Then reload this page and you should be able to save those changes.';
+$string['persistentfieldsconfirm'] = 'Do you want to add the following fields: ';
+$string['persistentfieldscomplete'] = 'The following fields have been added: ';
+$string['persistentfieldsexist'] = 'The f