Merge branch 'MDL-68113-master' of https://github.com/HuongNV13/moodle
authorJun Pataleta <jun@moodle.com>
Thu, 16 Apr 2020 03:46:50 +0000 (11:46 +0800)
committerJun Pataleta <jun@moodle.com>
Thu, 16 Apr 2020 03:46:50 +0000 (11:46 +0800)
901 files changed:
.eslintignore
.stylelintignore
Gruntfile.js
admin/cli/checks.php [new file with mode: 0644]
admin/contentbank.php [new file with mode: 0644]
admin/index.php
admin/renderer.php
admin/settings/badges.php
admin/settings/plugins.php
admin/tasklogs.php
admin/templates/tasklogs.mustache
admin/testoutgoingmailconf.php
admin/tool/analytics/classes/output/renderer.php
admin/tool/dataprivacy/amd/build/myrequestactions.min.js
admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map
admin/tool/dataprivacy/amd/src/myrequestactions.js
admin/tool/task/classes/check/adhocqueue.php [new file with mode: 0644]
admin/tool/task/classes/check/cronrunning.php [new file with mode: 0644]
admin/tool/task/classes/check/maxfaildelay.php [new file with mode: 0644]
admin/tool/task/classes/edit_scheduled_task_form.php
admin/tool/task/clear_fail_delay.php
admin/tool/task/lang/en/tool_task.php
admin/tool/task/lib.php [new file with mode: 0644]
admin/tool/task/renderer.php
admin/tool/task/schedule_task.php
admin/tool/task/scheduledtasks.php
admin/tool/task/tests/behat/clear_fail_delay.feature
admin/tool/task/tests/behat/manage_tasks.feature
auth/none/classes/check/noauth.php [new file with mode: 0644]
auth/none/lang/en/auth_none.php
auth/none/lib.php [new file with mode: 0644]
auth/none/version.php
backup/util/dbops/restore_dbops.class.php
backup/util/dbops/tests/restore_dbops_test.php
backup/util/ui/renderer.php
badges/classes/assertion.php
badges/classes/badge.php
badges/issuer_json.php
badges/renderer.php
badges/tests/badgeslib_test.php
badges/tests/behat/add_badge.feature
badges/tests/behat/award_badge.feature
badges/tests/behat/award_badge_groups.feature
badges/tests/behat/criteria_activity.feature
badges/tests/behat/criteria_cohort.feature
badges/tests/behat/criteria_competency.feature
badges/tests/behat/criteria_profile.feature
badges/tests/behat/role_visibility.feature
badges/upgrade.txt
badges/upgradelib.php
blocks/activity_modules/block_activity_modules.php
blocks/admin_bookmarks/tests/behat/bookmark_admin_pages.feature
blocks/badges/block_badges.php
blocks/badges/tests/behat/block_badges_course.feature
blocks/badges/tests/behat/block_badges_dashboard.feature
blocks/badges/tests/behat/block_badges_frontpage.feature
blocks/comments/block_comments.php
blocks/private_files/block_private_files.php
blocks/rss_client/block_rss_client.php
blocks/settings/block_settings.php
calendar/amd/build/crud.min.js
calendar/amd/build/crud.min.js.map
calendar/amd/src/crud.js
config-dist.php
contentbank/classes/content.php [new file with mode: 0644]
contentbank/classes/contentbank.php [new file with mode: 0644]
contentbank/classes/contenttype.php [new file with mode: 0644]
contentbank/classes/helper.php [new file with mode: 0644]
contentbank/classes/output/bankcontent.php [new file with mode: 0644]
contentbank/classes/privacy/provider.php [new file with mode: 0644]
contentbank/contenttype/h5p/classes/content.php [new file with mode: 0644]
contentbank/contenttype/h5p/classes/contenttype.php [new file with mode: 0644]
contentbank/contenttype/h5p/classes/privacy/provider.php [new file with mode: 0644]
contentbank/contenttype/h5p/db/access.php [new file with mode: 0644]
contentbank/contenttype/h5p/lang/en/contenttype_h5p.php [new file with mode: 0644]
contentbank/contenttype/h5p/tests/behat/admin_upload_content.feature [new file with mode: 0644]
contentbank/contenttype/h5p/tests/behat/teacher_upload_content.feature [new file with mode: 0644]
contentbank/contenttype/h5p/tests/content_h5p_test.php [new file with mode: 0644]
contentbank/contenttype/h5p/tests/contenttype_h5p_test.php [new file with mode: 0644]
contentbank/contenttype/h5p/version.php [new file with mode: 0644]
contentbank/files_form.php [new file with mode: 0644]
contentbank/index.php [new file with mode: 0644]
contentbank/templates/bankcontent.mustache [new file with mode: 0644]
contentbank/templates/toolbar.mustache [new file with mode: 0644]
contentbank/tests/behat/access_permissions.feature [new file with mode: 0644]
contentbank/tests/content_test.php [new file with mode: 0644]
contentbank/tests/contentbank_test.php [new file with mode: 0644]
contentbank/tests/contenttype_test.php [new file with mode: 0644]
contentbank/tests/fixtures/testable_content.php [new file with mode: 0644]
contentbank/tests/fixtures/testable_contenttype.php [new file with mode: 0644]
contentbank/upload.php [new file with mode: 0644]
contentbank/view.php [new file with mode: 0644]
course/amd/build/activitychooser.min.js
course/amd/build/activitychooser.min.js.map
course/amd/build/local/activitychooser/dialogue.min.js
course/amd/build/local/activitychooser/dialogue.min.js.map
course/amd/build/local/activitychooser/selectors.min.js
course/amd/build/local/activitychooser/selectors.min.js.map
course/amd/src/activitychooser.js
course/amd/src/local/activitychooser/dialogue.js
course/amd/src/local/activitychooser/selectors.js
course/classes/local/service/content_item_service.php
course/classes/management_renderer.php
course/classes/output/recommendations/activity_list.php
course/format/renderer.php
course/format/topics/format.js
course/format/topics/renderer.php
course/format/upgrade.txt
course/format/weeks/format.js
course/recommendations.php
course/resources.php
course/templates/activity_list.mustache
course/templates/activitychooser.mustache
course/templates/local/activitychooser/search.mustache
course/tests/behat/search_recommended_activities.feature [new file with mode: 0644]
course/tests/services_content_item_service_test.php
course/yui/build/moodle-course-dragdrop/moodle-course-dragdrop-debug.js
course/yui/build/moodle-course-dragdrop/moodle-course-dragdrop-min.js
course/yui/build/moodle-course-dragdrop/moodle-course-dragdrop.js
course/yui/src/dragdrop/js/resource.js
course/yui/src/dragdrop/js/section.js
enrol/manual/lib.php
grade/grading/form/guide/renderer.php
grade/import/lib.php
grade/report/user/renderer.php
h5p/ajax.php [new file with mode: 0644]
h5p/amd/build/editor_display.min.js [new file with mode: 0644]
h5p/amd/build/editor_display.min.js.map [new file with mode: 0644]
h5p/amd/src/editor_display.js [new file with mode: 0644]
h5p/classes/api.php
h5p/classes/core.php
h5p/classes/editor.php [new file with mode: 0644]
h5p/classes/editor_ajax.php [new file with mode: 0644]
h5p/classes/editor_framework.php [new file with mode: 0644]
h5p/classes/factory.php
h5p/classes/file_storage.php
h5p/classes/framework.php
h5p/classes/helper.php
h5p/classes/local/library/autoloader.php
h5p/classes/local/library/handler.php
h5p/classes/output/h5peditor.php [new file with mode: 0644]
h5p/classes/output/renderer.php [new file with mode: 0644]
h5p/classes/player.php
h5p/embed.php
h5p/h5plib/v124/joubel/editor/README.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/CHANGES.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/LICENSE.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/adapters/jquery.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/build-config.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/ckeditor.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/config.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/contents.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/af.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ar.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/az.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/bg.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/bn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/bs.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/cs.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/cy.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/da.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/de-ch.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/de.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/el.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/en-au.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/en-ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/en-gb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/en.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/eo.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/es-mx.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/es.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/et.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/eu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/fa.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/fi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/fo.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/fr-ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/fr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/gl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/gu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/he.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/hi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/hr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/hu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/id.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/is.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/it.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ja.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ka.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/km.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ko.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ku.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/lt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/lv.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/mk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/mn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ms.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/nb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/nl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/no.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/oc.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/pl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/pt-br.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/pt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ro.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ru.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/si.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/sk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/sl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/sq.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/sr-latn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/sr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/sv.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/th.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/tr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/tt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/ug.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/uk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/vi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/zh-cn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/lang/zh.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/af.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ar.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/az.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/bg.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/cs.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/cy.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/da.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/de-ch.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/de.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/el.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/en-au.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/en.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/eo.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/es-mx.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/es.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/et.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/eu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/fa.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/fi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/fo.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/fr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/gl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/gu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/he.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/hi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/hr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/hu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/id.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/it.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ja.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/km.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ko.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ku.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/lt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/lv.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/mk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/mn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/nb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/nl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/no.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/oc.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/pl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/pt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ro.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ru.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/si.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/sk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/sl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/sq.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/sr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/sv.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/th.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/tr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/tt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/ug.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/uk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/vi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/a11yhelp/dialogs/lang/zh.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/clipboard/dialogs/paste.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codeTag/README.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/dialogs/codesnippet.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/CHANGES.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/LICENSE [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/README.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/README.ru.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/highlight.pack.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/arta.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/ascetic.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-dune.dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-dune.light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-forest.dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-forest.light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-heath.dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-heath.light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-lakeside.dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-lakeside.light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-seaside.dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/atelier-seaside.light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/brown_paper.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/brown_papersq.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/default.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/docco.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/far.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/foundation.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/github.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/googlecode.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/idea.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/ir_black.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/magula.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/mono-blue.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/monokai.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/monokai_sublime.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/obsidian.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/paraiso.dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/paraiso.light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/pojoaque.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/pojoaque.jpg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/railscasts.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/rainbow.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/school_book.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/school_book.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/solarized_dark.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/solarized_light.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/sunburst.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/tomorrow-night-blue.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/tomorrow-night-bright.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/tomorrow-night-eighties.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/tomorrow-night.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/tomorrow.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/vs.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/xcode.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/codesnippet/lib/highlight/styles/zenburn.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/colordialog/dialogs/colordialog.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/colordialog/dialogs/colordialog.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/customCodeHighlighter/plugin.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/dialog/dialogDefinition.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/dialog/styles/dialog.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/icons.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/icons_hidpi.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/lineheight/LICENSE [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/lineheight/README.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/lineheight/readme.txt [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/link/dialogs/anchor.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/link/dialogs/link.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/link/images/anchor.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/link/images/hidpi/anchor.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/magicline/images/hidpi/icon-rtl.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/magicline/images/hidpi/icon.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/magicline/images/icon-rtl.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/magicline/images/icon.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/pastefromword/filter/default.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/pastetools/filter/common.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/removeRedundantNBSP/plugin.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/_translationstatus.txt [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/af.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ar.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/az.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/bg.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/cs.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/cy.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/da.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/de-ch.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/de.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/el.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/en-au.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/en-ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/en-gb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/en.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/eo.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/es-mx.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/es.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/et.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/eu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/fa.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/fi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/fr-ca.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/fr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/gl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/he.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/hr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/hu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/id.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/it.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ja.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/km.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ko.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ku.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/lt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/lv.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/nb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/nl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/no.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/oc.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/pl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/pt-br.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/pt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ro.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ru.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/si.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/sk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/sl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/sq.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/sr-latn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/sr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/sv.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/th.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/tr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/tt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/ug.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/uk.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/vi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/zh-cn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/lang/zh.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/specialchar/dialogs/specialchar.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/table/dialogs/table.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/tabletools/dialogs/tableCell.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/plugins/widget/images/handle.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/css/samples.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/img/github-top.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/img/header-bg.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/img/header-separator.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/img/logo.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/img/logo.svg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/img/navigation-tip.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/index.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/js/sample.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/js/sf.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/ajax.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/api.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/appendto.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/assets/inlineall/logo.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/assets/outputxhtml/outputxhtml.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/assets/posteddata.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/assets/sample.jpg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/assets/uilanguages/languages.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/autogrow/autogrow.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/codesnippet/codesnippet.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/datafiltering.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/dialog/assets/my_dialog.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/dialog/dialog.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/divreplace.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/enterkey/enterkey.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.fla [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.swf [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/htmlwriter/assets/outputforflash/swfobject.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/htmlwriter/outputforflash.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/htmlwriter/outputhtml.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/index.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/inlineall.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/inlinebycode.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/inlinetextarea.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/jquery.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/magicline/magicline.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/readonly.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/replacebyclass.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/replacebycode.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/sample.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/sample.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/sample_posteddata.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/tabindex.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/toolbar/toolbar.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/uicolor.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/uilanguages.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/wysiwygarea/fullpage.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/old/xhtmlstyle.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/css/fontello.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/font/LICENSE.txt [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/font/config.json [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/font/fontello.eot [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/font/fontello.svg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/font/fontello.ttf [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/font/fontello.woff [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/index.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/js/toolbarmodifier.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/js/toolbartextmodifier.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/LICENSE [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/codemirror.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/codemirror.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/javascript.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/neo.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/show-hint.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/samples/toolbarconfigurator/lib/codemirror/show-hint.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/dialog.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/dialog_ie.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/dialog_ie7.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/dialog_ie8.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/dialog_iequirks.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/dialog_opera.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/editor.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/editor_gecko.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/editor_ie.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/editor_ie7.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/editor_ie8.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/.temp/css/editor_iequirks.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/dialog.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/dialog_ie.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/dialog_ie7.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/dialog_ie8.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/dialog_iequirks.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/dialog_opera.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/editor.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/editor_gecko.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/editor_ie.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/editor_ie7.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/editor_ie8.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/editor_iequirks.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/icons.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/icons_hidpi.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/arrow.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/close.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/hidpi/close.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/hidpi/lock-open.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/hidpi/lock.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/hidpi/refresh.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/lock-open.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/lock.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/images/refresh.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/readme.md [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/sample/bootstrapck-sample.html [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/sample/css/bootstrapck-sample.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/sample/js/analytics.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/sample/js/jquery-1.11.0.min.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/gecko/editor_gecko.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/ie/dialog_ie.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/ie/editor_ie.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/ie7/dialog_ie7.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/ie7/editor_ie7.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/ie8/dialog_ie8.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/ie8/editor_ie8.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/iequirks/dialog_iequirks.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/iequirks/editor_iequirks.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/browser-specific/opera/dialog_opera.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_colorpanel.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_elementspath.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_mainui.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_menu.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_panel.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_presets.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_reset.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_richcombo.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/_toolbar.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/components/editor.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/config/_colors.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/config/_config.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/config/_defaults.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/skins/bootstrapck/scss/dialog/dialog.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/ckeditor/styles.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/h5peditor-ajax.class.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/h5peditor-ajax.interface.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/h5peditor-file.class.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/h5peditor-storage.interface.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/h5peditor.class.php [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/add.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/binary-file.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/collapse.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/down.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/expand.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/order.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/remove.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/transparent-background.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/images/webm-file.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/ar.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/bs.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/de.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/el.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/en.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/es-cr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/es-mx.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/es.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/et.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/eu.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/fi.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/fr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/it.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/nb.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/nl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/nn.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/pl.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/pt-br.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/pt.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/ru.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/language/tr.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/libs/darkroom.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/libs/darkroom.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/libs/fabric.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/libs/zebra_datepicker.min.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/readme_moodle.txt [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5p-hub-client.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-av.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-boolean.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-coordinates.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-dimensions.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-editor.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-file-uploader.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-file.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-form.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-fullscreen-bar.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-group.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-html.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-image-popup.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-image.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-init.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-library-list-cache.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-library-selector.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-library.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-list-editor.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-list.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-metadata-author-widget.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-metadata-changelog-widget.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-metadata.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-none.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-number.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-pre-save.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-select.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-selector-hub.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-selector-legacy.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-semantic-structure.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-text.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor-textarea.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/scripts/h5peditor.js [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/config.rb [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/application.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/cke-contents.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.eot [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.svg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.ttf [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.woff [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-hub.eot [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-hub.svg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-hub.ttf [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-hub.woff [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-metadata-icons.eot [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-metadata-icons.svg [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-metadata-icons.ttf [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/fonts/h5p-metadata-icons.woff [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/h5p-hub-client.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/libs/icons.png [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/css/libs/zebra_datepicker.min.css [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_copy-paste.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_deprecated.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_form-field.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_form-groups.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_fullscreen-bar.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_h5peditor-image-edit-popup.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_h5peditor-image-edit.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_metadata-author-widget.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_metadata-changelog-widget.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_metadata-form.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_metadata-popup.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_mixins.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_utils.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/_variables.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/application.scss [new file with mode: 0644]
h5p/h5plib/v124/joubel/editor/styles/scss/cke-contents.scss [new file with mode: 0644]
h5p/h5plib/v124/thirdpartylibs.xml
h5p/js/embed.js
h5p/js/h5p_overrides.js
h5p/lib.php
h5p/templates/h5peditor.mustache [new file with mode: 0644]
h5p/tests/editor_ajax_test.php [new file with mode: 0644]
h5p/tests/editor_framework_test.php [new file with mode: 0644]
h5p/tests/editor_test.php [new file with mode: 0644]
h5p/tests/fixtures/multiple-choice-2-6.h5p [new file with mode: 0644]
h5p/tests/framework_test.php
h5p/tests/generator/lib.php
h5p/tests/generator_test.php
h5p/tests/h5p_file_storage_test.php
h5p/upgrade.txt
install/lang/se/error.php [new file with mode: 0644]
install/lang/se/install.php
lang/en/admin.php
lang/en/cache.php
lang/en/contentbank.php [new file with mode: 0644]
lang/en/course.php
lang/en/error.php
lang/en/h5p.php
lang/en/moodle.php
lang/en/plugin.php
lang/en/role.php
lib/adminlib.php
lib/amd/build/drawer.min.js
lib/amd/build/drawer.min.js.map
lib/amd/build/form-autocomplete.min.js
lib/amd/build/form-autocomplete.min.js.map
lib/amd/src/drawer.js
lib/amd/src/form-autocomplete.js
lib/badgeslib.php
lib/classes/check/access/defaultuserrole.php [new file with mode: 0644]
lib/classes/check/access/frontpagerole.php [new file with mode: 0644]
lib/classes/check/access/guestrole.php [new file with mode: 0644]
lib/classes/check/access/riskadmin.php [new file with mode: 0644]
lib/classes/check/access/riskbackup.php [new file with mode: 0644]
lib/classes/check/access/riskbackup_result.php [new file with mode: 0644]
lib/classes/check/access/riskxss.php [new file with mode: 0644]
lib/classes/check/access/riskxss_result.php [new file with mode: 0644]
lib/classes/check/check.php [new file with mode: 0644]
lib/classes/check/environment/configrw.php [new file with mode: 0644]
lib/classes/check/environment/displayerrors.php [new file with mode: 0644]
lib/classes/check/environment/environment.php [new file with mode: 0644]
lib/classes/check/environment/nodemodules.php [new file with mode: 0644]
lib/classes/check/environment/preventexecpath.php [new file with mode: 0644]
lib/classes/check/environment/unsecuredataroot.php [new file with mode: 0644]
lib/classes/check/environment/upgradecheck.php [new file with mode: 0644]
lib/classes/check/environment/vendordir.php [new file with mode: 0644]
lib/classes/check/http/cookiesecure.php [new file with mode: 0644]
lib/classes/check/manager.php [new file with mode: 0644]
lib/classes/check/performance/backups.php [new file with mode: 0644]
lib/classes/check/performance/cachejs.php [new file with mode: 0644]
lib/classes/check/performance/debugging.php [new file with mode: 0644]
lib/classes/check/performance/designermode.php [new file with mode: 0644]
lib/classes/check/performance/stats.php [new file with mode: 0644]
lib/classes/check/result.php [new file with mode: 0644]
lib/classes/check/security/crawlers.php [new file with mode: 0644]
lib/classes/check/security/emailchangeconfirmation.php [new file with mode: 0644]
lib/classes/check/security/embed.php [new file with mode: 0644]
lib/classes/check/security/mediafilterswf.php [new file with mode: 0644]
lib/classes/check/security/openprofiles.php [new file with mode: 0644]
lib/classes/check/security/passwordpolicy.php [new file with mode: 0644]
lib/classes/check/security/webcron.php [new file with mode: 0644]
lib/classes/check/table.php [new file with mode: 0644]
lib/classes/output/icon_system_fontawesome.php
lib/classes/plugin_manager.php
lib/classes/plugininfo/contenttype.php [new file with mode: 0644]
lib/classes/task/manager.php
lib/classes/task/scheduled_task.php
lib/clilib.php
lib/completionlib.php
lib/components.json
lib/db/access.php
lib/db/caches.php
lib/db/install.xml
lib/db/upgrade.php
lib/filelib.php
lib/mdn-polyfills/readme_moodle.txt [deleted file]
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/polyfills/polyfill.js [moved from lib/mdn-polyfills/polyfill.js with 64% similarity]
lib/polyfills/readme_moodle.txt [new file with mode: 0644]
lib/table/amd/build/dynamic.min.js
lib/table/amd/build/dynamic.min.js.map
lib/table/amd/build/local/dynamic/repository.min.js
lib/table/amd/build/local/dynamic/repository.min.js.map
lib/table/amd/build/local/dynamic/selectors.min.js
lib/table/amd/build/local/dynamic/selectors.min.js.map
lib/table/amd/src/dynamic.js
lib/table/amd/src/local/dynamic/repository.js
lib/table/amd/src/local/dynamic/selectors.js
lib/table/classes/external/dynamic/fetch.php
lib/tablelib.php
lib/templates/check/result.mustache [new file with mode: 0644]
lib/templates/check/result/critical.mustache [new file with mode: 0644]
lib/templates/check/result/error.mustache [new file with mode: 0644]
lib/templates/check/result/info.mustache [new file with mode: 0644]
lib/templates/check/result/na.mustache [new file with mode: 0644]
lib/templates/check/result/ok.mustache [new file with mode: 0644]
lib/templates/check/result/unknown.mustache [new file with mode: 0644]
lib/templates/check/result/warning.mustache [new file with mode: 0644]
lib/templates/custom_menu_item.mustache
lib/templates/drawer.mustache
lib/templates/initials_bar.mustache
lib/templates/paging_bar.mustache
lib/tests/check_test.php [new file with mode: 0644]
lib/tests/completionlib_test.php
lib/tests/component_test.php
lib/tests/moodlelib_test.php
lib/tests/outputcomponents_test.php
lib/tests/tablelib_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-debug.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop-min.js
lib/yui/build/moodle-core-dragdrop/moodle-core-dragdrop.js
lib/yui/src/blocks/js/manager.js
lib/yui/src/dragdrop/js/dragdrop.js
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/book/tool/print/classes/output/renderer.php
mod/book/view.php
mod/choice/renderer.php
mod/data/field/multimenu/field.class.php
mod/forum/amd/build/local/grades/grader.min.js
mod/forum/amd/build/local/grades/grader.min.js.map
mod/forum/amd/build/local/grades/local/grader/selectors.min.js
mod/forum/amd/build/local/grades/local/grader/selectors.min.js.map
mod/forum/amd/build/local/grades/local/grader/user_picker.min.js
mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map
mod/forum/amd/build/local/grades/local/grader/user_picker/selectors.min.js
mod/forum/amd/build/local/grades/local/grader/user_picker/selectors.min.js.map
mod/forum/amd/src/local/grades/grader.js
mod/forum/amd/src/local/grades/local/grader/selectors.js
mod/forum/amd/src/local/grades/local/grader/user_picker.js
mod/forum/amd/src/local/grades/local/grader/user_picker/selectors.js
mod/forum/lang/en/forum.php
mod/forum/report/summary/classes/event/report_downloaded.php
mod/forum/report/summary/classes/event/report_viewed.php
mod/forum/report/summary/classes/output/filters.php
mod/forum/report/summary/classes/summary_table.php
mod/forum/report/summary/index.php
mod/forum/report/summary/lang/en/forumreport_summary.php
mod/forum/report/summary/renderer.php
mod/forum/report/summary/templates/filters.mustache
mod/forum/report/summary/tests/behat/bulk_message.feature
mod/forum/report/summary/tests/behat/course_summary.feature [new file with mode: 0644]
mod/forum/report/summary/tests/behat/private_replies.feature
mod/forum/report/summary/tests/behat/summary_data_access.feature
mod/forum/report/summary/tests/behat/summary_data_attachments.feature
mod/forum/report/summary/tests/behat/summary_data_post_dates.feature
mod/forum/report/summary/tests/behat/summary_filter_groups.feature
mod/forum/report/summary/tests/behat/summary_filter_no_groups.feature
mod/forum/templates/local/grades/grader.mustache
mod/forum/templates/local/grades/local/grader/content.mustache
mod/forum/templates/local/grades/local/grader/grading.mustache
mod/forum/templates/local/grades/local/grader/navigation.mustache
mod/forum/templates/local/grades/local/grader/user_picker.mustache
mod/forum/templates/local/grades/local/grader/user_picker/user.mustache
mod/h5pactivity/classes/event/course_module_instance_list_viewed.php
mod/h5pactivity/classes/event/course_module_viewed.php
mod/h5pactivity/classes/event/statement_received.php [new file with mode: 0644]
mod/h5pactivity/classes/local/attempt.php [new file with mode: 0644]
mod/h5pactivity/classes/privacy/provider.php
mod/h5pactivity/classes/xapi/handler.php [new file with mode: 0644]
mod/h5pactivity/db/access.php
mod/h5pactivity/db/install.xml
mod/h5pactivity/db/upgrade.php [new file with mode: 0644]
mod/h5pactivity/lang/en/h5pactivity.php
mod/h5pactivity/lib.php
mod/h5pactivity/tests/behat/add_h5pactivity.feature
mod/h5pactivity/tests/behat/sending_attempt.feature [new file with mode: 0644]
mod/h5pactivity/tests/event/course_module_instance_list_viewed_test.php [new file with mode: 0644]
mod/h5pactivity/tests/event/course_module_viewed_test.php [moved from mod/h5pactivity/tests/events_test.php with 61% similarity]
mod/h5pactivity/tests/event/statement_received_test.php [new file with mode: 0644]
mod/h5pactivity/tests/generator/lib.php
mod/h5pactivity/tests/local/attempt_test.php [new file with mode: 0644]
mod/h5pactivity/tests/privacy_test.php [new file with mode: 0644]
mod/h5pactivity/tests/xapi/handler_test.php [new file with mode: 0644]
mod/h5pactivity/version.php
mod/h5pactivity/view.php
mod/lesson/renderer.php
mod/wiki/renderer.php
mod/workshop/renderer.php
phpunit.xml.dist
pix/i/upload.png [new file with mode: 0644]
pix/i/upload.svg [new file with mode: 0644]
question/type/ddimageortext/rendererbase.php
question/type/ddmarker/renderer.php
question/type/ddwtos/renderer.php
report/eventlist/classes/renderer.php
report/insights/classes/output/renderer.php
report/log/classes/renderable.php
report/log/locallib.php
report/performance/index.php
report/performance/locallib.php [deleted file]
report/performance/version.php
report/security/classes/event/report_viewed.php [new file with mode: 0644]
report/security/index.php
report/security/lang/en/report_security.php
report/security/locallib.php [deleted file]
report/security/settings.php
report/security/version.php
report/status/classes/privacy/provider.php [new file with mode: 0644]
report/status/db/access.php [new file with mode: 0644]
report/status/index.php [new file with mode: 0644]
report/status/lang/en/report_status.php [new file with mode: 0644]
report/status/settings.php [new file with mode: 0644]
report/status/version.php [new file with mode: 0644]
rss/renderer.php
tag/classes/renderer.php
theme/boost/scss/moodle.scss
theme/boost/scss/moodle/contentbank.scss [new file with mode: 0644]
theme/boost/scss/moodle/core.scss
theme/boost/scss/moodle/modules.scss
theme/boost/scss/preset/default.scss
theme/boost/style/moodle.css
theme/classic/style/moodle.css
user/classes/participants_table.php
user/index.php
user/renderer.php
version.php

index c111d11..97af2d9 100644 (file)
@@ -9,7 +9,9 @@ cache/stores/mongodb/MongoDB/
 enrol/lti/ims-blti/
 filter/algebra/AlgParser.pm
 filter/tex/mimetex.*
+h5p/amd/src/editor_display.js
 h5p/h5plib/v124/joubel/core/
+h5p/h5plib/v124/joubel/editor/
 lib/editor/atto/plugins/html/yui/src/codemirror/
 lib/editor/atto/plugins/html/yui/src/beautify/
 lib/editor/atto/yui/src/rangy/js/*.*
@@ -62,7 +64,7 @@ lib/amd/src/popper.js
 lib/geopattern-php/
 lib/php-jwt/
 lib/babel-polyfill/
-lib/mdn-polyfills/
+lib/polyfills/
 lib/emoji-data/
 media/player/videojs/amd/src/video-lazy.js
 media/player/videojs/amd/src/Youtube-lazy.js
@@ -87,4 +89,4 @@ theme/boost/amd/src/toast.js
 theme/boost/amd/src/tooltip.js
 theme/boost/amd/src/util.js
 theme/boost/amd/src/tether.js
-theme/boost/scss/fontawesome/
\ No newline at end of file
+theme/boost/scss/fontawesome/
index a828212..f00e696 100644 (file)
@@ -11,6 +11,7 @@ enrol/lti/ims-blti/
 filter/algebra/AlgParser.pm
 filter/tex/mimetex.*
 h5p/h5plib/v124/joubel/core/
+h5p/h5plib/v124/joubel/editor/
 lib/editor/atto/plugins/html/yui/src/codemirror/
 lib/editor/atto/plugins/html/yui/src/beautify/
 lib/editor/atto/yui/src/rangy/js/*.*
@@ -63,7 +64,7 @@ lib/amd/src/popper.js
 lib/geopattern-php/
 lib/php-jwt/
 lib/babel-polyfill/
-lib/mdn-polyfills/
+lib/polyfills/
 lib/emoji-data/
 media/player/videojs/amd/src/video-lazy.js
 media/player/videojs/amd/src/Youtube-lazy.js
index bd39185..657bd77 100644 (file)
@@ -289,7 +289,13 @@ module.exports = function(grunt) {
         eslint: {
             // Even though warnings dont stop the build we don't display warnings by default because
             // at this moment we've got too many core warnings.
-            options: {quiet: !grunt.option('show-lint-warnings')},
+            // To display warnings call: grunt eslint --show-lint-warnings
+            // To fail on warnings call: grunt eslint --max-lint-warnings=0
+            // Also --max-lint-warnings=-1 can be used to display warnings but not fail.
+            options: {
+                quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
+                maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
+            },
             amd: {src: files ? files : amdSrc},
             // Check YUI module source files.
             yui: {src: files ? files : yuiSrc},
@@ -536,12 +542,8 @@ module.exports = function(grunt) {
         formatter.printResults(results);
 
         // Report on the results.
-        // We exit 1 if there is at least one error, otherwise we exit cleanly.
-        if (results.some(result => result.errors.length > 0)) {
-            done(1);
-        } else {
-            done(0);
-        }
+        // The done function takes a bool whereby a falsey statement causes the task to fail.
+        done(results.every(result => result.errors.length === 0));
     };
 
     tasks.startup = function() {
diff --git a/admin/cli/checks.php b/admin/cli/checks.php
new file mode 100644 (file)
index 0000000..40deb4d
--- /dev/null
@@ -0,0 +1,171 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * CLI tool for system checks
+ *
+ * @package    core
+ * @category   check
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+
+require(__DIR__ . '/../../config.php');
+require_once($CFG->libdir.'/clilib.php');
+
+use core\check\result;
+
+list($options, $unrecognized) = cli_get_params([
+    'help'    => false,
+    'filter'  => '',
+    'type'    => 'status',
+    'verbose' => false,
+], [
+    'h' => 'help',
+    'f' => 'filter',
+    'v' => 'verbose',
+    't' => 'type',
+]);
+
+if ($unrecognized) {
+    $unrecognized = implode("\n  ", $unrecognized);
+    cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
+}
+
+$checks = \core\check\manager::get_checks($options['type']);
+$types = join(', ', \core\check\manager::TYPES);
+
+$help = "Run Moodle system checks
+
+Options:
+ -h, --help      Print out this help
+ -f, --filter    Filter to a subset of checks
+ -t, --type      Which set of checks? Defaults to 'status'
+                 One of $types
+ -v, --verbose   Show details of all checks, not just failed checks
+
+Example:
+
+  sudo -u www-data php admin/cli/checks.php
+  sudo -u www-data php admin/cli/checks.php -v
+  sudo -u www-data php admin/cli/checks.php -v --filter=environment
+
+";
+
+if ($options['help']) {
+    echo $help;
+    die();
+}
+
+$filter = $options['filter'];
+if ($filter) {
+    $checks = array_filter($checks, function($check, $key) use ($filter) {
+        $ref = $check->get_ref();
+        return (strpos($ref, $filter) !== false);
+    }, 1);
+}
+
+// These shell exit codes and labels align with the NRPE standard.
+$exitcodes = [
+    result::NA        => 0,
+    result::OK        => 0,
+    result::INFO      => 0,
+    result::UNKNOWN   => 3,
+    result::WARNING   => 1,
+    result::ERROR     => 2,
+    result::CRITICAL  => 2,
+];
+$exitlabel = [
+    result::NA        => 'OK',
+    result::OK        => 'OK',
+    result::INFO      => 'OK',
+    result::UNKNOWN   => 'UNKNOWN',
+    result::WARNING   => 'WARNING',
+    result::ERROR     => 'CRITICAL',
+    result::CRITICAL  => 'CRITICAL',
+];
+
+$format = "%      10s| % -60s\n";
+$spacer = "----------+--------------------------------------------------------------------\n";
+$prefix = '          |';
+
+$output = '';
+$header = $exitlabel[result::OK] . ': ' . get_string('checksok', '', $options['type']) . "\n";
+$exitcode = $exitcodes[result::OK];
+
+foreach ($checks as $check) {
+    $ref = $check->get_ref();
+    $result = $check->get_result();
+
+    $status = $result->get_status();
+    $checkexitcode = $exitcodes[$status];
+
+    // Summary is treated as html.
+    $summary = $result->get_summary();
+    $summary = html_to_text($summary, 60, false);
+
+    if ($checkexitcode > $exitcode) {
+        $exitcode = $checkexitcode;
+        $header = $exitlabel[$status] . ': ' . $check->get_name() . " (" . $check->get_ref() . ")\n";
+    }
+
+    if (empty($messages[$status])) {
+        $messages[$status] = $result;
+    }
+
+    $len = strlen(get_string('status' . $status));
+
+    if ($options['verbose'] ||
+        $status == result::WARNING ||
+        $status == result::CRITICAL ||
+        $status == result::ERROR) {
+
+        $output .= sprintf(
+            $format,
+            $OUTPUT->check_result($result),
+            sprintf('%s (%s)', $check->get_name(), $ref)
+        );
+
+        $summary = str_replace("\n", "\n" . $prefix . '     ', $summary);
+        $output .= sprintf( $format, '', '    ' . $summary);
+
+        if ($options['verbose']) {
+            $actionlink = $check->get_action_link();
+            if ($actionlink) {
+                $output .= sprintf( $format, '', '    ' . $actionlink->url);
+            }
+            $output .= sprintf( $format, '', '');
+        }
+    }
+}
+
+// Print NRPE header.
+print $header;
+
+// Only show the table header if there is anything to show.
+if ($output) {
+    print sprintf($format,
+        get_string('status'). ' ',
+        get_string('check')
+    ) .  $spacer;
+    print $output;
+}
+
+// NRPE shell exit code.
+exit($exitcode);
+
diff --git a/admin/contentbank.php b/admin/contentbank.php
new file mode 100644 (file)
index 0000000..da29e6b
--- /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/>.
+
+/**
+ * Content bank and its plugins settings.
+ *
+ * @package    core
+ * @subpackage contentbank
+ * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+
+$action = required_param('action', PARAM_ALPHANUMEXT);
+$name   = required_param('name', PARAM_PLUGIN);
+
+$syscontext = context_system::instance();
+$PAGE->set_url('/admin/contentbank.php');
+$PAGE->set_context($syscontext);
+
+require_admin();
+require_sesskey();
+
+$return = new moodle_url('/admin/settings.php', array('section' => 'managecontentbanktypes'));
+
+$plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
+$sortorder = array_flip(array_keys($plugins));
+
+if (!isset($plugins[$name])) {
+    print_error('contenttypenotfound', 'error', $return, $name);
+}
+
+switch ($action) {
+    case 'disable':
+        if ($plugins[$name]->is_enabled()) {
+            set_config('disabled', 1, 'contentbank_'. $name);
+        }
+        break;
+    case 'enable':
+        if (!$plugins[$name]->is_enabled()) {
+            unset_config('disabled', 'contentbank_'. $name);
+        }
+        break;
+    case 'up':
+        if ($sortorder[$name]) {
+            $currentindex = $sortorder[$name];
+            $seq = array_keys($plugins);
+            $seq[$currentindex] = $seq[$currentindex - 1];
+            $seq[$currentindex - 1] = $name;
+            set_config('contentbank_plugins_sortorder', implode(',', $seq));
+        }
+        break;
+    case 'down':
+        if ($sortorder[$name] < count($sortorder) - 1) {
+            $currentindex = $sortorder[$name];
+            $seq = array_keys($plugins);
+            $seq[$currentindex] = $seq[$currentindex + 1];
+            $seq[$currentindex + 1] = $name;
+            set_config('contentbank_plugins_sortorder', implode(',', $seq));
+        }
+        break;
+}
+core_plugin_manager::reset_caches();
+$cache = cache::make('core', 'contentbank_enabled_extensions');
+$cache->purge();
+$cache = cache::make('core', 'contentbank_context_extensions');
+$cache->purge();
+
+redirect($return);
index c391089..ee3b2e3 100644 (file)
@@ -843,8 +843,9 @@ $errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED');
 $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);
+
+$expectedfrequency = $CFG->expectedcronfrequency ?? MINSECS;
+$croninfrequent = !$cronoverdue && ($lastcroninterval > ($expectedfrequency + MINSECS) || $lastcron < time() - $expectedfrequency);
 $dbproblems = $DB->diagnose();
 $maintenancemode = !empty($CFG->maintenance_enabled);
 
index 4ab7754..f904352 100644 (file)
@@ -601,19 +601,9 @@ class core_admin_renderer extends plugin_renderer_base {
             return '';
         }
 
-        if (empty($CFG->cronclionly)) {
-            $url = new moodle_url('/admin/cron.php');
-            if (!empty($CFG->cronremotepassword)) {
-                $url = new moodle_url('/admin/cron.php', array('password' => $CFG->cronremotepassword));
-            }
-
-            return $this->warning(get_string('cronwarning', 'admin', $url->out()) . '&nbsp;' .
-                    $this->help_icon('cron', 'admin'));
-        }
-
-        // $CFG->cronclionly is not empty: cron can run only from CLI.
-        return $this->warning(get_string('cronwarningcli', 'admin') . '&nbsp;' .
-                $this->help_icon('cron', 'admin'));
+        $check = new \tool_task\check\cronrunning();
+        $result = $check->get_result();
+        return $this->warning($result->get_summary() . '&nbsp;' . $this->help_icon('cron', 'admin'));
     }
 
     /**
@@ -629,9 +619,9 @@ class core_admin_renderer extends plugin_renderer_base {
             return '';
         }
 
-        $expectedfrequency = $CFG->expectedcronfrequency ?? 200;
-        return $this->warning(get_string('croninfrequent', 'admin', $expectedfrequency) . '&nbsp;' .
-                $this->help_icon('cron', 'admin'));
+        $check = new \tool_task\check\cronrunning();
+        $result = $check->get_result();
+        return $this->warning($result->get_summary() . '&nbsp;' . $this->help_icon('cron', 'admin'));
     }
 
     /**
index 0ea5193..2451390 100644 (file)
@@ -100,10 +100,11 @@ if (($hassiteconfig || has_any_capability(array(
             new lang_string('allowexternalbackpack', 'badges'),
             new lang_string('allowexternalbackpack_desc', 'badges'), 1));
 
+    $bp = $DB->get_record('badge_external_backpack', ['backpackweburl' => BADGRIO_BACKPACKWEBURL]);
     $backpacksettings->add(new admin_setting_configselect('badges_site_backpack',
             new lang_string('sitebackpack', 'badges'),
             new lang_string('sitebackpack_help', 'badges'),
-            1, $choices));
+            $bp->id, $choices));
 
     $warning = badges_verify_site_backpack();
     if (!empty($warning)) {
index 6b3848b..278d4f3 100644 (file)
@@ -657,6 +657,19 @@ if ($hassiteconfig) {
     }
 }
 
+// Content bank content types.
+if ($hassiteconfig) {
+    $ADMIN->add('modules', new admin_category('contenbanksettings', new lang_string('contentbank')));
+    $temp = new admin_settingpage('managecontentbanktypes', new lang_string('managecontentbanktypes'));
+    $temp->add(new admin_setting_managecontentbankcontenttypes());
+    $ADMIN->add('contenbanksettings', $temp);
+    $plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
+    foreach ($plugins as $plugin) {
+        /** @var \core\plugininfo\contentbank $plugin */
+        $plugin->load_settings($ADMIN, 'contenbanksettings', $hassiteconfig);
+    }
+}
+
 /// Add all local plugins - must be always last!
 if ($hassiteconfig) {
     $ADMIN->add('modules', new admin_category('localplugins', new lang_string('localplugins')));
index 0fb5206..796f323 100644 (file)
@@ -62,6 +62,8 @@ if (null !== $logid) {
 $renderer = $PAGE->get_renderer('tool_task');
 
 echo $OUTPUT->header();
+
+// Output the search form.
 echo $OUTPUT->render_from_template('core_admin/tasklogs', (object) [
     'action' => $pageurl->out(),
     'filter' => $filter,
@@ -84,6 +86,7 @@ echo $OUTPUT->render_from_template('core_admin/tasklogs', (object) [
     ],
 ]);
 
+// Output any matching logs.
 $table = new \core_admin\task_log_table($filter, $result);
 $table->baseurl = $pageurl;
 $table->out(100, false);
index c3180a2..bb180b6 100644 (file)
@@ -17,7 +17,7 @@
 {{!
     @template core_admin/tasklogs
 
-    Task Logs template.
+    This is the template for the search form which appears above the task logs report.
 }}
 <form class="form-inline" method="GET" action="{{{action}}}">
     <label class="sr-only" for="tasklog-filter">{{#str}}filter{{/str}}</label>
index 7d0db03..b1f9c58 100644 (file)
@@ -46,7 +46,8 @@ if ($data) {
     $emailuser->email = $data->recipient;
     $emailuser->id = -99;
 
-    $subject = get_string('testoutgoingmailconf_subject', 'admin', $SITE->fullname);
+    $subject = get_string('testoutgoingmailconf_subject', 'admin',
+        format_string($SITE->fullname, true, ['context' => context_system::instance()]));
     $messagetext = get_string('testoutgoingmailconf_message', 'admin');
 
     // Manage Moodle debugging options.
index edd165d..0855ed1 100644 (file)
@@ -27,8 +27,7 @@ namespace tool_analytics\output;
 defined('MOODLE_INTERNAL') || die();
 
 use plugin_renderer_base;
-use templatable;
-use renderable;
+
 
 /**
  * Renderer class.
@@ -74,14 +73,12 @@ class renderer extends plugin_renderer_base {
      * @return string HTML
      */
     public function render_evaluate_results($results, $logs = array()) {
-        global $OUTPUT;
-
         $output = '';
 
         foreach ($results as $timesplittingid => $result) {
 
             if (!CLI_SCRIPT) {
-                $output .= $OUTPUT->box_start('generalbox mb-3');
+                $output .= $this->output->box_start('generalbox mb-3');
             }
 
             // Check that the array key is a string, not all results depend on time splitting methods (e.g. general errors).
@@ -90,47 +87,48 @@ class renderer extends plugin_renderer_base {
                 $langstrdata = (object)array('name' => $timesplitting->get_name(), 'id' => $timesplittingid);
 
                 if (CLI_SCRIPT) {
-                    $output .= $OUTPUT->heading(get_string('scheduledanalysisresultscli', 'tool_analytics', $langstrdata), 3);
+                    $output .= $this->output->heading(get_string('scheduledanalysisresultscli', 'tool_analytics', $langstrdata), 3);
                 } else {
-                    $output .= $OUTPUT->heading(get_string('scheduledanalysisresults', 'tool_analytics', $langstrdata), 3);
+                    $output .= $this->output->heading(get_string('scheduledanalysisresults', 'tool_analytics', $langstrdata), 3);
                 }
             }
 
             if ($result->status == 0) {
-                $output .= $OUTPUT->notification(get_string('goodmodel', 'tool_analytics'),
+                $output .= $this->output->notification(get_string('goodmodel', 'tool_analytics'),
                     \core\output\notification::NOTIFY_SUCCESS);
             } else if ($result->status === \core_analytics\model::NO_DATASET) {
-                $output .= $OUTPUT->notification(get_string('nodatatoevaluate', 'tool_analytics'),
+                $output .= $this->output->notification(get_string('nodatatoevaluate', 'tool_analytics'),
                     \core\output\notification::NOTIFY_WARNING);
             }
 
             if (isset($result->score)) {
                 // Score.
-                $output .= $OUTPUT->heading(get_string('accuracy', 'tool_analytics') . ': ' .
+                $output .= $this->output->heading(get_string('accuracy', 'tool_analytics') . ': ' .
                     round(floatval($result->score), 4) * 100  . '%', 4);
             }
 
             if (!empty($result->info)) {
                 foreach ($result->info as $message) {
-                    $output .= $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING);
+                    $output .= $this->output->notification($message, \core\output\notification::NOTIFY_WARNING);
                 }
             }
 
             if (!CLI_SCRIPT) {
-                $output .= $OUTPUT->box_end();
+                $output .= $this->output->box_end();
             }
         }
 
         // Info logged during evaluation.
         if (!empty($logs) && debugging()) {
-            $output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 3);
+            $output .= $this->output->heading(get_string('extrainfo', 'tool_analytics'), 3);
             foreach ($logs as $log) {
-                $output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
+                $output .= $this->output->notification($log, \core\output\notification::NOTIFY_WARNING);
             }
         }
 
         if (!CLI_SCRIPT) {
-            $output .= $OUTPUT->single_button(new \moodle_url('/admin/tool/analytics/index.php'), get_string('continue'), 'get');
+            $output .= $this->output->single_button(new \moodle_url('/admin/tool/analytics/index.php'),
+                    get_string('continue'), 'get');
         }
 
         return $output;
@@ -147,62 +145,68 @@ class renderer extends plugin_renderer_base {
      * @return string HTML
      */
     public function render_get_predictions_results($trainresults = false, $trainlogs = array(), $predictresults = false, $predictlogs = array()) {
-        global $OUTPUT;
-
         $output = '';
 
         if ($trainresults || (!empty($trainlogs) && debugging())) {
-            $output .= $OUTPUT->heading(get_string('trainingresults', 'tool_analytics'), 3);
+            $output .= $this->output->heading(get_string('trainingresults', 'tool_analytics'), 3);
         }
 
         if ($trainresults) {
             if ($trainresults->status == 0) {
-                $output .= $OUTPUT->notification(get_string('trainingprocessfinished', 'tool_analytics'),
+                $output .= $this->output->notification(
+                        get_string('trainingprocessfinished', 'tool_analytics'),
                     \core\output\notification::NOTIFY_SUCCESS);
             } else if ($trainresults->status === \core_analytics\model::NO_DATASET ||
                     $trainresults->status === \core_analytics\model::NOT_ENOUGH_DATA) {
-                $output .= $OUTPUT->notification(get_string('nodatatotrain', 'tool_analytics'),
+                $output .= $this->output->notification(
+                        get_string('nodatatotrain', 'tool_analytics'),
                     \core\output\notification::NOTIFY_WARNING);
             } else {
-                $output .= $OUTPUT->notification(get_string('generalerror', 'tool_analytics', $trainresults->status),
+                $output .= $this->output->notification(
+                        get_string('generalerror', 'tool_analytics', $trainresults->status),
                     \core\output\notification::NOTIFY_ERROR);
             }
         }
 
         if (!empty($trainlogs) && debugging()) {
-            $output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 4);
+            $output .= $this->output->heading(get_string('extrainfo', 'tool_analytics'), 4);
             foreach ($trainlogs as $log) {
-                $output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
+                $output .= $this->output->notification($log, \core\output\notification::NOTIFY_WARNING);
             }
         }
 
         if ($predictresults || (!empty($predictlogs) && debugging())) {
-            $output .= $OUTPUT->heading(get_string('predictionresults', 'tool_analytics'), 3, 'main mt-3');
+            $output .= $this->output->heading(
+                    get_string('predictionresults', 'tool_analytics'), 3, 'main mt-3');
         }
 
         if ($predictresults) {
             if ($predictresults->status == 0) {
-                $output .= $OUTPUT->notification(get_string('predictionprocessfinished', 'tool_analytics'),
+                $output .= $this->output->notification(
+                        get_string('predictionprocessfinished', 'tool_analytics'),
                     \core\output\notification::NOTIFY_SUCCESS);
             } else if ($predictresults->status === \core_analytics\model::NO_DATASET ||
                     $predictresults->status === \core_analytics\model::NOT_ENOUGH_DATA) {
-                $output .= $OUTPUT->notification(get_string('nodatatopredict', 'tool_analytics'),
+                $output .= $this->output->notification(
+                        get_string('nodatatopredict', 'tool_analytics'),
                     \core\output\notification::NOTIFY_WARNING);
             } else {
-                $output .= $OUTPUT->notification(get_string('generalerror', 'tool_analytics', $predictresults->status),
+                $output .= $this->output->notification(
+                        get_string('generalerror', 'tool_analytics', $predictresults->status),
                     \core\output\notification::NOTIFY_ERROR);
             }
         }
 
         if (!empty($predictlogs) && debugging()) {
-            $output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 4);
+            $output .= $this->output->heading(get_string('extrainfo', 'tool_analytics'), 4);
             foreach ($predictlogs as $log) {
-                $output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
+                $output .= $this->output->notification($log, \core\output\notification::NOTIFY_WARNING);
             }
         }
 
         if (!CLI_SCRIPT) {
-            $output .= $OUTPUT->single_button(new \moodle_url('/admin/tool/analytics/index.php'), get_string('continue'), 'get');
+            $output .= $this->output->single_button(new \moodle_url('/admin/tool/analytics/index.php'),
+                    get_string('continue'), 'get');
         }
 
         return $output;
@@ -236,17 +240,18 @@ class renderer extends plugin_renderer_base {
      * @return string HTML
      */
     public function render_analytics_disabled() {
-        global $OUTPUT, $PAGE, $FULLME;
+        global $FULLME;
 
-        $PAGE->set_url($FULLME);
-        $PAGE->set_title(get_string('pluginname', 'tool_analytics'));
-        $PAGE->set_heading(get_string('pluginname', 'tool_analytics'));
+        $this->page->set_url($FULLME);
+        $this->page->set_title(get_string('pluginname', 'tool_analytics'));
+        $this->page->set_heading(get_string('pluginname', 'tool_analytics'));
 
-        $output = $OUTPUT->header();
-        $output .= $OUTPUT->notification(get_string('analyticsdisabled', 'analytics'), \core\output\notification::NOTIFY_INFO);
+        $output = $this->output->header();
+        $output .= $this->output->notification(get_string('analyticsdisabled', 'analytics'),
+                \core\output\notification::NOTIFY_INFO);
         $output .= \html_writer::tag('a', get_string('continue'), ['class' => 'btn btn-primary',
             'href' => (new \moodle_url('/'))->out()]);
-        $output .= $OUTPUT->footer();
+        $output .= $this->output->footer();
 
         return $output;
     }
index f510cd2..a6ba759 100644 (file)
Binary files a/admin/tool/dataprivacy/amd/build/myrequestactions.min.js and b/admin/tool/dataprivacy/amd/build/myrequestactions.min.js differ
index 6d17dee..c9f78ed 100644 (file)
Binary files a/admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map and b/admin/tool/dataprivacy/amd/build/myrequestactions.min.js.map differ
index 5ec631e..54f94fb 100644 (file)
@@ -28,8 +28,9 @@ define([
     'core/str',
     'core/modal_factory',
     'core/modal_events',
-    'core/templates'],
-function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {
+    'core/templates',
+    'core/pending'],
+function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates, Pending) {
 
     /**
      * List of action selectors.
@@ -118,6 +119,7 @@ function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {
         });
 
         $(ACTIONS.CONTACT_DPO).click(function(e) {
+            var pendingPromise = new Pending('dataprivacy/crud:initModal:contactdpo');
             e.preventDefault();
 
             var replyToEmail = $(this).data('replytoemail');
@@ -146,9 +148,12 @@ function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {
                     type: ModalFactory.types.SAVE_CANCEL,
                     large: true
                 });
-            }).done(function(modal) {
+            }).then(function(modal) {
                 modal.setSaveButtonText(sendButtonText);
 
+                // Show the modal!
+                modal.show();
+
                 // Handle send event.
                 modal.getRoot().on(ModalEvents.save, function(e) {
                     var message = $('#message').val().trim();
@@ -169,9 +174,9 @@ function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {
                     modal.destroy();
                 });
 
-                // Show the modal!
-                modal.show();
-            }).fail(Notification.exception);
+                return;
+            }).then(pendingPromise.resolve)
+            .catch(Notification.exception);
         });
     };
 
diff --git a/admin/tool/task/classes/check/adhocqueue.php b/admin/tool/task/classes/check/adhocqueue.php
new file mode 100644 (file)
index 0000000..85f98b8
--- /dev/null
@@ -0,0 +1,93 @@
+<?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/>.
+
+/**
+ * Ad hoc queue checks
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_task\check;
+
+defined('MOODLE_INTERNAL') || die();
+
+use core\check\check;
+use core\check\result;
+
+/**
+ * Ad hoc queue checks
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class adhocqueue extends check {
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        global $CFG;
+        $this->id = 'adhocqueue';
+        $this->name = get_string('checkadhocqueue', 'tool_task');
+    }
+
+    /**
+     * Return result
+     * @return result
+     */
+    public function get_result() : result {
+        global $DB, $CFG;
+
+        $stats = $DB->get_record_sql('
+            SELECT count(*) cnt,
+                   MAX(? - nextruntime) age
+              FROM {task_adhoc}', [time()]);
+
+        $status = result::OK;
+        $summary = get_string('adhocempty', 'tool_task');
+        $details = '';
+
+        if ($stats->cnt > 0) {
+            // A large queue size by itself is not an issue, only when tasks
+            // are not being processed in a timely fashion is it an issue.
+            $status = result::INFO;
+            $summary = get_string('adhocqueuesize', 'tool_task', $stats->cnt);
+        }
+
+        $max = $CFG->adhoctaskagewarn ?? 10 * MINSECS;
+        if ($stats->age > $max) {
+            $status = result::WARNING;
+            $summary = get_string('adhocqueueold', 'tool_task', [
+                'age' => format_time($stats->age),
+                'max' => format_time($max),
+            ]);
+        }
+
+        $max = $CFG->adhoctaskageerror ?? 4 * HOURSECS;
+        if ($stats->age > $max) {
+            $status = result::ERROR;
+            $summary = get_string('adhocqueueold', 'tool_task', [
+                'age' => format_time($stats->age),
+                'max' => format_time($max),
+            ]);
+        }
+
+        return new result($status, $summary, $details);
+    }
+}
diff --git a/admin/tool/task/classes/check/cronrunning.php b/admin/tool/task/classes/check/cronrunning.php
new file mode 100644 (file)
index 0000000..46aa690
--- /dev/null
@@ -0,0 +1,118 @@
+<?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/>.
+
+/**
+ * Cron running check
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_task\check;
+
+defined('MOODLE_INTERNAL') || die();
+
+use core\check\check;
+use core\check\result;
+/**
+ * Cron running check
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class cronrunning extends check {
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        global $CFG;
+        $this->id = 'cronrunning';
+        $this->name = get_string('checkcronrunning', 'tool_task');
+        if (empty($CFG->cronclionly)) {
+            $this->actionlink = new \action_link(
+                new \moodle_url('/admin/cron.php'),
+                get_string('cron', 'admin'));
+        }
+    }
+
+    /**
+     * Return result
+     * @return result
+     */
+    public function get_result() : result {
+        global $CFG;
+
+        // Eventually this should replace cron_overdue_warning and
+        // cron_infrequent_warning.
+        $lastcron = get_config('tool_task', 'lastcronstart');
+        $expectedfrequency = $CFG->expectedcronfrequency ?? MINSECS;
+
+        $delta = time() - $lastcron;
+
+        $lastcroninterval = get_config('tool_task', 'lastcroninterval');
+
+        $formatdelta    = format_time($delta);
+        $formatexpected = format_time($expectedfrequency);
+        $formatinterval = format_time($lastcroninterval);
+
+        $details = format_time($delta);
+
+        if ($delta > $expectedfrequency + MINSECS) {
+            $status = result::WARNING;
+
+            if ($delta > DAYSECS) {
+                $status = result::CRITICAL;
+            }
+
+            if (empty($lastcron)) {
+                $summary = get_string('cronwarningnever', 'admin', [
+                    'expected' => $formatexpected,
+                ]);
+            } else if (empty($CFG->cronclionly)) {
+                $url = new \moodle_url('/admin/cron.php');
+                $summary = get_string('cronwarning', 'admin', [
+                    'url' => $url->out(),
+                    'actual'   => $formatdelta,
+                    'expected' => $formatexpected,
+                ]);
+            } else {
+                $summary = get_string('cronwarningcli', 'admin', [
+                    'actual'   => $formatdelta,
+                    'expected' => $formatexpected,
+                ]);
+            }
+            return new result($status, $summary, $details);
+        }
+
+        if ($lastcroninterval > $expectedfrequency) {
+            $status = result::WARNING;
+            $summary = get_string('croninfrequent', 'admin', [
+                'actual'   => $formatinterval,
+                'expected' => $formatexpected,
+            ]);
+            return new result($status, $summary, $details);
+        }
+
+        $status = result::OK;
+        $summary = get_string('cronok', 'tool_task');
+
+        return new result($status, $summary, $details);
+    }
+}
+
diff --git a/admin/tool/task/classes/check/maxfaildelay.php b/admin/tool/task/classes/check/maxfaildelay.php
new file mode 100644 (file)
index 0000000..019aa75
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Task fail delay check
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_task\check;
+
+defined('MOODLE_INTERNAL') || die();
+
+use core\check\check;
+use core\check\result;
+
+/**
+ * Task fail delay check
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class maxfaildelay extends check {
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        global $CFG;
+        $this->id = 'cronfaildelay';
+        $this->name = get_string('checkmaxfaildelay', 'tool_task');
+        $this->actionlink = new \action_link(
+            new \moodle_url('/admin/tool/task/scheduledtasks.php'),
+            get_string('scheduledtasks', 'tool_task'));
+    }
+
+    /**
+     * Return result
+     * @return result
+     */
+    public function get_result() : result {
+        global $CFG;
+
+        $status = result::OK;
+        $summary = get_string('tasknofailures', 'tool_task');
+        $details = '';
+        $failures = 0;
+        $maxdelay = 0;
+
+        $tasks = \core\task\manager::get_all_scheduled_tasks();
+        foreach ($tasks as $task) {
+            if ($task->get_disabled()) {
+                continue;
+            }
+            $faildelay = $task->get_fail_delay();
+            if ($faildelay > $maxdelay) {
+                $maxdelay = $faildelay;
+            }
+            if ($faildelay > 0) {
+                $failures++;
+                $details .= get_string('faildelay', 'tool_task') . ': ' . format_time($faildelay);
+                $details .= ' - ' . $task->get_name() . ' (' .get_class($task) . ")<br>";
+            }
+        }
+
+        if ($failures > 0) {
+            // Intermittent failures are not yet a warning.
+            $status = result::INFO;
+            $summary = get_string('taskfailures', 'tool_task', $failures);
+        }
+        if ($maxdelay > 5 * MINSECS) {
+            $status = result::WARNING;
+        }
+        if ($maxdelay > 4 * HOURSECS) {
+            $status = result::ERROR;
+        }
+
+        return new result($status, $summary, $details);
+    }
+}
index 145b59d..1a76a3b 100644 (file)
@@ -34,46 +34,59 @@ require_once($CFG->libdir.'/formslib.php');
  */
 class tool_task_edit_scheduled_task_form extends moodleform {
     public function definition() {
+        global $PAGE;
+
         $mform = $this->_form;
         /** @var \core\task\scheduled_task $task */
         $task = $this->_customdata;
+        $defaulttask = \core\task\manager::get_default_scheduled_task(get_class($task), false);
+        $renderer = $PAGE->get_renderer('tool_task');
 
-        $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
-        $plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled();
-
-        $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : get_string('never');
-        $nextrun = $task->get_next_run_time();
-        if ($plugindisabled) {
-            $nextrun = get_string('plugindisabled', 'tool_task');
-        } else if ($task->get_disabled()) {
-            $nextrun = get_string('taskdisabled', 'tool_task');
-        } else if ($nextrun > time()) {
-            $nextrun = userdate($nextrun);
-        } else {
-            $nextrun = get_string('asap', 'tool_task');
-        }
-        $mform->addElement('static', 'lastrun', get_string('lastruntime', 'tool_task'), $lastrun);
-        $mform->addElement('static', 'nextrun', get_string('nextruntime', 'tool_task'), $nextrun);
+        $mform->addElement('static', 'lastrun', get_string('lastruntime', 'tool_task'),
+                $renderer->last_run_time($task));
+
+        $mform->addElement('static', 'nextrun', get_string('nextruntime', 'tool_task'),
+                $renderer->next_run_time($task));
 
-        $mform->addElement('text', 'minute', get_string('taskscheduleminute', 'tool_task'));
+        $mform->addGroup([
+                $mform->createElement('text', 'minute'),
+                $mform->createElement('static', 'minutedefault', '',
+                        get_string('defaultx', 'tool_task', $defaulttask->get_minute())),
+            ], 'minutegroup', get_string('taskscheduleminute', 'tool_task'), null, false);
         $mform->setType('minute', PARAM_RAW);
-        $mform->addHelpButton('minute', 'taskscheduleminute', 'tool_task');
+        $mform->addHelpButton('minutegroup', 'taskscheduleminute', 'tool_task');
 
-        $mform->addElement('text', 'hour', get_string('taskschedulehour', 'tool_task'));
+        $mform->addGroup([
+                $mform->createElement('text', 'hour'),
+                $mform->createElement('static', 'hourdefault', '',
+                        get_string('defaultx', 'tool_task', $defaulttask->get_hour())),
+        ], 'hourgroup', get_string('taskschedulehour', 'tool_task'), null, false);
         $mform->setType('hour', PARAM_RAW);
-        $mform->addHelpButton('hour', 'taskschedulehour', 'tool_task');
+        $mform->addHelpButton('hourgroup', 'taskschedulehour', 'tool_task');
 
-        $mform->addElement('text', 'day', get_string('taskscheduleday', 'tool_task'));
+        $mform->addGroup([
+                $mform->createElement('text', 'day'),
+                $mform->createElement('static', 'daydefault', '',
+                        get_string('defaultx', 'tool_task', $defaulttask->get_day())),
+        ], 'daygroup', get_string('taskscheduleday', 'tool_task'), null, false);
         $mform->setType('day', PARAM_RAW);
-        $mform->addHelpButton('day', 'taskscheduleday', 'tool_task');
+        $mform->addHelpButton('daygroup', 'taskscheduleday', 'tool_task');
 
-        $mform->addElement('text', 'month', get_string('taskschedulemonth', 'tool_task'));
+        $mform->addGroup([
+                $mform->createElement('text', 'month'),
+                $mform->createElement('static', 'monthdefault', '',
+                        get_string('defaultx', 'tool_task', $defaulttask->get_month())),
+        ], 'monthgroup', get_string('taskschedulemonth', 'tool_task'), null, false);
         $mform->setType('month', PARAM_RAW);
-        $mform->addHelpButton('month', 'taskschedulemonth', 'tool_task');
+        $mform->addHelpButton('monthgroup', 'taskschedulemonth', 'tool_task');
 
-        $mform->addElement('text', 'dayofweek', get_string('taskscheduledayofweek', 'tool_task'));
+        $mform->addGroup([
+                $mform->createElement('text', 'dayofweek'),
+                $mform->createElement('static', 'dayofweekdefault', '',
+                        get_string('defaultx', 'tool_task', $defaulttask->get_day_of_week())),
+        ], 'dayofweekgroup', get_string('taskscheduledayofweek', 'tool_task'), null, false);
         $mform->setType('dayofweek', PARAM_RAW);
-        $mform->addHelpButton('dayofweek', 'taskscheduledayofweek', 'tool_task');
+        $mform->addHelpButton('dayofweekgroup', 'taskscheduledayofweek', 'tool_task');
 
         $mform->addElement('advcheckbox', 'disabled', get_string('disabled', 'tool_task'));
         $mform->addHelpButton('disabled', 'disabled', 'tool_task');
@@ -111,7 +124,7 @@ class tool_task_edit_scheduled_task_form extends moodleform {
         $fields = array('minute', 'hour', 'day', 'month', 'dayofweek');
         foreach ($fields as $field) {
             if (!self::validate_fields($field, $data[$field])) {
-                $error[$field] = get_string('invaliddata', 'core_error');
+                $error[$field . 'group'] = get_string('invaliddata', 'core_error');
             }
         }
         return $error;
index 8f41b45..8f357b8 100644 (file)
@@ -39,13 +39,16 @@ if (!$task) {
     print_error('cannotfindinfo', 'error', $taskname);
 }
 
+$returnurl = new moodle_url('/admin/tool/task/scheduledtasks.php',
+        ['lastchanged' => get_class($task)]);
+
 // If actually doing the clear, then carry out the task and redirect to the scheduled task page.
 if (optional_param('confirm', 0, PARAM_INT)) {
     require_sesskey();
 
     \core\task\manager::clear_fail_delay($task);
 
-    redirect(new moodle_url('/admin/tool/task/scheduledtasks.php'));
+    redirect($returnurl);
 }
 
 // Start output.
@@ -60,9 +63,8 @@ echo $OUTPUT->header();
 // they confirm.
 echo $OUTPUT->confirm(get_string('clearfaildelay_confirm', 'tool_task', $task->get_name()),
         new single_button(new moodle_url('/admin/tool/task/clear_fail_delay.php',
-                array('task' => $taskname, 'confirm' => 1, 'sesskey' => sesskey())),
+                ['task' => $taskname, 'confirm' => 1, 'sesskey' => sesskey()]),
                 get_string('clear')),
-        new single_button(new moodle_url('/admin/tool/task/scheduledtasks.php'),
-                get_string('cancel'), false));
+        new single_button($returnurl, get_string('cancel'), false));
 
 echo $OUTPUT->footer();
index 76ab5da..9ccd292 100644 (file)
  */
 
 $string['asap'] = 'ASAP';
+$string['adhocempty'] = 'Adhoc task queue is empty';
+$string['adhocqueuesize'] = 'Adhoc task queue has {$a} tasks';
+$string['adhocqueueold'] = 'Oldest task is {$a->age} which is more than {$a->max}';
 $string['backtoscheduledtasks'] = 'Back to scheduled tasks';
 $string['blocking'] = 'Blocking';
 $string['cannotfindthepathtothecli'] = 'Cannot find the path to the PHP CLI executable so task execution aborted. Set the \'Path to PHP CLI\' setting in Site administration / Server / System paths.';
+$string['checkadhocqueue'] = 'Adhoc task queue';
+$string['checkcronrunning'] = 'Cron running';
+$string['checkmaxfaildelay'] = 'Tasks max fail delay';
 $string['clearfaildelay_confirm'] = 'Are you sure you want to clear the fail delay for task \'{$a}\'? After clearing the delay, the task will run according to its normal schedule.';
 $string['component'] = 'Component';
 $string['corecomponent'] = 'Core';
+$string['cronok'] = 'Cron is running frequently';
 $string['default'] = 'Default';
+$string['defaultx'] = 'Default: {$a}';
 $string['disabled'] = 'Disabled';
 $string['disabled_help'] = 'Disabled scheduled tasks are not executed from cron, however they can still be executed manually via the CLI tool.';
 $string['edittaskschedule'] = 'Edit task schedule: {$a}';
 $string['enablerunnow'] = 'Allow \'Run now\' for scheduled tasks';
 $string['enablerunnow_desc'] = 'Allows administrators to run a single scheduled task immediately, rather than waiting for it to run as scheduled. The feature requires \'Path to PHP CLI\' (pathtophp) to be set in System paths. The task runs on the web server, so you may wish to disable this feature to avoid potential performance issues.';
 $string['faildelay'] = 'Fail delay';
+$string['fromcomponent'] = 'From component: {$a}';
 $string['lastruntime'] = 'Last run';
 $string['nextruntime'] = 'Next run';
 $string['plugindisabled'] = 'Plugin disabled';
@@ -49,7 +58,9 @@ $string['runpattern'] = 'Run pattern';
 $string['scheduledtasks'] = 'Scheduled tasks';
 $string['scheduledtaskchangesdisabled'] = 'Modifications to the list of scheduled tasks have been prevented in Moodle configuration';
 $string['taskdisabled'] = 'Task disabled';
+$string['taskfailures'] = 'There are {$a} task(s) failing';
 $string['tasklogs'] = 'Task logs';
+$string['tasknofailures'] = 'There are no tasks failing';
 $string['taskscheduleday'] = 'Day';
 $string['taskscheduleday_help'] = 'Day of month field for task schedule. The field uses the same format as unix cron. Some examples are:
 
diff --git a/admin/tool/task/lib.php b/admin/tool/task/lib.php
new file mode 100644 (file)
index 0000000..ae23257
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Task API status checks
+ *
+ * @package    tool_task
+ * @copyright  2020 Brendan Heywood (brendan@catalyst-au.net)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Add cron related service status checks
+ *
+ * @return array of check objects
+ */
+function tool_task_status_checks() : array {
+    return [
+        new \tool_task\check\cronrunning(),
+        new \tool_task\check\maxfaildelay(),
+        new \tool_task\check\adhocqueue(),
+    ];
+}
+
index 3afd20c..0a01d0a 100644 (file)
@@ -25,6 +25,9 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+use core\task\scheduled_task;
+
+
 /**
  * Implements the plugin renderer
  *
@@ -36,9 +39,10 @@ class tool_task_renderer extends plugin_renderer_base {
      * This function will render one beautiful table with all the scheduled tasks.
      *
      * @param \core\task\scheduled_task[] $tasks - list of all scheduled tasks.
+     * @param string $lastchanged (optional) the last task edited. Gets highlighted in teh table.
      * @return string HTML to output.
      */
-    public function scheduled_tasks_table($tasks) {
+    public function scheduled_tasks_table($tasks, $lastchanged = '') {
         global $CFG;
 
         $showloglink = \core\task\logmanager::has_log_report();
@@ -68,118 +72,205 @@ class tool_task_renderer extends plugin_renderer_base {
             $table->colclasses['3'] = 'hidden';
         }
 
-        $data = array();
+        $data = [];
         $yes = get_string('yes');
         $no = get_string('no');
-        $never = get_string('never');
-        $asap = get_string('asap', 'tool_task');
-        $disabledstr = get_string('taskdisabled', 'tool_task');
-        $plugindisabledstr = get_string('plugindisabled', 'tool_task');
-        $runnabletasks = tool_task\run_from_cli::is_runnable();
+        $canruntasks = tool_task\run_from_cli::is_runnable();
         foreach ($tasks as $task) {
+            $classname = get_class($task);
+            $defaulttask = \core\task\manager::get_default_scheduled_task($classname, false);
+
             $customised = $task->is_customised() ? $no : $yes;
             if (empty($CFG->preventscheduledtaskchanges)) {
-                $configureurl = new moodle_url('/admin/tool/task/scheduledtasks.php', array('action'=>'edit', 'task' => get_class($task)));
-                $editlink = $this->action_icon($configureurl, new pix_icon('t/edit', get_string('edittaskschedule', 'tool_task', $task->get_name())));
+                $configureurl = new moodle_url('/admin/tool/task/scheduledtasks.php',
+                        ['action' => 'edit', 'task' => $classname]);
+                $editlink = $this->output->action_icon($configureurl, new pix_icon('t/edit',
+                        get_string('edittaskschedule', 'tool_task', $task->get_name())));
             } else {
-                $editlink = $this->render(new pix_icon('t/locked', get_string('scheduledtaskchangesdisabled', 'tool_task')));
+                $editlink = $this->render(new pix_icon('t/locked',
+                        get_string('scheduledtaskchangesdisabled', 'tool_task')));
             }
 
             $loglink = '';
             if ($showloglink) {
-                $loglink = $this->action_icon(
-                    \core\task\logmanager::get_url_for_task_class(get_class($task)),
+                $loglink = $this->output->action_icon(
+                    \core\task\logmanager::get_url_for_task_class($classname),
                     new pix_icon('e/file-text', get_string('viewlogs', 'tool_task', $task->get_name())
                 ));
             }
 
-            $namecell = new html_table_cell($task->get_name() . "\n" . html_writer::tag('span', '\\'.get_class($task),
-                array('class' => 'task-class text-ltr')));
+            $namecell = new html_table_cell($task->get_name() . "\n" .
+                    html_writer::span('\\' . $classname, 'task-class text-ltr'));
             $namecell->header = true;
 
-            $component = $task->get_component();
-            $plugininfo = null;
-            list($type, $plugin) = core_component::normalize_component($component);
-            if ($type === 'core') {
-                $componentcell = new html_table_cell(get_string('corecomponent', 'tool_task'));
-            } else {
-                if ($plugininfo = core_plugin_manager::instance()->get_plugin_info($component)) {
-                    $plugininfo->init_display_name();
-                    $componentcell = new html_table_cell($plugininfo->displayname);
-                } else {
-                    $componentcell = new html_table_cell($component);
-                }
-            }
-
-            $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : $never;
-            $nextrun = $task->get_next_run_time();
-            $disabled = false;
-            if ($plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled()) {
-                $disabled = true;
-                $nextrun = $plugindisabledstr;
-            } else if ($task->get_disabled()) {
-                $disabled = true;
-                $nextrun = $disabledstr;
-            } else if ($nextrun > time()) {
-                $nextrun = userdate($nextrun);
-            } else {
-                $nextrun = $asap;
-            }
+            $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
+            $plugindisabled = $plugininfo && $plugininfo->is_enabled() === false &&
+                    !$task->get_run_if_component_disabled();
+            $disabled = $plugindisabled || $task->get_disabled();
 
             $runnow = '';
-            if ( ! $disabled && get_config('tool_task', 'enablerunnow') && $runnabletasks ) {
+            if (!$disabled && get_config('tool_task', 'enablerunnow') && $canruntasks ) {
                 $runnow = html_writer::div(html_writer::link(
                         new moodle_url('/admin/tool/task/schedule_task.php',
-                            array('task' => get_class($task))),
+                            ['task' => $classname]),
                         get_string('runnow', 'tool_task')), 'task-runnow');
             }
 
-            $clearfail = '';
+            $faildelaycell = new html_table_cell($task->get_fail_delay());
             if ($task->get_fail_delay()) {
-                $clearfail = html_writer::div(html_writer::link(
+                $faildelaycell->text .= html_writer::div(html_writer::link(
                         new moodle_url('/admin/tool/task/clear_fail_delay.php',
-                                array('task' => get_class($task), 'sesskey' => sesskey())),
+                                ['task' => $classname, 'sesskey' => sesskey()]),
                         get_string('clear')), 'task-clearfaildelay');
+                $faildelaycell->attributes['class'] = 'table-danger';
             }
 
-            $row = new html_table_row(array(
+            $row = new html_table_row([
                         $namecell,
-                        $componentcell,
+                        new html_table_cell($this->component_name($task->get_component())),
                         new html_table_cell($editlink),
                         new html_table_cell($loglink),
-                        new html_table_cell($lastrun . $runnow),
-                        new html_table_cell($nextrun),
-                        new html_table_cell($task->get_minute()),
-                        new html_table_cell($task->get_hour()),
-                        new html_table_cell($task->get_day()),
-                        new html_table_cell($task->get_day_of_week()),
-                        new html_table_cell($task->get_month()),
-                        new html_table_cell($task->get_fail_delay() . $clearfail),
-                        new html_table_cell($customised)));
-
-            // Cron-style values must always be LTR.
-            $row->cells[6]->attributes['class'] = 'text-ltr';
-            $row->cells[7]->attributes['class'] = 'text-ltr';
-            $row->cells[8]->attributes['class'] = 'text-ltr';
-            $row->cells[9]->attributes['class'] = 'text-ltr';
-            $row->cells[10]->attributes['class'] = 'text-ltr';
+                        new html_table_cell($this->last_run_time($task) . $runnow),
+                        new html_table_cell($this->next_run_time($task)),
+                        $this->time_cell($task->get_minute(), $defaulttask->get_minute()),
+                        $this->time_cell($task->get_hour(), $defaulttask->get_hour()),
+                        $this->time_cell($task->get_day(), $defaulttask->get_day()),
+                        $this->time_cell($task->get_day_of_week(), $defaulttask->get_day_of_week()),
+                        $this->time_cell($task->get_month(), $defaulttask->get_month()),
+                        $faildelaycell,
+                        new html_table_cell($customised)]);
 
+            $classes = [];
             if ($disabled) {
-                $row->attributes['class'] = 'disabled';
+                $classes[] = 'disabled';
+            }
+            if (get_class($task) == $lastchanged) {
+                $classes[] = 'table-primary';
             }
+            $row->attributes['class'] = implode(' ', $classes);
             $data[] = $row;
         }
         $table->data = $data;
+        if ($lastchanged) {
+            // IE does not support this, and the ancient version of Firefox we use for Behat
+            // has the method, but then errors on 'centre'. So, just try to scroll, and if it fails, don't care.
+            $this->page->requires->js_init_code(
+                    'try{document.querySelector("tr.table-primary").scrollIntoView({block: "center"});}catch(e){}');
+        }
         return html_writer::table($table);
     }
 
+    /**
+     * Nicely display the name of a component, with its disabled status and internal name.
+     *
+     * @param string $component component name, e.g. 'core' or 'mod_forum'.
+     * @return string HTML.
+     */
+    public function component_name(string $component): string {
+        list($type) = core_component::normalize_component($component);
+        if ($type === 'core') {
+            return get_string('corecomponent', 'tool_task');
+        }
+
+        $plugininfo = core_plugin_manager::instance()->get_plugin_info($component);
+        if (!$plugininfo) {
+            return $component;
+        }
+
+        $plugininfo->init_display_name();
+
+        $componentname = $plugininfo->displayname;
+        if (!$plugininfo->is_enabled()) {
+            $componentname .= ' ' . html_writer::span(
+                            get_string('disabled', 'tool_task'), 'badge badge-secondary');
+        }
+        $componentname .= "\n" . html_writer::span($plugininfo->component, 'task-class text-ltr');
+
+        return $componentname;
+    }
+
+    /**
+     * Standard display of a tasks last run time.
+     *
+     * @param scheduled_task $task
+     * @return string HTML.
+     */
+    public function last_run_time(scheduled_task $task): string {
+        if ($task->get_last_run_time()) {
+            return userdate($task->get_last_run_time());
+        } else {
+            return get_string('never');
+        }
+    }
+
+    /**
+     * Standard display of a tasks next run time.
+     *
+     * @param scheduled_task $task
+     * @return string HTML.
+     */
+    public function next_run_time(scheduled_task $task): string {
+        $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
+
+        $nextrun = $task->get_next_run_time();
+        if ($plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled()) {
+            $nextrun = get_string('plugindisabled', 'tool_task');
+        } else if ($task->get_disabled()) {
+            $nextrun = get_string('taskdisabled', 'tool_task');
+        } else if ($nextrun > time()) {
+            $nextrun = userdate($nextrun);
+        } else {
+            $nextrun = get_string('asap', 'tool_task');
+        }
+
+        return $nextrun;
+    }
+
+    /**
+     * Get a table cell to show one time, comparing it to the default.
+     *
+     * @param string $current the current setting.
+     * @param string $default the default setting from the db/tasks.php file.
+     * @return html_table_cell for use in the table.
+     */
+    protected function time_cell(string $current, string $default): html_table_cell {
+        $cell = new html_table_cell($current);
+        // Cron-style values must always be LTR.
+        $cell->attributes['class'] = 'text-ltr';
+
+        // If the current value is default, that is all we want to do.
+        if ($default === '*') {
+            if ($current === '*') {
+                return $cell;
+            }
+        } else if ($default === 'R' ) {
+            if (is_numeric($current)) {
+                return $cell;
+            }
+        } else {
+            if ($default === $current) {
+                return $cell;
+            }
+        }
+
+        // Otherwise, highlight and show the default.
+        $cell->attributes['class'] .= ' table-warning';
+        $cell->text .= ' ' . html_writer::span(
+                get_string('defaultx', 'tool_task', $default), 'task-class');
+        return $cell;
+    }
+
     /**
      * Renders a link back to the scheduled tasks page (used from the 'run now' screen).
      *
+     * @param string $taskclassname if specified, the list of tasks will scroll to show this task.
      * @return string HTML code
      */
-    public function link_back() {
-        return $this->render_from_template('tool_task/link_back',
-                array('url' => new moodle_url('/admin/tool/task/scheduledtasks.php')));
+    public function link_back($taskclassname = '') {
+        $url = new moodle_url('/admin/tool/task/scheduledtasks.php');
+        if ($taskclassname) {
+            $url->param('lastchanged', $taskclassname);
+        }
+        return $this->render_from_template('tool_task/link_back', ['url' => $url]);
     }
 }
index fd7bc30..b404a82 100644 (file)
@@ -71,9 +71,10 @@ echo $OUTPUT->heading($task->get_name());
 if (!optional_param('confirm', 0, PARAM_INT)) {
     echo $OUTPUT->confirm(get_string('runnow_confirm', 'tool_task', $task->get_name()),
             new single_button(new moodle_url('/admin/tool/task/schedule_task.php',
-            array('task' => $taskname, 'confirm' => 1, 'sesskey' => sesskey())),
+                    ['task' => $taskname, 'confirm' => 1, 'sesskey' => sesskey()]),
             get_string('runnow', 'tool_task')),
-            new single_button(new moodle_url('/admin/tool/task/scheduledtasks.php'),
+            new single_button(new moodle_url('/admin/tool/task/scheduledtasks.php',
+                    ['lastchanged' => get_class($task)]),
             get_string('cancel'), false));
     echo $OUTPUT->footer();
     exit;
@@ -97,6 +98,6 @@ $output = $PAGE->get_renderer('tool_task');
 echo $OUTPUT->single_button(new moodle_url('/admin/tool/task/schedule_task.php',
         array('task' => $taskname, 'confirm' => 1, 'sesskey' => sesskey())),
         get_string('runagain', 'tool_task'));
-echo $output->link_back();
+echo $output->link_back(get_class($task));
 
 echo $OUTPUT->footer();
index 90d8b8d..d256f3d 100644 (file)
@@ -26,19 +26,12 @@ require_once(__DIR__ . '/../../../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/tablelib.php');
 
-$PAGE->set_url('/admin/tool/task/scheduledtasks.php');
-$PAGE->set_context(context_system::instance());
-$PAGE->set_pagelayout('admin');
-$strheading = get_string('scheduledtasks', 'tool_task');
-$PAGE->set_title($strheading);
-$PAGE->set_heading($strheading);
-
-require_admin();
-
-$renderer = $PAGE->get_renderer('tool_task');
+admin_externalpage_setup('scheduledtasks');
 
 $action = optional_param('action', '', PARAM_ALPHAEXT);
 $taskname = optional_param('task', '', PARAM_RAW);
+$lastchanged = optional_param('lastchanged', '', PARAM_RAW);
+
 $task = null;
 $mform = null;
 
@@ -55,15 +48,16 @@ if ($action == 'edit') {
 
 if ($task) {
     $mform = new tool_task_edit_scheduled_task_form(null, $task);
+    $nexturl = new moodle_url($PAGE->url, ['lastchanged' => $taskname]);
 }
 
+$renderer = $PAGE->get_renderer('tool_task');
+
 if ($mform && ($mform->is_cancelled() || !empty($CFG->preventscheduledtaskchanges))) {
-    redirect(new moodle_url('/admin/tool/task/scheduledtasks.php'));
+    redirect($nexturl);
 } else if ($action == 'edit' && empty($CFG->preventscheduledtaskchanges)) {
 
     if ($data = $mform->get_data()) {
-
-
         if ($data->resettodefaults) {
             $defaulttask = \core\task\manager::get_default_scheduled_task($taskname);
             $task->set_minute($defaulttask->get_minute());
@@ -85,13 +79,16 @@ if ($mform && ($mform->is_cancelled() || !empty($CFG->preventscheduledtaskchange
 
         try {
             \core\task\manager::configure_scheduled_task($task);
-            redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
+            redirect($nexturl, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
         } catch (Exception $e) {
-            redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
+            redirect($nexturl, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
         }
     } else {
         echo $OUTPUT->header();
         echo $OUTPUT->heading(get_string('edittaskschedule', 'tool_task', $task->get_name()));
+        echo html_writer::div('\\' . get_class($task), 'task-class text-ltr');
+        echo html_writer::div(get_string('fromcomponent', 'tool_task',
+                $renderer->component_name($task->get_component())));
         $mform->display();
         echo $OUTPUT->footer();
     }
@@ -99,6 +96,6 @@ if ($mform && ($mform->is_cancelled() || !empty($CFG->preventscheduledtaskchange
 } else {
     echo $OUTPUT->header();
     $tasks = core\task\manager::get_all_scheduled_tasks();
-    echo $renderer->scheduled_tasks_table($tasks);
+    echo $renderer->scheduled_tasks_table($tasks, $lastchanged);
     echo $OUTPUT->footer();
 }
index aaa36d9..ceee867 100644 (file)
@@ -9,6 +9,11 @@ Feature: Clear scheduled task fail delay
     And I log in as "admin"
     And I navigate to "Server > Tasks > Scheduled tasks" in site administration
 
+  Scenario: Any fail delay is highlighted
+    Then I should see "60" in the "Send new user passwords" "table_row"
+    And I should see "Clear" in the "Send new user passwords" "table_row"
+    And I should see "60" in the "td.table-danger" "css_element"
+
   Scenario: Clear fail delay
     When I click on "Clear" "text" in the "Send new user passwords" "table_row"
     And I should see "Are you sure you want to clear the fail delay"
@@ -16,6 +21,7 @@ Feature: Clear scheduled task fail delay
 
     Then I should not see "60" in the "Send new user passwords" "table_row"
     And I should not see "Clear" in the "Send new user passwords" "table_row"
+    And I should see "Send new user passwords" in the "tr.table-primary" "css_element"
 
   Scenario: Cancel clearing the fail delay
     When I click on "Clear" "text" in the "Send new user passwords" "table_row"
@@ -23,3 +29,4 @@ Feature: Clear scheduled task fail delay
 
     Then I should see "60" in the "Send new user passwords" "table_row"
     And I should see "Clear" in the "Send new user passwords" "table_row"
+    And I should see "Send new user passwords" in the "tr.table-primary" "css_element"
index 4da19e5..160451d 100644 (file)
@@ -16,6 +16,7 @@ Feature: Manage scheduled tasks
     And I press "Save changes"
     Then I should see "Changes saved"
     And I should see "Task disabled" in the "Log table cleanup" "table_row"
+    And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
 
   Scenario: Enable scheduled task
     When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
@@ -25,10 +26,20 @@ Feature: Manage scheduled tasks
     And I press "Save changes"
     Then I should see "Changes saved"
     And I should not see "Task disabled" in the "Log table cleanup" "table_row"
+    And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
 
   Scenario: Edit scheduled task
     When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
     Then I should see "Edit task schedule: Log table cleanup"
+    And I should see "\logstore_standard\task\cleanup_task"
+    And I should see "From component: Standard log"
+    And I should see "logstore_standard"
+    And I should see "Default: R" in the "Minute" "fieldset"
+    And I should see "Default: *" in the "Day" "fieldset"
+    And I set the following fields to these values:
+      | minute               | frog |
+    And I press "Save changes"
+    And I should see "Data submitted is invalid"
     And I set the following fields to these values:
       | minute               | */5 |
       | hour                 | 1   |
@@ -36,10 +47,12 @@ Feature: Manage scheduled tasks
       | month                | 3   |
       | dayofweek            | 4   |
     And I press "Save changes"
-    Then I should see "Changes saved"
+    And I should see "Changes saved"
     And the following should exist in the "admintable" table:
-      | Component    | Minute | Hour | Day | Day of week | Month |
-      | Standard log | */5    | 1    | 2   | 4           | 3     |
+      | Component                      | Minute         | Hour         | Day          | Day of week  | Month        |
+      | Standard log logstore_standard | */5 Default: R | 1 Default: 4 | 2 Default: * | 4 Default: * | 3 Default: * |
+    And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
+    And I should see "*/5 Default: R" in the "td.table-warning" "css_element"
 
   Scenario: Reset scheduled task to default
     When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
@@ -50,4 +63,5 @@ Feature: Manage scheduled tasks
     Then I should see "Changes saved"
     And the following should not exist in the "admintable" table:
       | Name               | Component    | Minute | Hour | Day | Day of week | Month |
-      | Log table cleanup  | Standard log | */5    | 1    | 2   | 4           | 3     |
\ No newline at end of file
+      | Log table cleanup  | Standard log | */5    | 1    | 2   | 4           | 3     |
+    And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
diff --git a/auth/none/classes/check/noauth.php b/auth/none/classes/check/noauth.php
new file mode 100644 (file)
index 0000000..7e57907
--- /dev/null
@@ -0,0 +1,69 @@
+<?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/>.
+
+/**
+ * Verifies unsupported noauth setting
+ *
+ * @package    auth_none
+ * @copyright  2020 Brendan Heywood <brendan@catalyst-au.net>
+ * @copyright  2008 petr Skoda
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace auth_none\check;
+
+defined('MOODLE_INTERNAL') || die();
+
+use core\check\result;
+
+/**
+ * Verifies unsupported noauth setting
+ *
+ * @copyright  2020 Brendan Heywood <brendan@catalyst-au.net>
+ * @copyright  2008 petr Skoda
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class noauth extends \core\check\check {
+
+    /**
+     * A link to a place to action this
+     *
+     * @return action_link
+     */
+    public function get_action_link(): ?\action_link {
+        return new \action_link(
+            new \moodle_url('/admin/settings.php?section=manageauths'),
+            get_string('authsettings', 'admin'));
+    }
+
+    /**
+     * Return result
+     * @return result
+     */
+    public function get_result(): result {
+        if (is_enabled_auth('none')) {
+            $status = result::ERROR;
+            $summary = get_string('checknoautherror', 'auth_none');
+        } else {
+            $status = result::OK;
+            $summary = get_string('checknoauthok', 'auth_none');
+        }
+        $details = get_string('checknoauthdetails', 'auth_none');
+
+        return new result($status, $summary, $details);
+    }
+}
+
index a4ba89d..4ae1975 100644 (file)
@@ -25,3 +25,7 @@
 $string['auth_nonedescription'] = 'Users can sign in and create valid accounts immediately, with no authentication against an external server and no confirmation via email.  Be careful using this option - think of the security and administration problems this could cause.';
 $string['pluginname'] = 'No authentication';
 $string['privacy:metadata'] = 'The No authentication plugin does not store any personal data.';
+$string['checknoauthdetails'] = '<p>The <em>No authentication</em> plugin is not intended for production sites. Please disable it unless this is a development test site.</p>';
+$string['checknoautherror'] = 'The No authentication plugin cannot be used on production sites.';
+$string['checknoauth'] = 'No authentication';
+$string['checknoauthok'] = 'The no authentication plugin is disabled.';
diff --git a/auth/none/lib.php b/auth/none/lib.php
new file mode 100644 (file)
index 0000000..7c6b551
--- /dev/null
@@ -0,0 +1,36 @@
+<?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/>.
+
+/**
+ * Anybody can login with any password.
+ *
+ * @package    auth_none
+ * @category   check
+ * @copyright  2020 Brendan Heywood <brendan@catalyst-au.net>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Add security check to make sure this isn't on in production.
+ *
+ * @return array check
+ */
+function auth_none_security_checks() {
+    return [new auth_none\check\noauth()];
+}
+
index b09772e..4dea016 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2019111800;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2019111801;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2019111200;        // Requires this Moodle version
 $plugin->component = 'auth_none';       // Full name of the plugin (used for diagnostics)
index 0911c68..eef73fc 100644 (file)
@@ -1394,7 +1394,9 @@ abstract class restore_dbops {
             // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
             //       hence we are looking there for usernames if not empty. See delete_user()
             // If match by id and mnethost and user is deleted in DB and
-            // match by username LIKE 'backup_email.%' or by non empty email = md5(username) => ok, return target user
+            // match by username LIKE 'substring(backup_email).%' where the substr length matches the retained data in the
+            // username field (100 - (timestamp + 1) characters), or by non empty email = md5(username) => ok, return target user.
+            $usernamelookup = core_text::substr($user->email, 0, 89) . '.%';
             if ($rec = $DB->get_record_sql("SELECT *
                                               FROM {user} u
                                              WHERE id = ?
@@ -1407,13 +1409,14 @@ abstract class restore_dbops {
                                                        AND email = ?
                                                        )
                                                    )",
-                                           array($user->id, $user->mnethostid, $user->email.'.%', md5($user->username)))) {
+                                           array($user->id, $user->mnethostid, $usernamelookup, md5($user->username)))) {
                 return $rec; // Matching user, deleted in DB found, return it
             }
 
             // 1D - Handle users deleted in backup file and "alive" in DB
             // If match by id and mnethost and user is deleted in backup file
-            // and match by email = email_without_time(backup_email) => ok, return target user
+            // and match by substring(email) = email_without_time(backup_email) where the substr length matches the retained data
+            // in the username field (100 - (timestamp + 1) characters) => ok, return target user.
             if ($user->deleted) {
                 // Note: for DB deleted users email is stored in username field, hence we
                 //       are looking there for emails. See delete_user()
@@ -1423,7 +1426,7 @@ abstract class restore_dbops {
                                                   FROM {user} u
                                                  WHERE id = ?
                                                    AND mnethostid = ?
-                                                   AND UPPER(email) = UPPER(?)",
+                                                   AND " . $DB->sql_substr('UPPER(email)', 1, 89) . " = UPPER(?)",
                                                array($user->id, $user->mnethostid, $trimemail))) {
                     return $rec; // Matching user, deleted in backup file found, return it
                 }
@@ -1470,7 +1473,8 @@ abstract class restore_dbops {
             // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
             //       hence we are looking there for usernames if not empty. See delete_user()
             // 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
-            //       (by username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
+            //       (by username LIKE 'substring(backup_email).%' or non-zero firstaccess) => ok, return target user.
+            $usernamelookup = core_text::substr($user->email, 0, 89) . '.%';
             if ($rec = $DB->get_record_sql("SELECT *
                                               FROM {user} u
                                              WHERE mnethostid = ?
@@ -1484,14 +1488,15 @@ abstract class restore_dbops {
                                                        AND firstaccess = ?
                                                        )
                                                    )",
-                                           array($user->mnethostid, md5($user->username), $user->email.'.%', $user->firstaccess))) {
+                                           array($user->mnethostid, md5($user->username), $usernamelookup, $user->firstaccess))) {
                 return $rec; // Matching user found, return it
             }
 
             // 2B2 - If match by mnethost and user is deleted in DB and
-            //       username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
+            //       username LIKE 'substring(backup_email).%' and non-zero firstaccess) => ok, return target user
             //       (this covers situations where md5(username) wasn't being stored so we require both
             //        the email & non-zero firstaccess to match)
+            $usernamelookup = core_text::substr($user->email, 0, 89) . '.%';
             if ($rec = $DB->get_record_sql("SELECT *
                                               FROM {user} u
                                              WHERE mnethostid = ?
@@ -1499,13 +1504,13 @@ abstract class restore_dbops {
                                                AND UPPER(username) LIKE UPPER(?)
                                                AND firstaccess != 0
                                                AND firstaccess = ?",
-                                           array($user->mnethostid, $user->email.'.%', $user->firstaccess))) {
+                                           array($user->mnethostid, $usernamelookup, $user->firstaccess))) {
                 return $rec; // Matching user found, return it
             }
 
             // 2C - Handle users deleted in backup file and "alive" in DB
             // If match mnethost and user is deleted in backup file
-            // and match by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
+            // and match by substring(email) = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user.
             if ($user->deleted) {
                 // Note: for DB deleted users email is stored in username field, hence we
                 //       are looking there for emails. See delete_user()
@@ -1514,7 +1519,7 @@ abstract class restore_dbops {
                 if ($rec = $DB->get_record_sql("SELECT *
                                                   FROM {user} u
                                                  WHERE mnethostid = ?
-                                                   AND UPPER(email) = UPPER(?)
+                                                   AND " . $DB->sql_substr('UPPER(email)', 1, 89) . " = UPPER(?)
                                                    AND firstaccess != 0
                                                    AND firstaccess = ?",
                                                array($user->mnethostid, $trimemail, $user->firstaccess))) {
index d0fd2cc..59c127b 100644 (file)
@@ -119,4 +119,246 @@ class restore_dbops_testcase extends advanced_testcase {
             $this->assertSame('Table "backup_ids_temp" does not exist', $e->getMessage());
         }
     }
+
+    /**
+     * Data provider for {@link test_precheck_user()}
+     */
+    public function precheck_user_provider() {
+
+        $emailmultiplier = [
+            'shortmail' => 'normalusername@example.com',
+            'longmail' => str_repeat('a', 100)  // It's not validated, hence any string is ok.
+        ];
+
+        $providercases = [];
+
+        foreach ($emailmultiplier as $emailk => $email) {
+            // Get the related cases.
+            $cases = $this->precheck_user_cases($email);
+            // Rename them (keys).
+            foreach ($cases as $key => $case) {
+                $providercases[$key . ' - ' . $emailk] = $case;
+            }
+        }
+
+        return $providercases;
+    }
+
+    /**
+     * Get all the cases implemented in {@link restore_dbops::precheck_users()}
+     *
+     * @param string $email
+     */
+    private function precheck_user_cases($email) {
+        global $CFG;
+
+        $baseuserarr = [
+            'username' => 'normalusername',
+            'email'    => $email,
+            'mnethostid' => $CFG->mnet_localhost_id,
+            'firstaccess' => 123456789,
+            'deleted'    => 0,
+            'forceemailcleanup' => false, // Hack to force the DB record to have empty mail.
+            'forceduplicateadminallowed' => false]; // Hack to enable import_general_duplicate_admin_allowed.
+
+        return [
+            // Cases with samesite = true.
+            'samesite match existing (1A)' => [
+                'dbuser' => $baseuserarr,
+                'backupuser' => $baseuserarr,
+                'samesite' => true,
+                'outcome' => 'match'
+            ],
+            'samesite match existing anon (1B)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'username' => 'anon01']),
+                'backupuser' => array_merge($baseuserarr, [
+                    'id' => -1, 'username' => 'anon01', 'firstname' => 'anonfirstname01',
+                    'lastname' => 'anonlastname01', 'email' => 'anon01@doesntexist.invalid']),
+                'samesite' => true,
+                'outcome' => 'match'
+            ],
+            'samesite match existing deleted in db, alive in backup, by db username (1C)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'deleted' => 1]),
+                'backupuser' => array_merge($baseuserarr, [
+                    'username' => 'this_wont_match']),
+                'samesite' => true,
+                'outcome' => 'match'
+            ],
+            'samesite match existing deleted in db, alive in backup, by db email (1C)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'deleted' => 1]),
+                'backupuser' => array_merge($baseuserarr, [
+                    'email' => 'this_wont_match']),
+                'samesite' => true,
+                'outcome' => 'match'
+            ],
+            'samesite match existing alive in db, deleted in backup (1D)' => [
+                'dbuser' => $baseuserarr,
+                'backupuser' => array_merge($baseuserarr, [
+                    'deleted' => 1]),
+                'samesite' => true,
+                'outcome' => 'match'
+            ],
+            'samesite conflict (1E)' => [
+                'dbuser' => $baseuserarr,
+                'backupuser' => array_merge($baseuserarr, ['id' => -1]),
+                'samesite' => true,
+                'outcome' => false
+            ],
+            'samesite create user (1F)' => [
+                'dbuser' => $baseuserarr,
+                'backupuser' => array_merge($baseuserarr, [
+                    'username' => 'newusername']),
+                'samesite' => false,
+                'outcome' => true
+            ],
+
+            // Cases with samesite = false.
+            'no samesite match existing, by db email (2A1)' => [
+                'dbuser' => $baseuserarr,
+                'backupuser' => array_merge($baseuserarr, [
+                    'firstaccess' => 0]),
+                'samesite' => false,
+                'outcome' => 'match'
+            ],
+            'no samesite match existing, by db firstaccess (2A1)' => [
+                'dbuser' => $baseuserarr,
+                'backupuser' => array_merge($baseuserarr, [
+                    'email' => 'this_wont_match@example.con']),
+                'samesite' => false,
+                'outcome' => 'match'
+            ],
+            'no samesite match existing anon (2A1 too)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'username' => 'anon01']),
+                'backupuser' => array_merge($baseuserarr, [
+                    'id' => -1, 'username' => 'anon01', 'firstname' => 'anonfirstname01',
+                    'lastname' => 'anonlastname01', 'email' => 'anon01@doesntexist.invalid']),
+                'samesite' => false,
+                'outcome' => 'match'
+            ],
+            'no samesite match dupe admin (2A2)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'username' => 'admin_old_site_id',
+                    'forceduplicateadminallowed' => true]),
+                'backupuser' => array_merge($baseuserarr, [
+                    'username' => 'admin']),
+                'samesite' => false,
+                'outcome' => 'match'
+            ],
+            'no samesite match existing deleted in db, alive in backup, by db username (2B1)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'deleted' => 1]),
+                'backupuser' => array_merge($baseuserarr, [
+                    'firstaccess' => 0]),
+                'samesite' => false,
+                'outcome' => 'match'
+            ],
+            'no samesite match existing deleted in db, alive in backup, by db firstaccess (2B1)' => [
+                'dbuser' => array_merge($baseuserarr, [
+                    'deleted' => 1]),
+                'backupuser' => array_merge($baseuserarr, [
+                    'mail' => 'this_wont_match']),
+                'samesite'&nbs