From ac995c34e36d3f5b2acdc76f0060fad0ca5a1646 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Mon, 4 Nov 2024 09:18:40 +0800 Subject: [PATCH 1/3] [site] Remove 4.2 docs --- versioned_docs/version-4.2/_utils.tsx | 120 -- versioned_docs/version-4.2/apis.md | 256 --- .../version-4.2/apis/_files/amd-dir.mdx | 10 - .../version-4.2/apis/_files/amd-dir.tsx | 42 - .../version-4.2/apis/_files/backup-dir.mdx | 7 - .../version-4.2/apis/_files/backup-dir.tsx | 29 - .../version-4.2/apis/_files/changes.mdx | 7 - .../version-4.2/apis/_files/changes.tsx | 31 - .../version-4.2/apis/_files/classes-dir.mdx | 9 - .../version-4.2/apis/_files/classes-dir.tsx | 29 - .../version-4.2/apis/_files/cli-dir.mdx | 8 - .../version-4.2/apis/_files/cli-dir.tsx | 40 - .../version-4.2/apis/_files/db-access-php.mdx | 13 - .../version-4.2/apis/_files/db-access-php.tsx | 45 - .../version-4.2/apis/_files/db-events-php.mdx | 14 - .../version-4.2/apis/_files/db-events-php.tsx | 41 - .../apis/_files/db-install-php.mdx | 10 - .../apis/_files/db-install-php.tsx | 30 - .../apis/_files/db-install-xml.mdx | 8 - .../apis/_files/db-messages-php.mdx | 4 - .../apis/_files/db-messages-php.tsx | 42 - .../version-4.2/apis/_files/db-mobile-php.mdx | 6 - .../version-4.2/apis/_files/db-mobile-php.tsx | 30 - .../apis/_files/db-renamedclasses-php.mdx | 8 - .../apis/_files/db-renamedclasses-php.tsx | 49 - .../apis/_files/db-services-php.mdx | 16 - .../apis/_files/db-services-php.tsx | 47 - .../apis/_files/db-tasks-example.php | 11 - .../version-4.2/apis/_files/db-tasks-php.mdx | 18 - .../version-4.2/apis/_files/db-tasks-php.tsx | 33 - .../apis/_files/db-uninstall-php.mdx | 2 - .../apis/_files/db-uninstall-php.tsx | 30 - .../apis/_files/db-upgrade-php.mdx | 30 - .../apis/_files/db-upgrade-php.tsx | 55 - .../apis/_files/environment-xml.mdx | 4 - .../apis/_files/environment-xml.tsx | 45 - .../version-4.2/apis/_files/index.tsx | 78 - .../version-4.2/apis/_files/install-xml.tsx | 30 - .../version-4.2/apis/_files/lang-extra.md | 15 - .../version-4.2/apis/_files/lang.md | 25 - .../version-4.2/apis/_files/lang.tsx | 35 - .../version-4.2/apis/_files/lib.mdx | 11 - .../version-4.2/apis/_files/lib.tsx | 32 - .../version-4.2/apis/_files/locallib.mdx | 14 - .../version-4.2/apis/_files/locallib.tsx | 31 - .../version-4.2/apis/_files/pix-dir.mdx | 6 - .../version-4.2/apis/_files/pix-dir.tsx | 30 - .../version-4.2/apis/_files/readme.mdx | 4 - .../version-4.2/apis/_files/readme.tsx | 30 - .../apis/_files/readme_moodle-txt.mdx | 5 - .../apis/_files/readme_moodle-txt.tsx | 30 - .../version-4.2/apis/_files/settings-php.mdx | 16 - .../version-4.2/apis/_files/settings-php.tsx | 30 - .../version-4.2/apis/_files/styles-css.mdx | 11 - .../version-4.2/apis/_files/styles-css.tsx | 30 - .../apis/_files/thirdpartylibs-xml.mdx | 14 - .../apis/_files/thirdpartylibs-xml.tsx | 51 - .../version-4.2/apis/_files/upgrade-php.mdx | 13 - .../version-4.2/apis/_files/upgrade-txt.mdx | 56 - .../version-4.2/apis/_files/upgrade-txt.tsx | 30 - .../version-4.2/apis/_files/version-php.mdx | 11 - .../version-4.2/apis/_files/version-php.tsx | 51 - .../version-4.2/apis/_files/yui-dir.mdx | 11 - .../version-4.2/apis/_files/yui-dir.tsx | 32 - .../apis/commonfiles/db-tasks.php/index.md | 154 -- .../version-4.2/apis/commonfiles/index.mdx | 164 -- .../apis/commonfiles/tag.php/index.md | 112 -- .../apis/commonfiles/version.php/index.md | 210 --- .../apis/core/activitycompletion/index.md | 436 ----- .../_index/my_overview_sam_student.png | Bin 48765 -> 0 bytes .../version-4.2/apis/core/calendar/index.md | 479 ------ .../apis/core/conditionalactivities/index.md | 220 --- .../TransactionsAndExceptionsFlow.png | Bin 41878 -> 0 bytes .../core/dml/_exceptions/Dml_exceptions.png | Bin 3522 -> 0 bytes .../apis/core/dml/database-schema.md | 89 -- .../version-4.2/apis/core/dml/ddl.md | 131 -- .../apis/core/dml/delegated-transactions.md | 78 - .../version-4.2/apis/core/dml/drivers.md | 47 - .../version-4.2/apis/core/dml/exceptions.md | 33 - .../version-4.2/apis/core/dml/index.md | 1115 ------------- .../version-4.2/apis/core/grading/index.md | 97 -- .../version-4.2/apis/core/htmlwriter/index.md | 62 - versioned_docs/version-4.2/apis/core/index.md | 8 - .../version-4.2/apis/core/lock/index.md | 73 - .../apis/core/navigation/_index/Moodle-IA.png | Bin 252363 -> 0 bytes .../core/navigation/_index/assignmentmenu.png | Bin 13625 -> 0 bytes .../version-4.2/apis/core/navigation/index.md | 403 ----- .../version-4.2/apis/core/preference/index.md | 106 -- .../version-4.2/apis/core/user/index.md | 85 - .../antivirus/_files/scanner-php.mdx | 13 - .../antivirus/_files/scanner-php.tsx | 88 - .../apis/plugintypes/antivirus/index.mdx | 112 -- .../assign/_files/submission_settings.php | 22 - .../apis/plugintypes/assign/feedback.md | 540 ------- .../apis/plugintypes/assign/index.md | 13 - .../apis/plugintypes/assign/submission.md | 656 -------- .../apis/plugintypes/atto/_examples/button.md | 4 - .../plugintypes/atto/_examples/button.tsx | 69 - .../apis/plugintypes/atto/_examples/lib.md | 7 - .../apis/plugintypes/atto/_examples/lib.php | 37 - .../apis/plugintypes/atto/index.md | 112 -- .../availability/_examples/lang.md | 14 - .../availability/_examples/lang.php | 3 - .../apis/plugintypes/availability/index.md | 338 ---- .../plugintypes/blocks/_examples/access.php | 20 - .../blocks/_examples/block_pluginname.php | 49 - .../blocks/_examples/edit_form.php | 10 - .../blocks/_examples/pluginskel_recipe.yaml | 103 -- .../apis/plugintypes/blocks/index.md | 436 ----- .../customfield/_files/data_controller.php | 53 - .../customfield/_files/data_controller.tsx | 28 - .../customfield/_files/field_controller.php | 28 - .../customfield/_files/field_controller.tsx | 28 - .../apis/plugintypes/customfield/index.md | 130 -- .../plugintypes/enrol/_examples/access.php | 39 - .../enrol/_examples/enrol_lang.php | 7 - .../apis/plugintypes/enrol/_examples/lib.php | 5 - .../enrol/_examples/message_lib.php | 48 - .../plugintypes/enrol/_examples/ui_lib.php | 100 -- .../apis/plugintypes/enrol/index.md | 422 ----- .../fileconverter/_files/converter.md | 6 - .../fileconverter/_files/converter.tsx | 39 - .../apis/plugintypes/fileconverter/index.md | 100 -- .../plugintypes/filter/_examples/dynamic.js | 31 - .../plugintypes/filter/_examples/filter.php | 6 - .../apis/plugintypes/filter/index.md | 197 --- .../plugintypes/format/_examples/format.php | 27 - .../format/_examples/format_lang.php | 12 - .../apis/plugintypes/format/_examples/lib.php | 104 -- .../format/_examples/lib_components.php | 8 - .../format/_examples/lib_course_index.php | 8 - .../format/_examples/output/cmitem.mustache | 8 - .../format/_examples/output/cmitem.php | 16 - .../format/_examples/output/content.mustache | 14 - .../format/_examples/output/content.php | 16 - .../format/_examples/output/renderer.php | 9 - .../format/_examples/output/section.mustache | 12 - .../format/_examples/output/section.php | 16 - .../format/_examples/pluginskel_recipe.yaml | 84 - .../plugintypes/format/_examples/renderer.php | 41 - .../format/_files/course_editor_workflow.png | Bin 92444 -> 0 bytes .../format/_files/course_format_output.png | Bin 327459 -> 0 bytes .../apis/plugintypes/format/index.md | 627 -------- .../apis/plugintypes/format/migration.md | 284 ---- .../version-4.2/apis/plugintypes/index.md | 141 -- .../apis/plugintypes/local/index.mdx | 152 -- .../apis/plugintypes/logstore/index.md | 14 - .../apis/plugintypes/mlbackend/index.md | 212 --- .../_activitymodule/activity-chooser-info.png | Bin 95142 -> 0 bytes .../activity-chooser-recommend.png | Bin 35361 -> 0 bytes .../activity-chooser-starred.png | Bin 39244 -> 0 bytes .../mod/_files/access_description.md | 20 - .../apis/plugintypes/mod/_files/index-php.mdx | 2 - .../apis/plugintypes/mod/_files/index-php.tsx | 52 - .../mod/_files/install_description.md | 12 - .../plugintypes/mod/_files/lib_description.md | 18 - .../plugintypes/mod/_files/mod_form-php.mdx | 16 - .../plugintypes/mod/_files/mod_form-php.tsx | 64 - .../plugintypes/mod/_files/mod_form-php.txt | 31 - .../apis/plugintypes/mod/_files/view-php.mdx | 2 - .../apis/plugintypes/mod/_files/view-php.tsx | 40 - .../apis/plugintypes/mod/activitymodule.md | 77 - .../apis/plugintypes/mod/index.mdx | 239 --- .../apis/plugintypes/mod_book/index.md | 10 - .../apis/plugintypes/mod_data/fields.md | 81 - .../apis/plugintypes/mod_data/index.md | 12 - .../apis/plugintypes/mod_data/presets.md | 15 - .../apis/plugintypes/mod_forum/index.md | 10 - .../apis/plugintypes/qbank/index.md | 23 - .../repository/_examples/access.php | 13 - .../_examples/flickr_public_lib.php | 100 -- .../repository/_examples/full_list.jsonc | 68 - .../plugintypes/repository/_examples/lib.php | 64 - .../plugintypes/repository/_files/options.png | Bin 9244 -> 0 bytes .../apis/plugintypes/repository/index.md | 962 ----------- .../apis/plugintypes/tiny/index.md | 586 ------- .../apis/plugintypes/tiny/testing.md | 181 --- .../apis/subsystems/_category_.yml | 3 - .../subsystems/_roles/Moodle-contexts-1.8.png | Bin 37085 -> 0 bytes .../version-4.2/apis/subsystems/access.md | 235 --- .../apis/subsystems/admin/index.md | 224 --- ...nalytics_API_classes_diagram_(summary).svg | 4 - .../_index/Inspire_API_components.png | Bin 87921 -> 0 bytes .../analytics/_index/Inspire_data_flow.png | Bin 102545 -> 0 bytes .../apis/subsystems/analytics/index.md | 812 ---------- .../apis/subsystems/availability/index.md | 164 -- .../apis/subsystems/backup/index.md | 119 -- .../apis/subsystems/backup/restore.md | 58 - .../apis/subsystems/check/index.md | 226 --- .../apis/subsystems/editor/index.md | 54 - .../version-4.2/apis/subsystems/enrol.md | 240 --- .../external/advanced/_category_.json | 6 - .../external/advanced/custom-services.md | 71 - .../apis/subsystems/external/description.md | 83 - .../apis/subsystems/external/files.md | 137 -- .../apis/subsystems/external/functions.md | 137 -- .../apis/subsystems/external/index.md | 62 - .../apis/subsystems/external/security.md | 85 - .../apis/subsystems/external/testing.md | 126 -- .../subsystems/external/writing-a-service.md | 462 ------ .../apis/subsystems/favourites/index.md | 132 -- .../apis/subsystems/files/browsing.md | 45 - .../apis/subsystems/files/converter.md | 98 -- .../apis/subsystems/files/index.md | 438 ----- .../apis/subsystems/files/internals.md | 207 --- .../subsystems/form/advanced/_category_.yml | 1 - .../form/advanced/advanced-elements.md | 94 -- .../form/advanced/checkbox-controller.md | 74 - .../form/advanced/no-submit-button.md | 54 - .../form/advanced/repeat-elements.md | 106 -- .../version-4.2/apis/subsystems/form/index.md | 331 ---- .../apis/subsystems/form/usage/files.md | 441 ----- .../apis/subsystems/form/usage/index.md | 142 -- .../apis/subsystems/group/index.md | 195 --- .../version-4.2/apis/subsystems/output.md | 279 ---- .../version-4.2/apis/subsystems/plagiarism.md | 30 - .../_index/MoodlePrivacyMetadataUML.png | Bin 114289 -> 0 bytes .../_index/MoodlePrivacyRequestUML.png | Bin 285158 -> 0 bytes .../apis/subsystems/privacy/faq.md | 69 - .../apis/subsystems/privacy/index.md | 984 ------------ .../apis/subsystems/privacy/utils.md | 286 ---- .../version-4.2/apis/subsystems/roles.md | 226 --- .../version-4.2/apis/subsystems/tag/index.md | 320 ---- .../version-4.2/apis/subsystems/task/adhoc.md | 158 -- .../version-4.2/apis/subsystems/task/index.md | 120 -- .../apis/subsystems/task/scheduled.md | 77 - .../version-4.2/apis/subsystems/time/index.md | 142 -- .../version-4.2/apis/subsystems/xapi/index.md | 481 ------ versioned_docs/version-4.2/devupdate.md | 155 -- .../gettingstarted/requirements.md | 45 - versioned_docs/version-4.2/guides.md | 13 - .../guides/git/_index/git-pushpull-model.png | Bin 47515 -> 0 bytes .../guides/git/_index/git-sync-github.png | Bin 9478 -> 0 bytes .../version-4.2/guides/git/index.md | 496 ------ .../javascript/_examples/promises/getModal.js | 12 - .../guides/javascript/_examples/str.js | 9 - .../guides/javascript/ajax/index.md | 150 -- .../version-4.2/guides/javascript/index.md | 535 ------- .../guides/javascript/jquery/index.md | 101 -- .../guides/javascript/modal/index.md | 206 --- .../version-4.2/guides/javascript/modules.md | 273 ---- .../reactive/_files/basic_classes.svg | 525 ------ .../reactive/_files/lifecycle_hooks.svg | 420 ----- .../guides/javascript/reactive/index.md | 1419 ----------------- .../guides/javascript/yui/index.md | 171 -- .../guides/javascript/yui/modules.md | 289 ---- .../guides/javascript/yui/namespacing.md | 53 - .../version-4.2/guides/templates/index.md | 945 ----------- .../version-4.2/guides/upgrade/index.md | 207 --- versioned_docs/version-4.2/intro.md | 26 - versioned_sidebars/version-4.2-sidebars.json | 57 - versions.json | 1 - 252 files changed, 29375 deletions(-) delete mode 100644 versioned_docs/version-4.2/_utils.tsx delete mode 100644 versioned_docs/version-4.2/apis.md delete mode 100644 versioned_docs/version-4.2/apis/_files/amd-dir.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/amd-dir.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/backup-dir.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/backup-dir.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/changes.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/changes.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/classes-dir.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/classes-dir.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/cli-dir.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/cli-dir.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-access-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-access-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-events-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-events-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-install-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-install-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-install-xml.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-messages-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-messages-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-mobile-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-mobile-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-services-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-services-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-tasks-example.php delete mode 100644 versioned_docs/version-4.2/apis/_files/db-tasks-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-tasks-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-uninstall-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-uninstall-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-upgrade-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/db-upgrade-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/environment-xml.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/environment-xml.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/index.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/install-xml.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/lang-extra.md delete mode 100644 versioned_docs/version-4.2/apis/_files/lang.md delete mode 100644 versioned_docs/version-4.2/apis/_files/lang.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/lib.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/lib.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/locallib.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/locallib.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/pix-dir.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/pix-dir.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/readme.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/readme.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/readme_moodle-txt.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/readme_moodle-txt.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/settings-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/settings-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/styles-css.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/styles-css.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/upgrade-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/upgrade-txt.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/upgrade-txt.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/version-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/version-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/_files/yui-dir.mdx delete mode 100644 versioned_docs/version-4.2/apis/_files/yui-dir.tsx delete mode 100644 versioned_docs/version-4.2/apis/commonfiles/db-tasks.php/index.md delete mode 100644 versioned_docs/version-4.2/apis/commonfiles/index.mdx delete mode 100644 versioned_docs/version-4.2/apis/commonfiles/tag.php/index.md delete mode 100644 versioned_docs/version-4.2/apis/commonfiles/version.php/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/activitycompletion/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/calendar/_index/my_overview_sam_student.png delete mode 100644 versioned_docs/version-4.2/apis/core/calendar/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/conditionalactivities/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/dml/_delegated-transactions/TransactionsAndExceptionsFlow.png delete mode 100644 versioned_docs/version-4.2/apis/core/dml/_exceptions/Dml_exceptions.png delete mode 100644 versioned_docs/version-4.2/apis/core/dml/database-schema.md delete mode 100644 versioned_docs/version-4.2/apis/core/dml/ddl.md delete mode 100644 versioned_docs/version-4.2/apis/core/dml/delegated-transactions.md delete mode 100644 versioned_docs/version-4.2/apis/core/dml/drivers.md delete mode 100644 versioned_docs/version-4.2/apis/core/dml/exceptions.md delete mode 100644 versioned_docs/version-4.2/apis/core/dml/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/grading/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/htmlwriter/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/lock/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/navigation/_index/Moodle-IA.png delete mode 100644 versioned_docs/version-4.2/apis/core/navigation/_index/assignmentmenu.png delete mode 100644 versioned_docs/version-4.2/apis/core/navigation/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/preference/index.md delete mode 100644 versioned_docs/version-4.2/apis/core/user/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/assign/_files/submission_settings.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/assign/feedback.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/assign/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/assign/submission.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/atto/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/availability/_examples/lang.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/availability/_examples/lang.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/availability/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/blocks/_examples/access.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/blocks/_examples/block_pluginname.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/blocks/_examples/edit_form.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/blocks/_examples/pluginskel_recipe.yaml delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/blocks/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/customfield/_files/data_controller.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/customfield/_files/data_controller.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/customfield/_files/field_controller.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/customfield/_files/field_controller.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/customfield/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/enrol/_examples/access.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/enrol/_examples/enrol_lang.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/enrol/_examples/lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/enrol/_examples/message_lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/enrol/_examples/ui_lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/enrol/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/fileconverter/_files/converter.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/fileconverter/_files/converter.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/fileconverter/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/filter/_examples/dynamic.js delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/filter/_examples/filter.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/filter/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/format.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/format_lang.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/lib_components.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/lib_course_index.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/cmitem.mustache delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/cmitem.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/content.mustache delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/content.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/renderer.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/section.mustache delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/output/section.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/pluginskel_recipe.yaml delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_examples/renderer.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_files/course_editor_workflow.png delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/_files/course_format_output.png delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/format/migration.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/local/index.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/logstore/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mlbackend/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_activitymodule/activity-chooser-info.png delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_activitymodule/activity-chooser-recommend.png delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_activitymodule/activity-chooser-starred.png delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/access_description.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/index-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/index-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/install_description.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/lib_description.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/mod_form-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/mod_form-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/mod_form-php.txt delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/view-php.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/_files/view-php.tsx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/activitymodule.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod/index.mdx delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod_book/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod_data/fields.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod_data/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod_data/presets.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/mod_forum/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/qbank/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/repository/_examples/access.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/repository/_examples/flickr_public_lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/repository/_examples/full_list.jsonc delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/repository/_examples/lib.php delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/repository/_files/options.png delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/repository/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/tiny/index.md delete mode 100644 versioned_docs/version-4.2/apis/plugintypes/tiny/testing.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/_category_.yml delete mode 100644 versioned_docs/version-4.2/apis/subsystems/_roles/Moodle-contexts-1.8.png delete mode 100644 versioned_docs/version-4.2/apis/subsystems/access.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/admin/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/analytics/_index/Analytics_API_classes_diagram_(summary).svg delete mode 100644 versioned_docs/version-4.2/apis/subsystems/analytics/_index/Inspire_API_components.png delete mode 100644 versioned_docs/version-4.2/apis/subsystems/analytics/_index/Inspire_data_flow.png delete mode 100644 versioned_docs/version-4.2/apis/subsystems/analytics/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/availability/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/backup/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/backup/restore.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/check/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/editor/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/enrol.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/advanced/_category_.json delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/advanced/custom-services.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/description.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/files.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/functions.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/security.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/testing.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/external/writing-a-service.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/favourites/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/files/browsing.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/files/converter.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/files/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/files/internals.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/advanced/_category_.yml delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/advanced/advanced-elements.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/advanced/checkbox-controller.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/advanced/no-submit-button.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/advanced/repeat-elements.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/usage/files.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/form/usage/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/group/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/output.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/plagiarism.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/privacy/_index/MoodlePrivacyMetadataUML.png delete mode 100644 versioned_docs/version-4.2/apis/subsystems/privacy/_index/MoodlePrivacyRequestUML.png delete mode 100644 versioned_docs/version-4.2/apis/subsystems/privacy/faq.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/privacy/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/privacy/utils.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/roles.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/tag/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/task/adhoc.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/task/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/task/scheduled.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/time/index.md delete mode 100644 versioned_docs/version-4.2/apis/subsystems/xapi/index.md delete mode 100644 versioned_docs/version-4.2/devupdate.md delete mode 100644 versioned_docs/version-4.2/gettingstarted/requirements.md delete mode 100644 versioned_docs/version-4.2/guides.md delete mode 100644 versioned_docs/version-4.2/guides/git/_index/git-pushpull-model.png delete mode 100644 versioned_docs/version-4.2/guides/git/_index/git-sync-github.png delete mode 100644 versioned_docs/version-4.2/guides/git/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/_examples/promises/getModal.js delete mode 100644 versioned_docs/version-4.2/guides/javascript/_examples/str.js delete mode 100644 versioned_docs/version-4.2/guides/javascript/ajax/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/jquery/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/modal/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/modules.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/reactive/_files/basic_classes.svg delete mode 100644 versioned_docs/version-4.2/guides/javascript/reactive/_files/lifecycle_hooks.svg delete mode 100644 versioned_docs/version-4.2/guides/javascript/reactive/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/yui/index.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/yui/modules.md delete mode 100644 versioned_docs/version-4.2/guides/javascript/yui/namespacing.md delete mode 100644 versioned_docs/version-4.2/guides/templates/index.md delete mode 100644 versioned_docs/version-4.2/guides/upgrade/index.md delete mode 100644 versioned_docs/version-4.2/intro.md delete mode 100644 versioned_sidebars/version-4.2-sidebars.json diff --git a/versioned_docs/version-4.2/_utils.tsx b/versioned_docs/version-4.2/_utils.tsx deleted file mode 100644 index 437aa81219..0000000000 --- a/versioned_docs/version-4.2/_utils.tsx +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React, { type ReactNode } from 'react'; -import ComponentFileSummaryGeneric, { - type ComponentFileSummaryProps, -} from '@site/src/components/ComponentFileSummary'; -import { MDXProvider } from '@mdx-js/react'; - -import { getExample } from '@site/src/moodleBridge'; - -export { - getExample, - ComponentFileSummaryProps, -}; - -/** - * Fill the default properties. - * @param {Props} props - * @return {Props} - */ -export const fillDefaultProps = (props: ComponentFileSummaryProps): ComponentFileSummaryProps => ({ - filetype: 'php', - examplePurpose: props.summary, - ...props, -}); - -const normaliseDescription = (Value: ReactNode | string): null | JSX.Element => { - if (typeof Value === 'boolean' || !Value) { - return null; - } - - if (typeof Value === 'string' || React.isValidElement(Value)) { - return ( - - {Value} - - ); - } - - return ( - - - - ); -}; - -/** - * Get the preferred description given a standard properties value which contains an optional description, - * and/or extraDescription, and a DefaultDescription object. - * - * @param {Props} props - * @param {DefaultDescription} DefaultDescription The default description to use if the `description` property is empty - * @returns {MDXLayout} - */ -export const getDescription = ({ - description = null, - extraDescription = null, - children = null, -}: ComponentFileSummaryProps, defaultDescription?: ReactNode | string): null | ReactNode | JSX.Element => { - if (children) { - const Description = normaliseDescription(children); - return ( - - {Description} - - ); - } - - if (description) { - const Description = normaliseDescription(description); - return ( - - {Description} - - ); - } - - const Description = normaliseDescription(defaultDescription); - const ExtraDescription = normaliseDescription(extraDescription); - - if (Description) { - return ( - - {Description} - {ExtraDescription} - - ); - } - - return null; -}; - -export const ComponentFileSummary = (initialProps: ComponentFileSummaryProps): JSX.Element => { - const props = fillDefaultProps({ - examplePurpose: initialProps?.summary ?? null, - ...initialProps, - }); - - props.description = getDescription(props, props?.defaultDescription ?? null); - - if (props?.example || props?.defaultExample) { - props.example = getExample(props, props?.defaultExample ?? null); - } - - return ComponentFileSummaryGeneric(props); -}; diff --git a/versioned_docs/version-4.2/apis.md b/versioned_docs/version-4.2/apis.md deleted file mode 100644 index 598b17052c..0000000000 --- a/versioned_docs/version-4.2/apis.md +++ /dev/null @@ -1,256 +0,0 @@ ---- -title: API Guides ---- - -Moodle has a number of core APIs that provide tools for Moodle scripts. - -They are essential when writing [Moodle plugins](https://docs.moodle.org/dev/Plugins). - -## Most-used General API - -These APIs are critical and will be used by nearly every Moodle plugin. - -### Access API (access) - -The [Access API](./apis/subsystems/access.md) gives you functions so you can determine what the current user is allowed to do, and it allows modules to extend Moodle with new capabilities. - -### Data manipulation API (dml) - -The [Data manipulation API](./apis/core/dml/index.md) allows you to read/write to databases in a consistent and safe way. - -### File API (files) - -The [File API](./apis/subsystems/files/index.md) controls the storage of files in connection to various plugins. - -### Form API (form) - -The [Form API](./apis/subsystems/form/index.md) defines and handles user data via web forms. - -### Logging API (log) - -The [Events API](https://docs.moodle.org/dev/Events_API) allows you to log events in Moodle, while [Logging 2](https://docs.moodle.org/dev/Logging_2) describes how logs are stored and retrieved. - -### Navigation API (navigation) - -The [Navigation API](./apis/core/navigation/index.md) allows you to manipulate the navigation tree to add and remove items as you wish. - -### Page API (page) - -The [Page API](https://docs.moodle.org/dev/Page_API) is used to set up the current page, add JavaScript, and configure how things will be displayed to the user. - -### Output API (output) - -The [Output API](./apis/subsystems/output.md) is used to render the HTML for all parts of the page. - -### String API (string) - -The [String API](https://docs.moodle.org/dev/String_API) is how you get language text strings to use in the user interface. It handles any language translations that might be available. - -### Upgrade API (upgrade) - -The [Upgrade API](./guides/upgrade/index.md) is how your module installs and upgrades itself, by keeping track of its own version. - -### Moodlelib API (core) - -The [Moodlelib API](https://docs.moodle.org/dev/Moodlelib_API) is the central library file of miscellaneous general-purpose Moodle functions. Functions can over the handling of request parameters, configs, user preferences, time, login, mnet, plugins, strings and others. There are plenty of defined constants too. - -## Other General API - -### Admin settings API (admin) - -The [Admin settings](./apis/subsystems/admin/index.md) API deals with providing configuration options for each plugin and Moodle core. - -### Admin presets API (adminpresets) - -The [Admin presets API](https://docs.moodle.org/dev/AdminPresetsAPI) allows plugins to make some decisions/implementations related to the Site admin presets. - -### Analytics API (analytics) - -The [Analytics API](./apis/subsystems/analytics/index.md) allow you to create prediction models and generate insights. - -### Availability API (availability) - -The [Availability API](./apis/subsystems/availability/index.md) controls access to activities and sections. - -### Backup API (backup) - -The [Backup API](./apis/subsystems/backup/index.md) defines exactly how to convert course data into XML for backup purposes, and the [Restore API](./apis/subsystems/backup/restore.md) describes how to convert it back the other way. - -### Cache API (cache) - -The [The Moodle Universal Cache (MUC)](https://docs.moodle.org/dev/The_Moodle_Universal_Cache_(MUC)) is the structure for storing cache data within Moodle. [Cache API](/docs/apis/subsystems/muc/index.md) explains some of what is needed to use a cache in your code. - -### Calendar API (calendar) - -The [Calendar API](./apis/core/calendar/index.md) allows you to add and modify events in the calendar for user, groups, courses, or the whole site. - -### Check API (check) - -The [Check API](./apis/subsystems/check/index.md) allows you to add security, performance or health checks to your site. - -### Comment API (comment) - -The [Comment API](https://docs.moodle.org/dev/Comment_API) allows you to save and retrieve user comments, so that you can easily add commenting to any of your code. - -### Competency API (competency) - -The [Competency API](https://docs.moodle.org/dev/Competency_API) allows you to list and add evidence of competencies to learning plans, learning plan templates, frameworks, courses and activities. - -### Data definition API (ddl) - -The [Data definition API](./apis/core/dml/ddl.md) is what you use to create, change and delete tables and fields in the database during upgrades. - -### Editor API - -The [Editor API](./apis/subsystems/editor/index.md) is used to control HTML text editors. - -### Enrolment API (enrol) - -The [Enrolment API](./apis/subsystems/enrol.md) deals with course participants. - -### Events API (event) - -The [Events API](https://docs.moodle.org/dev/Events_API) allows to define "events" with payload data to be fired whenever you like, and it also allows you to define handlers to react to these events when they happen. This is the recommended form of inter-plugin communication. This also forms the basis for logging in Moodle. - -### Experience API (xAPI) - -The Experience API (xAPI) is an e-learning standard that allows learning content and learning systems to speak to each other. The [Experience API (xAPI)](https://docs.moodle.org/dev/Experience_API_(xAPI)) -allows any plugin to generate and handle xAPI standard statements. - -### External functions API (external) - -The [External functions API](./apis/subsystems/external/functions.md) allows you to create fully parametrised methods that can be accessed by external programs (such as [Web services](./apis/subsystems/external/index.md)). - -### Favourites API - -The [Favourites API](./apis/subsystems/favourites/index.md) allows you to mark items as favourites for a user and manage these favourites. This is often referred to as 'Starred'. - -### H5P API (h5p) - -The [H5P API](https://docs.moodle.org/dev/H5P_API) allows plugins to make some decisions/implementations related to the [H5P integration](https://docs.moodle.org/dev/H5P). - -### Lock API (lock) - -The [Lock API](./apis/core/lock/index.md) lets you synchronise processing between multiple requests, even for separate nodes in a cluster. - -### Message API (message) - -The [Message API](/docs/apis/core/message/index.md) lets you post messages to users. They decide how they want to receive them. - -### Media API (media) - -The [Media](https://docs.moodle.org/dev/Media_players#Using_media_players) API can be used to embed media items such as audio, video, and Flash. - -### My profile API - -The [My profile API](https://docs.moodle.org/dev/My_profile_API) is used to add things to the profile page. - -### OAuth 2 API (oauth2) - -The [OAuth 2 API](https://docs.moodle.org/dev/OAuth_2_API) is used to provide a common place to configure and manage external systems using OAuth 2. - -### Payment API (payment) - -The [Payment API](https://docs.moodle.org/dev/Payment_API) deals with payments. - -### Preference API (preference) - -The [Preference API](./apis/core/preference/index.md) is a simple way to store and retrieve preferences for individual users. - -### Portfolio API (portfolio) - -The [Portfolio API](https://docs.moodle.org/dev/Portfolio_API) allows you to add portfolio interfaces on your pages and allows users to package up data to send to their portfolios. - -### Privacy API (privacy) - -The [Privacy API](./apis/subsystems/privacy/index.md) allows you to describe the personal data that you store, and provides the means for that data to be discovered, exported, and deleted on a per-user basis. -This allows compliance with regulation such as the General Data Protection Regulation (GDPR) in Europe. - -### Rating API (rating) - -The [Rating API](https://docs.moodle.org/dev/Rating_API) lets you create AJAX rating interfaces so that users can rate items in your plugin. In an activity module, you may choose to aggregate ratings to form grades. - - -### Report builder API (reportbuilder) - -The [Report builder API](/docs/apis/core/reportbuilder/index.md) allows you to create reports in your plugin, as well as providing custom reporting data which users can use to build their own reports. - -### RSS API (rss) - -The [RSS API](https://docs.moodle.org/dev/RSS_API) allows you to create secure RSS feeds of data in your module. - -### Search API (search) - -The [Search API](https://docs.moodle.org/dev/Search_API) allows you to index contents in a search engine and query the search engine for results. - -### Tag API (tag) - -The [Tag API](./apis/subsystems/tag/index.md) allows you to store tags (and a tag cloud) to items in your module. - -### Task API (task) - -The [Task API](./apis/subsystems/task/index.md) lets you run jobs in the background. Either once off, or on a regular schedule. - -### Time API (time) - -The [Time API](./apis/subsystems/time/index.md) takes care of translating and displaying times between users in the site. - -### Testing API (test) - -The testing API contains the Unit test API ([PHPUnit](/general/development/tools/phpunit)) and Acceptance test API ([Acceptance testing](/general/development/tools/behat)). Ideally all new code should have unit tests written FIRST. - -### User-related APIs (user) - -This is a rather informal grouping of miscellaneous [User-related APIs](./apis/core/user/index.md) relating to sorting and searching lists of users. - -### Web services API (webservice) - -The [Web services API](./apis/subsystems/external/writing-a-service.md) allows you to expose particular functions (usually external functions) as web services. - -### Badges API (badges) - -The [https://docs.moodle.org/dev/OpenBadges_User_Documentation Badges] user documentation (is a temp page until we compile a proper page with all the classes and APIs that allows you to manage particular badges and OpenBadges Backpack). - -### Custom fields API (customfield) - -The [Custom fields API](/docs/apis/core/customfields/index.md) allows you to configure and add custom fields for different entities - -## Activity module APIs - -Activity modules are the most important plugin in Moodle. There are several core APIs that service only Activity modules. - -### Activity completion API (completion) - -The [Activity completion API](./apis/core/activitycompletion/index.md) is to indicate to the system how activities are completed. - -### Advanced grading API (grading) - -The [Advanced grading API](./apis/core/grading/index.md) allows you to add more advanced grading interfaces (such as rubrics) that can produce simple grades for the gradebook. - -### Conditional activities API (condition) - deprecated in 2.7 - -The deprecated [Conditional activities API](./apis/core/conditionalactivities/index.md) used to provide conditional access to modules and sections in Moodle 2.6 and below. It has been replaced by the [Availability API](./apis/subsystems/availability/index.md). - -### Groups API (group) - -The [Groups API](./apis/subsystems/group/index.md) allows you to check the current activity group mode and set the current group. - -### Gradebook API (grade) - -The [Gradebook API](https://docs.moodle.org/dev/Gradebook_API) allows you to read and write from the gradebook. It also allows you to provide an interface for detailed grading information. - -### Plagiarism API (plagiarism) - -The [Plagiarism API](./apis/subsystems/plagiarism.md) allows your activity module to send files and data to external services to have them checked for plagiarism. - -### Question API (question) - -The [Question API](https://docs.moodle.org/dev/Question_API) (which can be divided into the Question bank API and the Question engine API), can be used by activities that want to use questions from the question bank. - -## See also - - -- [Plugins](https://docs.moodle.org/dev/Plugins) - plugin types also have their own APIs -- [Callbacks](https://docs.moodle.org/dev/Callbacks) - list of all callbacks in Moodle -- [Coding style](/general/development/policies/codingstyle) - general information about writing PHP code for Moodle -- [Session locks](https://docs.moodle.org/dev/Session_locks) diff --git a/versioned_docs/version-4.2/apis/_files/amd-dir.mdx b/versioned_docs/version-4.2/apis/_files/amd-dir.mdx deleted file mode 100644 index b22f14b4cd..0000000000 --- a/versioned_docs/version-4.2/apis/_files/amd-dir.mdx +++ /dev/null @@ -1,10 +0,0 @@ - -JavaScript in Moodle is written in the ESM format, and transpiled into AMD modules for deployment. - -The [Moodle JavaScript Guide](../guides/javascript) has detailed information and examples on writing JavaScript in Moodle. Further information is also available in the [JavaScript Modules](../../guides/javascript/modules.md) documentation. - -:::caution - -Although the AMD module format is supported, all new JavaScript is written in the EcmaScript Module (ESM) format. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/amd-dir.tsx b/versioned_docs/version-4.2/apis/_files/amd-dir.tsx deleted file mode 100644 index 3587716005..0000000000 --- a/versioned_docs/version-4.2/apis/_files/amd-dir.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './amd-dir.mdx'; - -const defaultExample = ` -import {fetchThings} from './repository'; - -export const updateThings = (thingData) => { - return fetchThings(thingData); -}; -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/backup-dir.mdx b/versioned_docs/version-4.2/apis/_files/backup-dir.mdx deleted file mode 100644 index 7b77168eb2..0000000000 --- a/versioned_docs/version-4.2/apis/_files/backup-dir.mdx +++ /dev/null @@ -1,7 +0,0 @@ - -If your plugin stores data then you may need to implement the Backup feature which allows the activity to backed up, restored, and duplicated. - -For more information on Backup and restore, see the following: - -- [Backup 2.0 for developers](https://docs.moodle.org/dev/Backup_2.0_for_developers) -- [Restore 2.0 for developers](https://docs.moodle.org/dev/Restore_2.0_for_developers) diff --git a/versioned_docs/version-4.2/apis/_files/backup-dir.tsx b/versioned_docs/version-4.2/apis/_files/backup-dir.tsx deleted file mode 100644 index 00e6225317..0000000000 --- a/versioned_docs/version-4.2/apis/_files/backup-dir.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './backup-dir.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/changes.mdx b/versioned_docs/version-4.2/apis/_files/changes.mdx deleted file mode 100644 index d4386313c8..0000000000 --- a/versioned_docs/version-4.2/apis/_files/changes.mdx +++ /dev/null @@ -1,7 +0,0 @@ - -If your plugin includes a changelog in its root directory, this will be used to automatically pre-fill the release notes field when uploading new versions of your plugin to the [Plugins directory](https://docs.moodle.org/dev/Plugins_directory). This file can be in any of the following locations: - -- `CHANGES.md`: as a markdown file; or -- `CHANGES.txt`: as a text file; or -- `CHANGES.html`: as an HTML file; or -- `CHANGES`: as a text file. diff --git a/versioned_docs/version-4.2/apis/_files/changes.tsx b/versioned_docs/version-4.2/apis/_files/changes.tsx deleted file mode 100644 index 7ba853911c..0000000000 --- a/versioned_docs/version-4.2/apis/_files/changes.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './changes.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/classes-dir.mdx b/versioned_docs/version-4.2/apis/_files/classes-dir.mdx deleted file mode 100644 index d5a522cef6..0000000000 --- a/versioned_docs/version-4.2/apis/_files/classes-dir.mdx +++ /dev/null @@ -1,9 +0,0 @@ - -Moodle supports, and recommends, the use of autoloaded PHP classes. - -By placing files within the `classes` directory or appropriate sub-directories, and with the correct PHP Namespace, and class name, Moodle is able to autoload classes without the need to manually require, or include them. - -Details on these rules and conventions are available in the following documentation: - -- [Coding style - namespace conventions](/general/development/policies/codingstyle#namespaces) -- [Automatic class loading](https://docs.moodle.org/dev/Automatic_class_loading) diff --git a/versioned_docs/version-4.2/apis/_files/classes-dir.tsx b/versioned_docs/version-4.2/apis/_files/classes-dir.tsx deleted file mode 100644 index 7bacc979f6..0000000000 --- a/versioned_docs/version-4.2/apis/_files/classes-dir.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './classes-dir.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/cli-dir.mdx b/versioned_docs/version-4.2/apis/_files/cli-dir.mdx deleted file mode 100644 index 8757cadb97..0000000000 --- a/versioned_docs/version-4.2/apis/_files/cli-dir.mdx +++ /dev/null @@ -1,8 +0,0 @@ - -For plugins which make use of [CLI scripts](https://docs.moodle.org/dev/CLI_scripts), the convention is that these are placed into the `cli` folder to make their purpose clear, and easy to find. - -:::caution - -All CLI scripts **must** declare themselves as being a CLI script by defining the `CLI_SCRIPT` constant to true before including `config.php`. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/cli-dir.tsx b/versioned_docs/version-4.2/apis/_files/cli-dir.tsx deleted file mode 100644 index 94f11fcb00..0000000000 --- a/versioned_docs/version-4.2/apis/_files/cli-dir.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './cli-dir.mdx'; - -const defaultExample = `define('CLI_SCRIPT', true); - -require_once(__DIR__ . '/../../config.php'); -require_once("{$CFG->libdir}/clilib.php"); - -// Your CLI features go here. -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-access-php.mdx b/versioned_docs/version-4.2/apis/_files/db-access-php.mdx deleted file mode 100644 index f4bd89b3a4..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-access-php.mdx +++ /dev/null @@ -1,13 +0,0 @@ - - -The `db/access.php` file contains the __initial__ configuration for a plugin's access control rules. - -Access control is handled in Moodle by the use of Roles, and Capabilities. You can read more about these in the [Access API](../subsystems/access.md) documentation. - -:::caution Changing initial configuration - -If you make changes to the initial configuration of _existing_ access control rules, these will only take effect for _new installations of your plugin_. Any existing installation **will not** be updated with the latest configuration. - -Updating existing capability configuration for an installed site is not recommended as it may have already been modified by an administrator. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/db-access-php.tsx b/versioned_docs/version-4.2/apis/_files/db-access-php.tsx deleted file mode 100644 index 877cd86aae..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-access-php.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-access-php.mdx'; - -const defaultExample = `$capabilities = [ - // Ability to use the plugin. - 'plugintype/pluginname:useplugininstance' => [ - 'riskbitmask' => RISK_XSS, - 'captype' => 'write', - 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => [ - 'manager' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - ], - ], -]; -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-events-php.mdx b/versioned_docs/version-4.2/apis/_files/db-events-php.mdx deleted file mode 100644 index 11667d3c5e..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-events-php.mdx +++ /dev/null @@ -1,14 +0,0 @@ - -Moodle supports a feature known as _ [Event observers](https://docs.moodle.org/dev/Events_API#Event_observers) _ to allow components to make changes when certain events take place. - -The `db/events.php` file allows you define any event subscriptions that your plugin needs to listen for. - -Event subscriptions are a convenient way to observe events generated elsewhere in Moodle. - -:::caution Communication between components - -You _should not_ use event subscriptions to subscribe to events belonging to other plugins, without defining a dependency upon that plugin. - -See the [Component communication principles](/general/development/policies/component-communication#event-observers) documentation for a description of some of the risks of doing so. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/db-events-php.tsx b/versioned_docs/version-4.2/apis/_files/db-events-php.tsx deleted file mode 100644 index 71e928813f..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-events-php.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-events-php.mdx'; - -const defaultExample = `$observers = [ - [ - 'eventname' => '\\core\\event\\course_module_created', - 'callback' => '\\plugintype_pluginname\\event\\observer\\course_module_created::store', - 'priority' => 1000, - ], -]; -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-install-php.mdx b/versioned_docs/version-4.2/apis/_files/db-install-php.mdx deleted file mode 100644 index e91709f741..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-install-php.mdx +++ /dev/null @@ -1,10 +0,0 @@ - -The `db/install.php` file allows you define a post-installation hook, which is called immediately after the initial creation of your database schema. - -:::caution - -This file is not used at all after the _initial_ installation of your plugin. - -It is _not called_ during any upgrade. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/db-install-php.tsx b/versioned_docs/version-4.2/apis/_files/db-install-php.tsx deleted file mode 100644 index 3657478436..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-install-php.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-install-php.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-install-xml.mdx b/versioned_docs/version-4.2/apis/_files/db-install-xml.mdx deleted file mode 100644 index 4af56d4989..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-install-xml.mdx +++ /dev/null @@ -1,8 +0,0 @@ - -The `install.xml` file is used to define any database tables, fields, indexes, and keys, which should be created for a plugin during its initial installation. - -:::caution - -When creating or updating the `install.xml` you **must** use the built-in [XMLDB editor](https://docs.moodle.org/dev/XMLDB_Documentation) within Moodle. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/db-messages-php.mdx b/versioned_docs/version-4.2/apis/_files/db-messages-php.mdx deleted file mode 100644 index 000225f1dc..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-messages-php.mdx +++ /dev/null @@ -1,4 +0,0 @@ - -The `db/messages.php` file allows you to declare the messages that your plugin sends. - -See the [Message API](https://docs.moodle.org/dev/Message_API) documentation for further information. diff --git a/versioned_docs/version-4.2/apis/_files/db-messages-php.tsx b/versioned_docs/version-4.2/apis/_files/db-messages-php.tsx deleted file mode 100644 index f8c576ec84..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-messages-php.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-messages-php.mdx'; - -const defaultExample = ` -$messageproviders = [ - 'things' => [ - 'defaults' => [ - 'airnotifier' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED, - ], - ], -]; -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-mobile-php.mdx b/versioned_docs/version-4.2/apis/_files/db-mobile-php.mdx deleted file mode 100644 index b16a65f3c1..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-mobile-php.mdx +++ /dev/null @@ -1,6 +0,0 @@ - -The Moodle Mobile remote add-on is the mobile app version of the plugin that will be loaded when a user accesses the plugin on the app. - -A plugin can include several Mobile add-ons. Each add-on must indicate a unique name. - -See the [Moodle App Plugins development guide](/general/app/development/plugins-development-guide) for more information on configuring your plugin for the Moodle App. diff --git a/versioned_docs/version-4.2/apis/_files/db-mobile-php.tsx b/versioned_docs/version-4.2/apis/_files/db-mobile-php.tsx deleted file mode 100644 index 322b29f8f9..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-mobile-php.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-mobile-php.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.mdx b/versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.mdx deleted file mode 100644 index 91e69e0053..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.mdx +++ /dev/null @@ -1,8 +0,0 @@ - -Details of classes that have been renamed to fit in with autoloading. See [forum discussion](https://moodle.org/mod/forum/discuss.php?d=262403) for details. - -:::note -Adding renamed or moved classes to `renamedclasses.php` is only necessary when the class is part of the component's API where it can be reused by other components, especially by third-party plugins. This is to maintain backwards-compatibility in addition to autoloading purposes. - -If the renamed or moved class is private/internal to the component and is not subject for external use, there is no need to add it to `renamedclasses.php`. -::: diff --git a/versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.tsx b/versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.tsx deleted file mode 100644 index ef6d5b81d6..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-renamedclasses-php.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-renamedclasses-php.mdx'; - -const defaultExample = ` -defined('MOODLE_INTERNAL') || die; - -$renamedclasses = [ - 'old_class_name' => 'fully_qualified\\\\new\\\\name', - - // Examples: - 'assign_header' => 'mod_assign\\\\output\\\\header', - '\\assign_header' => 'mod_assign\\\\output\\\\header', - '\\assign' => 'mod_assign\\\\assignment', - - // Incorrect: - // The new class name should _not_ have a leading \\. - 'assign_header' => '\\\\mod_assign\\\\output\\\\header', -]; -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-services-php.mdx b/versioned_docs/version-4.2/apis/_files/db-services-php.mdx deleted file mode 100644 index 8e34f888db..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-services-php.mdx +++ /dev/null @@ -1,16 +0,0 @@ - -The `db/services.php` file is used to describe the external functions available for use in web services. This includes - -web service functions defined for JavaScript, and for the [Moodle Mobile App](/general/app). - -:::note - -Web services should be named following the [naming convention for web services](https://docs.moodle.org/dev/Web_service_API_functions#Naming_convention). - -::: - -For further information on external functions and web services, see: - -- [Adding a web service to a plugin](../subsystems/external/writing-a-service.md) -- [Web services API](../subsystems/external/writing-a-service.md) -- [External functions API](../subsystems/external/functions.md) diff --git a/versioned_docs/version-4.2/apis/_files/db-services-php.tsx b/versioned_docs/version-4.2/apis/_files/db-services-php.tsx deleted file mode 100644 index 04a8536db3..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-services-php.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-services-php.mdx'; - -const defaultExample = ` -$functions = [ - 'plugintype_pluginname_create_things' => [ - 'classname' => 'plugintype_pluginname\\external\\create_things', - 'description' => 'Create a new thing', - 'type' => 'write', - 'ajax' => true, - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ], - ], -]; -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-tasks-example.php b/versioned_docs/version-4.2/apis/_files/db-tasks-example.php deleted file mode 100644 index 1c8ac31514..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-tasks-example.php +++ /dev/null @@ -1,11 +0,0 @@ -$tasks = [ - [ - 'classname' => 'mod_example\task\do_something', - 'blocking' => 0, - 'minute' => '30', - 'hour' => '17', - 'day' => '*', - 'month' => '1,7', - 'dayofweek' => '0', - ], -]; diff --git a/versioned_docs/version-4.2/apis/_files/db-tasks-php.mdx b/versioned_docs/version-4.2/apis/_files/db-tasks-php.mdx deleted file mode 100644 index ea33364e06..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-tasks-php.mdx +++ /dev/null @@ -1,18 +0,0 @@ - - -The `db/tasks.php` file contains the initial schedule configuration for each of your plugins _scheduled_ tasks. Adhoc tasks are not run on a regular schedule and therefore are not described in this file. - -:::caution Editing the schedule for an existing task - -If an existing task is edited, it will only be updated in the database if the administrator has not customised the schedule of that task in any way. - -::: - -The following fields also accept a value of `R`, which indicates that Moodle should choose a random value for that field: - -- minute -- hour -- dayofweek -- day - -See [db/tasks.php](../commonfiles/db-tasks.php/index.md) for full details of the file format. diff --git a/versioned_docs/version-4.2/apis/_files/db-tasks-php.tsx b/versioned_docs/version-4.2/apis/_files/db-tasks-php.tsx deleted file mode 100644 index 68c9ac809b..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-tasks-php.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary, type ComponentFileSummaryProps } from '../../_utils'; -import DefaultDescription from './db-tasks-php.mdx'; -// eslint-disable-next-line import/no-webpack-loader-syntax, import/no-unresolved -import DefaultExample from '!!raw-loader!./db-tasks-example.php'; - -export default (initialProps: ComponentFileSummaryProps): JSX.Element => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-uninstall-php.mdx b/versioned_docs/version-4.2/apis/_files/db-uninstall-php.mdx deleted file mode 100644 index 5ed3089e4b..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-uninstall-php.mdx +++ /dev/null @@ -1,2 +0,0 @@ - -The `db/uninstall.php` file allows you define a pre-uninstallation hook, which is called immediately before all table and data from your plugin are removed. diff --git a/versioned_docs/version-4.2/apis/_files/db-uninstall-php.tsx b/versioned_docs/version-4.2/apis/_files/db-uninstall-php.tsx deleted file mode 100644 index 8d4f8c2081..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-uninstall-php.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-uninstall-php.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/db-upgrade-php.mdx b/versioned_docs/version-4.2/apis/_files/db-upgrade-php.mdx deleted file mode 100644 index 3dde622bc7..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-upgrade-php.mdx +++ /dev/null @@ -1,30 +0,0 @@ - -The `db/upgrade.php` file contains upgrade steps, including database schema changes, changes to settings, and other steps which must be performed during upgrade. - -See the [Upgrade API](../../guides/upgrade/index.md) documentation for further information. - -:::danger Generating Database Schema changes - -When making changes to the database schema you **must** use the build-in [XMLDB editor](https://docs.moodle.org/dev/XMLDB_Documentation) within -Moodle. This can be used to generate php upgrade steps. - -The [install.xml](../commonfiles/index.mdx#dbinstallxml) schema must match the schema generated by the upgrade at all times. - -::: - -To create an upgrade step you must: - -1. Use the [XMLDB editor](/general/development/tools/xmldb) to create the definition of the new fields -1. Update the `install.xml` from the XMLDB editor -1. Generate the PHP upgrade steps from within the XMLDB Editor -1. Update the version number in your `version.php` - -:::tip - -In many cases you will be able to combine multiple upgrade steps into a single version change. - -::: - -When a version number increment is detected during an upgrade, the `xmldb_[pluginname]_upgrade` function is called with the old version number as the first argument. - -See the [Upgrade API](../../guides/upgrade/index.md) documentation for more information on the upgrade process. diff --git a/versioned_docs/version-4.2/apis/_files/db-upgrade-php.tsx b/versioned_docs/version-4.2/apis/_files/db-upgrade-php.tsx deleted file mode 100644 index 0078065bb2..0000000000 --- a/versioned_docs/version-4.2/apis/_files/db-upgrade-php.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-upgrade-php.mdx'; - -const defaultExample = ` -function xmldb_certificate_upgrade($oldversion = 0) { - if ($oldversion < 2012091800) { - // Add new fields to certificate table. - $table = new xmldb_table('certificate'); - $field = new xmldb_field('showcode'); - $field->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'savecert'); - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - // Add new fields to certificate_issues table. - $table = new xmldb_table('certificate_issues'); - $field = new xmldb_field('code'); - $field->set_attributes(XMLDB_TYPE_CHAR, '50', null, null, null, null, 'certificateid'); - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - - // Certificate savepoint reached. - upgrade_mod_savepoint(true, 2012091800, 'certificate'); - } -}`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/environment-xml.mdx b/versioned_docs/version-4.2/apis/_files/environment-xml.mdx deleted file mode 100644 index 62af6b1660..0000000000 --- a/versioned_docs/version-4.2/apis/_files/environment-xml.mdx +++ /dev/null @@ -1,4 +0,0 @@ - -A plugin can declare its own environment requirements, in addition to those declared by Moodle core. These may includes features such as PHP extension requirements, version requirements, and similar items. - -Further information on this file and its format can be found in the [Environment checking](https://docs.moodle.org/dev/Environment_checking) documentation. diff --git a/versioned_docs/version-4.2/apis/_files/environment-xml.tsx b/versioned_docs/version-4.2/apis/_files/environment-xml.tsx deleted file mode 100644 index ce2afb8324..0000000000 --- a/versioned_docs/version-4.2/apis/_files/environment-xml.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './environment-xml.mdx'; - -const defaultExample = ` - - - - - - - - -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/index.tsx b/versioned_docs/version-4.2/apis/_files/index.tsx deleted file mode 100644 index d106049452..0000000000 --- a/versioned_docs/version-4.2/apis/_files/index.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ - -import AmdDir from './amd-dir'; -import BackupDir from './backup-dir'; -import CLIDir from './cli-dir'; -import Changes from './changes'; -import ClassesDir from './classes-dir'; -import DbAccessPHP from './db-access-php'; -import DbEventsPHP from './db-events-php'; -import DbInstallPHP from './db-install-php'; -import DbInstallXML from './install-xml'; -import DbMessagesPHP from './db-messages-php'; -import DbMobilePHP from './db-mobile-php'; -import DbRenamedclassesPHP from './db-renamedclasses-php'; -import DbServicesPHP from './db-services-php'; -import DbTasksPHP from './db-tasks-php'; -import DbUninstallPHP from './db-uninstall-php'; -import DbUpgradePHP from './db-upgrade-php'; -import EnvironmentXML from './environment-xml'; -import Lang from './lang'; -import Lib from './lib'; -import LocalLib from './locallib'; -import PixDir from './pix-dir'; -import Readme from './readme'; -import ReadmeMoodleTXT from './readme_moodle-txt'; -import SettingsPHP from './settings-php'; -import StylesCSS from './styles-css'; -import ThirdpartylibsXML from './thirdpartylibs-xml'; -import UpgradeTXT from './upgrade-txt'; -import VersionPHP from './version-php'; -import YUIDir from './yui-dir'; - -export { - AmdDir, - BackupDir, - CLIDir, - Changes, - ClassesDir, - DbAccessPHP, - DbEventsPHP, - DbInstallPHP, - DbInstallXML, - DbMessagesPHP, - DbMobilePHP, - DbRenamedclassesPHP, - DbServicesPHP, - DbTasksPHP, - DbUninstallPHP, - EnvironmentXML, - Lang, - Lib, - LocalLib, - PixDir, - Readme, - ReadmeMoodleTXT, - SettingsPHP, - StylesCSS, - ThirdpartylibsXML, - DbUpgradePHP, - UpgradeTXT, - VersionPHP, - YUIDir, -}; diff --git a/versioned_docs/version-4.2/apis/_files/install-xml.tsx b/versioned_docs/version-4.2/apis/_files/install-xml.tsx deleted file mode 100644 index 98b03c8821..0000000000 --- a/versioned_docs/version-4.2/apis/_files/install-xml.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './db-install-xml.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/lang-extra.md b/versioned_docs/version-4.2/apis/_files/lang-extra.md deleted file mode 100644 index f6f10fb772..0000000000 --- a/versioned_docs/version-4.2/apis/_files/lang-extra.md +++ /dev/null @@ -1,15 +0,0 @@ - - -:::caution Activity modules are different - -Activity modules do not use the __frankenstyle__ name as a filename, they use the plugin name. For example the forum activity plugin: - -```php -// Plugin type: `mod` -// Plugin name: `forum` -// Frankenstyle plugin name: `mod_forum` -// Plugin location: `mod/forum` -// Language string location: `mod/forum/lang/en/forum.php` -``` - -::: diff --git a/versioned_docs/version-4.2/apis/_files/lang.md b/versioned_docs/version-4.2/apis/_files/lang.md deleted file mode 100644 index c73920bb90..0000000000 --- a/versioned_docs/version-4.2/apis/_files/lang.md +++ /dev/null @@ -1,25 +0,0 @@ - - -Each plugin must define a set of language strings with, at a minimum, an English translation. These are specified in the plugin's `lang/en` directory in a file named after the plugin. For example the LDAP authentication plugin: - -```php -// Plugin type: `auth` -// Plugin name: `ldap` -// Frankenstyle plugin name: `auth_ldap` -// Plugin location: `auth/ldap` -// Language string location: `auth/ldap/lang/en/auth_ldap.php` -``` - -:::warning - -Every plugin _must_ define the name of the plugin, or its `pluginname`. - -::: - -The `get_string` API can be used to translate a string identifier back into a translated string. - -``` -get_string('pluginname', '[plugintype]_[pluginname]'); -``` - -- See the [String API](https://docs.moodle.org/dev/String_API#Adding_language_file_to_plugin) documentation for more information on language files. diff --git a/versioned_docs/version-4.2/apis/_files/lang.tsx b/versioned_docs/version-4.2/apis/_files/lang.tsx deleted file mode 100644 index 8356a3d5af..0000000000 --- a/versioned_docs/version-4.2/apis/_files/lang.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { ComponentFileSummaryProps } from '../../_utils'; -import DefaultDescription from './lang.md'; - -const defaultExample = "$string['pluginname'] = 'The name of my plugin will go here';"; - -export default (initialProps: ComponentFileSummaryProps): JSX.Element => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/lib.mdx b/versioned_docs/version-4.2/apis/_files/lib.mdx deleted file mode 100644 index e9f02313d0..0000000000 --- a/versioned_docs/version-4.2/apis/_files/lib.mdx +++ /dev/null @@ -1,11 +0,0 @@ - - -The `lib.php` file is a legacy file which acts as a bridge between Moodle core, and the plugin. In recent plugins it is should only used to define callbacks and related functionality which currently is not supported as an auto-loadable class. - -All functions defined in this file **must** meet the requirements set out in the relevant section of the [Coding style](/general/development/policies/codingstyle#functions-and-methods). - -:::note Performance impact - -Moodle core often loads all the lib.php files of a given plugin types. For performance reasons, it is strongly recommended to keep this file as small as possible and have just required code implemented in it. All the plugin's internal logic should be implemented in the auto-loaded classes. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/lib.tsx b/versioned_docs/version-4.2/apis/_files/lib.tsx deleted file mode 100644 index bc3ddec6b9..0000000000 --- a/versioned_docs/version-4.2/apis/_files/lib.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './lib.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/locallib.mdx b/versioned_docs/version-4.2/apis/_files/locallib.mdx deleted file mode 100644 index fb3cab2811..0000000000 --- a/versioned_docs/version-4.2/apis/_files/locallib.mdx +++ /dev/null @@ -1,14 +0,0 @@ - - - -:::caution Legacy feature - -The use of this file is no longer recommended, and new uses of it will not be permitted in core code. - -::: - -Rather than creating global functions in a global namespace in a locallib.php file, you should use autoloaded classes which are located in the classes/ directory. - -Where this file is in use, all functions **must** meet the requirements set out in the relevant section of the [Coding style](/general/development/policies/codingstyle#functions-and-methods) - -Existing functions which have been incorrectly named **will not** be accepted as an example of an existing convention. Existing functions which are incorrectly named **should** be converted to use a namespaced class. diff --git a/versioned_docs/version-4.2/apis/_files/locallib.tsx b/versioned_docs/version-4.2/apis/_files/locallib.tsx deleted file mode 100644 index 0093700154..0000000000 --- a/versioned_docs/version-4.2/apis/_files/locallib.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './locallib.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/pix-dir.mdx b/versioned_docs/version-4.2/apis/_files/pix-dir.mdx deleted file mode 100644 index f58f9c6fee..0000000000 --- a/versioned_docs/version-4.2/apis/_files/pix-dir.mdx +++ /dev/null @@ -1,6 +0,0 @@ - -Plugins can provide icons in several formats, and most plugin types require that a default icon be provided. - -Where a browser supports it, the `svg` format is used, falling back to `png` formats when an SVG is unavailable. - -Full details of the correct naming, sizing, and design guidelines for icons in Moodle can be found in the [Moodle icons](https://docs.moodle.org/dev/Moodle_icons) documentation. diff --git a/versioned_docs/version-4.2/apis/_files/pix-dir.tsx b/versioned_docs/version-4.2/apis/_files/pix-dir.tsx deleted file mode 100644 index cdb803f34a..0000000000 --- a/versioned_docs/version-4.2/apis/_files/pix-dir.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './pix-dir.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/readme.mdx b/versioned_docs/version-4.2/apis/_files/readme.mdx deleted file mode 100644 index 185121a363..0000000000 --- a/versioned_docs/version-4.2/apis/_files/readme.mdx +++ /dev/null @@ -1,4 +0,0 @@ - -We recommend that you include any additional information for your plugin in a project readme file. Ideally this should act as an offline version of all information in your plugin's page in the [Plugins directory](https://docs.moodle.org/dev/Plugins_directory). - -We recommend creating your readme file in either a `README.md`, or `README.txt` format. diff --git a/versioned_docs/version-4.2/apis/_files/readme.tsx b/versioned_docs/version-4.2/apis/_files/readme.tsx deleted file mode 100644 index 8999ddaccc..0000000000 --- a/versioned_docs/version-4.2/apis/_files/readme.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './readme.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/readme_moodle-txt.mdx b/versioned_docs/version-4.2/apis/_files/readme_moodle-txt.mdx deleted file mode 100644 index ed589cbfd4..0000000000 --- a/versioned_docs/version-4.2/apis/_files/readme_moodle-txt.mdx +++ /dev/null @@ -1,5 +0,0 @@ - -When importing a third-party library into your plugin, it is advisable to create a `readme_moodle.txt` file detailing relevant information, including: - -- Download URLs -- Build instructions diff --git a/versioned_docs/version-4.2/apis/_files/readme_moodle-txt.tsx b/versioned_docs/version-4.2/apis/_files/readme_moodle-txt.tsx deleted file mode 100644 index 55827c08aa..0000000000 --- a/versioned_docs/version-4.2/apis/_files/readme_moodle-txt.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './readme_moodle-txt.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/settings-php.mdx b/versioned_docs/version-4.2/apis/_files/settings-php.mdx deleted file mode 100644 index 04b942c4c9..0000000000 --- a/versioned_docs/version-4.2/apis/_files/settings-php.mdx +++ /dev/null @@ -1,16 +0,0 @@ - -You can define settings for your plugin that the administrator can configure by creating a `settings.php` file in the root of your plugins' directory. - -:::caution - -Settings must named in the following format: - -``` -plugintype_pluginname/settingname -``` - -By following the correct naming, all settings will automatically be stored in the `config_plugins` database table. - -::: - -Full details on how to create settings are available in the [Admin settings](../subsystems/admin/index.md) documentation. diff --git a/versioned_docs/version-4.2/apis/_files/settings-php.tsx b/versioned_docs/version-4.2/apis/_files/settings-php.tsx deleted file mode 100644 index 9dd13af88e..0000000000 --- a/versioned_docs/version-4.2/apis/_files/settings-php.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './settings-php.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/styles-css.mdx b/versioned_docs/version-4.2/apis/_files/styles-css.mdx deleted file mode 100644 index e62a0dd592..0000000000 --- a/versioned_docs/version-4.2/apis/_files/styles-css.mdx +++ /dev/null @@ -1,11 +0,0 @@ - -Plugins may define a '/styles.css' to provide plugin-specific styling. See the following for further documentation: - -- [Plugin contribution checklist#CSS styles](https://docs.moodle.org/dev/Plugin_contribution_checklist#CSS_styles) -- [CSS Coding Style](https://docs.moodle.org/dev/CSS_Coding_Style) - -:::tip Avoid custom styles where possible - -Rather than writing custom CSS for your plugin, where possible apply Bootstrap classes to the DOM elements in your output. These will be easier to maintain and will adopt most colour, branding, and other customisations applied to a theme. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/styles-css.tsx b/versioned_docs/version-4.2/apis/_files/styles-css.tsx deleted file mode 100644 index 21ea5adcc5..0000000000 --- a/versioned_docs/version-4.2/apis/_files/styles-css.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './styles-css.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.mdx b/versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.mdx deleted file mode 100644 index 301dde8126..0000000000 --- a/versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.mdx +++ /dev/null @@ -1,14 +0,0 @@ - -Details of all third-party libraries should be declared in the `thirdpartylibs.xml` file. - -This information is used to generate ignore file configuration for linting tools. For Moodle core it is also used to generate library information as part of release notes and credits. - -Within the XML the `location` is a file, or directory, relative to your plugin's root. - -:::caution Licensing - -The license of any third-party code included in your plugin, and within the `thirdpartylibs.xml` file **must** be [compatible with the GNU GPLv3](http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses). - -::: - -See the [Third Party Libraries](https://docs.moodle.org/dev/Third_Party_Libraries) documentation for further information. diff --git a/versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.tsx b/versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.tsx deleted file mode 100644 index 052e1a2ed0..0000000000 --- a/versioned_docs/version-4.2/apis/_files/thirdpartylibs-xml.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './thirdpartylibs-xml.mdx'; - -const defaultExample = ` - - - javascript/html5shiv.js - Html5Shiv - 3.6.2 - Apache - 2.0 - - - vendor/guzzle/guzzle/ - guzzle - v3.9.3 - MIT - - -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/upgrade-php.mdx b/versioned_docs/version-4.2/apis/_files/upgrade-php.mdx deleted file mode 100644 index 41f6748ed8..0000000000 --- a/versioned_docs/version-4.2/apis/_files/upgrade-php.mdx +++ /dev/null @@ -1,13 +0,0 @@ - -The `db/upgrade.php` file contains upgrade steps, including database schema changes, changes to settings, and other steps which must be performed during upgrade. - -See the [Upgrade API](../../guides/upgrade/index.md) documentation for further information. - -:::danger Generating Database Schema changes - -When making changes to the database schema you **must** use the build-in [XMLDB editor](https://docs.moodle.org/dev/XMLDB_Documentation) within -Moodle. This can be used to generate php upgrade steps. - -The [install.xml](../commonfiles/index.mdx#dbinstallxml) schema must match the schema generated by the upgrade at all times. - -::: diff --git a/versioned_docs/version-4.2/apis/_files/upgrade-txt.mdx b/versioned_docs/version-4.2/apis/_files/upgrade-txt.mdx deleted file mode 100644 index a29d8cd37f..0000000000 --- a/versioned_docs/version-4.2/apis/_files/upgrade-txt.mdx +++ /dev/null @@ -1,56 +0,0 @@ - -Each component and subsystem may make use of an `upgrade.txt` file in the top level folder. A section title is used to identify the Moodle version where the change was introduced, and significant changes for that version relating to that component or subsystem are noted. - -For example, given an API change is applied for the upcoming Moodle version 4.1 which is still in the **main** branch (4.1dev), the version number on the `upgrade.txt`'s section title will be set to **4.1**. - -```txt title="Example 1: Change applied to the main branch" -== 4.1 == -An API change to empower educators! -``` - -#### Changes applied to multiple branches - -When changes are integrated to multiple branches, for example a stable version and the main branch, then the relevant versions used to describe the change in the `upgrade.txt` file should be the next version to be released _for each branch_. The **main** branch should always use the next major version. - -For example, if a change is applied to the **MOODLE_400_STABLE** during the development of Moodle 4.0.2, and the **main** branch during the development of Moodle 4.1, then the relevant versions will be **4.0.2** and **4.1**, respectively. The section title for the **main** branch will be the same as the one in Example 1. The section title for the **MOODLE_400_STABLE** branch will indicate the next upcoming minor version (4.0.2 in this case): - -```txt title="Example 2: Patch applied to main and MOODLE_400_STABLE" -== 4.0.2 == -An API change to empower educators! -``` - -#### Mentioning other Moodle versions the change applies to - -Multiple versions within the section title are **not** allowed. However, developers may note the Moodle versions that the change applies to within the upgrade note text itself. - -```txt title="Example 3a: main (4.1dev)" -== 4.1 == -An API change to empower educators! (This was fixed in 4.1 and 4.0.2) -``` - -```txt title="Example 3b: MOODLE_400_STABLE" -== 4.0.2 == -An API change to empower educators! (This was fixed in 4.1 and 4.0.2) -``` - -```txt title="Example 3c: (INCORRECT) Multiple versions on the section title" -== 4.1, 4.0.2 == -An API change to empower educators! -``` - -#### Exception during parallel development - -When Moodle is developing two major versions in parallel, for example Moodle 3.11.0, and Moodle 4.0.0, then the -version in the earliest of the major version development branches will be used for both branches. - -For example, given we are in a parallel development situation with **MOODLE_311_STABLE** (3.11dev) and **main** (4.0dev), with Moodle 3.11 as the next upcoming major Moodle version. If an API change is applied to **MOODLE_311_STABLE**, the version number on the section title will be **3.11** for both **main** and **MOODLE_400_STABLE** branches. - -```txt title="Example 4a: main (4.0dev)" -== 3.11 == -An API change to empower educators! -``` - -```txt title="Example 4b: MOODLE_311_STABLE (3.11dev)" -== 3.11 == -An API change to empower educators! -``` diff --git a/versioned_docs/version-4.2/apis/_files/upgrade-txt.tsx b/versioned_docs/version-4.2/apis/_files/upgrade-txt.tsx deleted file mode 100644 index db928bfec3..0000000000 --- a/versioned_docs/version-4.2/apis/_files/upgrade-txt.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './upgrade-txt.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/_files/version-php.mdx b/versioned_docs/version-4.2/apis/_files/version-php.mdx deleted file mode 100644 index 23c9c7847a..0000000000 --- a/versioned_docs/version-4.2/apis/_files/version-php.mdx +++ /dev/null @@ -1,11 +0,0 @@ - -The version.php contains metadata about the plugin. - -It is used during the installation and upgrade of the plugin. - -This file contains metadata used to describe the plugin, and includes information such as: - -- the version number -- a list of dependencies -- the minimum Moodle version required -- maturity of the plugin diff --git a/versioned_docs/version-4.2/apis/_files/version-php.tsx b/versioned_docs/version-4.2/apis/_files/version-php.tsx deleted file mode 100644 index f855221dcb..0000000000 --- a/versioned_docs/version-4.2/apis/_files/version-php.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import { type ComponentFileSummaryProps } from '@site/src/components/ComponentFileSummary'; -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import DefaultDescription from './version-php.mdx'; - -const defaultExample = `defined('MOODLE_INTERNAL') || die(); - -$plugin->version = TODO; -$plugin->requires = TODO; -$plugin->supported = TODO; // Available as of Moodle 3.9.0 or later. -$plugin->incompatible = TODO; // Available as of Moodle 3.9.0 or later. -$plugin->component = 'TODO_FRANKENSTYLE'; -$plugin->maturity = MATURITY_STABLE; -$plugin->release = 'TODO'; - -$plugin->dependencies = [ - 'mod_forum' => 2022042100, - 'mod_data' => 2022042100 -]; -`; - -export default function VersionPHP(props: ComponentFileSummaryProps): JSX.Element { - return ( - - ); -} diff --git a/versioned_docs/version-4.2/apis/_files/yui-dir.mdx b/versioned_docs/version-4.2/apis/_files/yui-dir.mdx deleted file mode 100644 index 4ec0275759..0000000000 --- a/versioned_docs/version-4.2/apis/_files/yui-dir.mdx +++ /dev/null @@ -1,11 +0,0 @@ - -In older versions of Moodle, JavaScript was written in the YUI format. This is being phased out in favour of [JavaScript Modules](../../guides/javascript/modules.md), although some older uses still remain in Moodle core. - -- [YUI/Modules](../../guides/javascript/yui/modules.md) -- [YUI](../../guides/javascript/yui/index.md) - -:::caution - -New YUI code will not be accepted into Moodle core, except for new plugins for the [Atto editor](../plugintypes/atto/index.md). - -::: diff --git a/versioned_docs/version-4.2/apis/_files/yui-dir.tsx b/versioned_docs/version-4.2/apis/_files/yui-dir.tsx deleted file mode 100644 index fec0d588eb..0000000000 --- a/versioned_docs/version-4.2/apis/_files/yui-dir.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../_utils'; -import type { Props } from '../../_utils'; -import DefaultDescription from './yui-dir.mdx'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/commonfiles/db-tasks.php/index.md b/versioned_docs/version-4.2/apis/commonfiles/db-tasks.php/index.md deleted file mode 100644 index 024c64999f..0000000000 --- a/versioned_docs/version-4.2/apis/commonfiles/db-tasks.php/index.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: db/tasks.php -tags: - - Plugins - - Common files - - Scheduled tasks -description: A description of the plugin scheduled task configuration file ---- - -import { LanguageProperty } from '@site/src/components'; - -If a plugin wants to configure scheduled task, two items are required: - -- a class extending the `\core\task\scheduled_task` class; and -- the `db/tasks.php` file containing its initial configuration. - -The general format of the file is as follows: - -```php -$tasks = [ - // First task configuration. - [ ... ], - - // Second task configuration. - [ ... ], -]; -``` - -Each task configuration entry has a number of possible properties, described below. - -## Task configuration entries - -### Classname - - - -The `classname` contains the fully-qualified class name where the scheduled task is located. - -```php -$tasks = [ - [ - 'classname' => 'mod_example\task\do_something', - // ... - ] -] -``` - -### Blocking - - - -Tasks can be configured to block the execution of all other tasks by setting the `blocking` property to a truthy value. - -:::caution - -Whilst this feature is available its use is _strongly_ discouraged and *will not* be accepted in Moodle core. - -::: - -```php -$tasks = [ - [ - 'classname' => 'mod_example\task\do_something', - 'blocking' => 1, - // ... - ], -]; -``` - -### Date and time fields - - - -The following date and time fields are available: - -- month -- day -- dayofweek -- hour -- month - -Each of these fields accepts one, or more values, and the format for each field is described as: - -``` - := (/)(,) - := int - := ||| - := * - := int-int - := R -``` - -:::info Random values - -A fixed random value can be selected by using a value of `R`. By specifying this option, a random day or time is chosen when the task is installed or updated. The same value will be used each time the task is scheduled. - -::: - -If no value is specified then the following defaults are used: - -- Month: `*` (Every month) -- Day: `*` (Every day) -- Day of the week: `*` (Every day of the week) -- Hour: `*` (Every hour) -- Minute: `*` (Every minute) - -:::info Day and Day of the week - -If either field is set to `*` then use the other field, otherwise the soonest value is used. - -::: - -#### Examples - -```php title="Run at a fixed time each day, randomised during installation of the task" -$tasks = [ - [ - 'classname' => 'mod_example\task\do_something', - - // Every month. - 'month' => '*', - // Every day. - 'day' => '*', - - // A fixed random hour and minute. - 'hour' => 'R', - 'month' => 'R', - ], -]; -``` - -```php title="Specifying multiple times in an hour" -$tasks = [ - [ - 'classname' => 'mod_example\task\do_something', - - // At two intervals in the hour. - 'minute' => '5, 35', - ], -]; -``` - -### Disabled tasks - -You can create a task that defaults to disabled by setting the field **disabled** to 1. Unless the administrator manually enables your task, it will not run. - -This is useful if a task is only required in certain situations and shouldn't run on every server that has your plugin installed. diff --git a/versioned_docs/version-4.2/apis/commonfiles/index.mdx b/versioned_docs/version-4.2/apis/commonfiles/index.mdx deleted file mode 100644 index 19c8ab7ee2..0000000000 --- a/versioned_docs/version-4.2/apis/commonfiles/index.mdx +++ /dev/null @@ -1,164 +0,0 @@ ---- -title: Common files -tags: - - Plugins - - API - - Subsystem ---- - -import { - AmdDir, - BackupDir, - CLIDir, - Changes, - ClassesDir, - DbAccessPHP, - DbEventsPHP, - DbInstallPHP, - DbInstallXML, - DbMessagesPHP, - DbRenamedclassesPHP, - DbServicesPHP, - DbTasksPHP, - DbUninstallPHP, - DbUpgradePHP, - EnvironmentXML, - Lang, - Lib, - LocalLib, - PixDir, - Readme, - ReadmeMoodleTXT, - SettingsPHP, - StylesCSS, - ThirdpartylibsXML, - UpgradeTXT, - VersionPHP, - YUIDir, -} from '../_files'; - - - -This page describes the common files which may be present in any Moodle subsystem or [plugin type](../plugintypes/index.md). Some of these files are mandatory and __must__ exist within a component, whilst others are optional. - -### version.php - - - -### lang/en/plugintype_pluginname.php - -import extraLangDescription from '../_files/lang-extra.md'; - - - -### lib.php - - - -### locallib.php - - - -### db/install.xml - - - -### db/upgrade.php - - - -### db/access.php - - - -### db/install.php - - - -### db/uninstall.php - - - -### db/events.php - - - -### db/messages.php - - - -### db/services.php - - - -### db/tasks.php - - - -### db/renamedclasses.php - - - -### classes/ - - - -### cli/ - - - -### settings.php - - - -### amd/ - - - -### yui/ - - - -### backup/ - - - -### styles.css - - - -### pix/icon.svg - - - -### thirdpartylibs.xml - - - -### readme_moodle.txt - - - -### upgrade.txt - - - -### environment.xml - - - -### README - - - -### CHANGES - - - -## See also - -- [Moodle architecture](https://docs.moodle.org/dev/Moodle_architecture) - general overview of Moodle code architecture -- [Plugin types](../plugintypes/index.md) - list of all supported plugin types -- [Moodle plugins directory](https://moodle.org/plugins/) - repository of contributed plugins for Moodle -- [Moodle plugin skeleton generator](https://moodle.org/plugins/tool_pluginskel) - allows to quickly generate code skeleton for a new plugin -- [Checklist for plugin contributors](https://docs.moodle.org/dev/Plugin_contribution_checklist) - read before submitting a plugin diff --git a/versioned_docs/version-4.2/apis/commonfiles/tag.php/index.md b/versioned_docs/version-4.2/apis/commonfiles/tag.php/index.md deleted file mode 100644 index fcfd89e679..0000000000 --- a/versioned_docs/version-4.2/apis/commonfiles/tag.php/index.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: tag.php -tags: - - Plugins - - Tags - - API -description: A description of the library tag.php file, describing what plugins have tags where their callbacks are located. ---- - -import { LanguageProperty } from '@site/src/components'; - -:::note -There are more options such as specifying the default value for "Standard tags", having a fixed collection or excluding from search. -::: - -## Example file - -Here is the core libraries tag.php file for reference: - -```php -. - -/** - * Tag area definitions - * - * File db/tag.php lists all available tag areas in core or a plugin. - * - * Each tag area may have the following attributes: - * - itemtype (required) - what is tagged. Must be name of the existing DB table - * - component - component responsible for tagging, if the tag area is inside a - * plugin the component must be the full frankenstyle name of the plugin - * - collection - name of the custom tag collection that will be used to store - * tags in this area. If specified aministrator will be able to neither add - * any other tag areas to this collection nor move this tag area elsewhere - * - searchable (only if collection is specified) - wether the tag collection - * should be searchable on /tag/search.php - * - showstandard - default value for the "Standard tags" attribute of the area, - * this is only respected when new tag area is added and ignored during upgrade - * - customurl (only if collection is specified) - custom url to use instead of - * /tag/search.php to display information about one tag - * - callback - name of the function that returns items tagged with this tag, - * see core_tag_tag::get_tag_index() and existing callbacks for more details, - * callback should return instance of core_tag\output\tagindex - * - callbackfile - file where callback is located (if not an autoloaded location) - * - * Language file must contain the human-readable names of the tag areas and - * collections (either in plugin language file or in component language file or - * lang/en/tag.php in case of core): - * - for item type "user": - * $string['tagarea_user'] = 'Users'; - * - for tag collection "mycollection": - * $string['tagcollection_mycollection'] = 'My tag collection'; - * - * @package core - * @copyright 2015 Marina Glancy - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$tagareas = [ - [ - 'itemtype' => 'user', // Users. - 'component' => 'core', - 'callback' => 'user_get_tagged_users', - 'callbackfile' => '/user/lib.php', - 'showstandard' => core_tag_tag::HIDE_STANDARD, - ], - [ - 'itemtype' => 'course', // Courses. - 'component' => 'core', - 'callback' => 'course_get_tagged_courses', - 'callbackfile' => '/course/lib.php', - ], - [ - 'itemtype' => 'question', // Questions. - 'component' => 'core_question', - 'multiplecontexts' => true, - ], - [ - 'itemtype' => 'post', // Blog posts. - 'component' => 'core', - 'callback' => 'blog_get_tagged_posts', - 'callbackfile' => '/blog/lib.php', - ], - [ - 'itemtype' => 'blog_external', // External blogs. - 'component' => 'core', - ], - [ - 'itemtype' => 'course_modules', // Course modules. - 'component' => 'core', - 'callback' => 'course_get_tagged_course_modules', - 'callbackfile' => '/course/lib.php', - ], -]; - -``` diff --git a/versioned_docs/version-4.2/apis/commonfiles/version.php/index.md b/versioned_docs/version-4.2/apis/commonfiles/version.php/index.md deleted file mode 100644 index bbb009d448..0000000000 --- a/versioned_docs/version-4.2/apis/commonfiles/version.php/index.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: version.php -tags: - - Plugins - - Common files - - Plugin types -description: A description of the plugin version.php file, describing the various features ---- - -import { LanguageProperty } from '@site/src/components'; - -Every plugin must have a `version.php` file located in the root directory of that plugin. - -It contains a number of properties, which are used during the plugin installation and upgrade process. It allows to make sure the plugin is compatible with the given Moodle site, as well as spotting whether an upgrade is needed. - -## Plugin version properties - -### Component - - - -The component value contains the name of the plugin in its full [frankenstyle](/general/development/policies/codingstyle/frankenstyle) format. - -```php -$plugin->component = 'plugintype_pluginname'; -``` - -This value is used during the installation and upgrade process for diagnostics and validation purposes to make sure the plugin code has been deployed to the correct location within the Moodle code tree. - -### Version - - - -The version number of the plugin. The format is partially date based with the form YYYYMMDDXX where XX is an incremental counter for the given year (YYYY), month (MM) and date (DD) of the plugin version's release. Every new plugin version must have this number increased in this file, which is detected by Moodle core and the upgrade process is triggered. - -If multiple stable branches of the plugin are maintained, the date part YYYYMMDD should be frozen at the branch forking date and the XX is used for incrementing the value on the given stable branch (allowing up to 100 updates on the given stable branch). The key point is that the version number is always increased both horizontally (within the same stable branch, more recent updates have higher XX than any previous one) and vertically (between any two stable branches, the more recent branch has YYYYMMDD00 higher than the older stable branch). Pay attention to this. It's easy to mess up and hard to fix. - -```php -$plugin->version = 2022061700; - // YYYY - // MM - // DD - // XX -``` - -### Requirements - - - -The requires key specifies the minimum version of Moodle core requires for this plugin to function. It is _not_ possible to install the plugin on an earlier version of Moodle. - -Moodle core's version number is defined in the `version.php` file located in the Moodle root directory. - -```php -// Require Moodle 4.0.0. -$plugin->requires = 2022041900.00; -``` - -### Supported versions - - - - -A set of branch numbers to specify the lowest and highest branches of Moodle that the plugin supports. These value are inclusive. - -```php title="Support all versions of Moodle 3.11, and 4.0" -$plugin->supported = [ - - // Support from the Moodle 3.11 series. - 311, - - // To the Moodle 4.0 series. - 400, -]; -``` - -### Incompatible versions - - - - -The _earliest_ **incompatible** version of Moodle that the plugin cannot support the specified branch of Moodle. - -The plugin will not be installable on any versions of Moodle from this point on. - -```php title="Specify that this version of the plugin does not support Moodle 3.11 and subsequent releases" -$plugin->incompatible = 311; -``` - -### Maturity - - - -The maturity of the plugin, otherwise known as its stability. This value affects the [available update notifications](https://docs.moodle.org/en/Available_update_notifications) feature in Moodle. - -Administrators can configure their site so that they are not notified about an available update unless it has certain maturity level declared. - -```php -// The plugin is a pre-release version. -$plugin->maturity = MATURITY_ALPHA; - -// The plugin is a beta version. -$plugin->maturity = MATURITY_BETA; - -// The plugin is a release candidate version. -$plugin->maturity = MATURITY_RC; - -// The plugin is a stable version. -$plugin->maturity = MATURITY_STABLE; -``` - -### Release name - - - -A human-readable version name that should help to identify each release of the plugin. - -This can be any value you like, although it is recommended that you choose a pattern and stick with it. Usually this is a simple version like 2.1 but some plugin authors use more sophisticated schemes or follow the upstream release name if the plugin represents a wrapper for another program. - -```php -// This plugin release is version 1.0 for the 52.0-flamethrower upstream dependency. -$plugin->release = '52.0-flamethrower-1.0'; -``` - -### Peer dependenices - - - -An optional list of related plugins that this plugin depends upon to work. - -Moodle core checks that these declared dependencies are met, and will prevent installation and upgrade of this plugin if any of the dependencies are not met. - -```php -$plugin->dependencies = [ - // Depend upon version 2022041900 of mod_forum. - 'mod_forum' => 2022041900, - - // Depend upon version 2022041900 of block_foo. - 'block_foo' => 2022041900, -] -``` - -## File template - -Here is a template for the plugin's version.php file to copy and paste: - -```php -. - -/** - * @package plugintype_pluginname - * @copyright 2020, You Name - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->version = 2022060100; -$plugin->requires = 2022041900.00; // Moodle 4.0. -$plugin->supported = [400, 400]; -$plugin->incompatible = [401]; -$plugin->component = 'tool_example'; -$plugin->maturity = MATURITY_STABLE; -$plugin->release = '41.3-lemmings-1.0'; - -$plugin->dependencies = [ - 'mod_forum' => 2022041900, - 'mod_data' => 2022041900, -]; -``` - -## See also - -- [Moodle versions](https://docs.moodle.org/dev/Moodle_versions) diff --git a/versioned_docs/version-4.2/apis/core/activitycompletion/index.md b/versioned_docs/version-4.2/apis/core/activitycompletion/index.md deleted file mode 100644 index 11dbce63fb..0000000000 --- a/versioned_docs/version-4.2/apis/core/activitycompletion/index.md +++ /dev/null @@ -1,436 +0,0 @@ ---- -title: Activity completion API -tags: - - Conditional activities - - API -documentationDraft: true ---- - -:::note -There are changes to the completion API introduced in **Moodle 3.11** to be incorporated to this page. Please refer to [Student activity completion](https://docs.moodle.org/dev/Student_activity_completion) for details. -::: - -Activities do not need to be changed to support conditional availability, but they do need changing to support the completion system. - -If you make no changes to an activity whatsoever, it can only support 'manual' completion (where the user ticks a box). - -## Feature support - -To support the completion system, your activity must include a `[activityname]_supports` function in its `lib.php`. Here is an example: - -```php - /** - * Indicates API features that the forum supports. - * - * @param string $feature - * @return null|bool - */ -function forum_supports(string $feature): bool { - switch($feature) { - case FEATURE_COMPLETION_TRACKS_VIEWS: - return true; - case FEATURE_COMPLETION_HAS_RULES: - return true; - default: - return null; - } -} -``` - -The relevant features for completion are: - -- **`FEATURE_COMPLETION_TRACKS_VIEWS`** - the activity can support completion 'on view', meaning that an activity becomes marked complete as soon as a user clicks on it. -- **`FEATURE_GRADE_HAS_GRADE`** - the activity provides (or may provide, depending on settings) a grade for students. When an activity supports grades, it can support completion 'on grade', meaning that an activity becomes marked complete as soon as a user is assigned a grade. -- **`FEATURE_COMPLETION_HAS_RULES`** - the activity has custom completion rules. - -## Completion on view - -Completion on view means that, if selected, an activity is marked as complete as soon as the user views it. - -'View' is usually defined as seeing the activity's main page; if you click on the activity, and there isn't an error, you have probably viewed it. However it is up to each activity precisely how they define 'view'. - -### How to implement - -In your activity's `[activityname]_supports` function, return true for `FEATURE_COMPLETION_TRACKS_VIEWS`. - -Then add this code to run whenever a user successfully views the activity. In order for navigation to work as expected (that is so that the navigation block on the activity's page takes account that you have viewed this activity, if there is another activity that depends on it) you should put this code before printing the page header. - -```php - $completion = new completion_info($course); - $completion->set_module_viewed($cm); -``` - -### Performance issues - -Calling this method has no significant performance cost if 'on view' completion is not enabled for the activity. If it is enabled, then the performance cost is kept low because the 'viewed' state is cached; it doesn't add a database query to every request. - -## Completion on grade - -Completion on grade means that, if selected, an activity is marked as complete as soon as the user receives a grade from that activity. - -### How to implement - -In your `[activityname]_supports` function, return true for `FEATURE_GRADE_HAS_GRADE`. No other action is necessary. - -### Performance issues - -When 'on grade' completion is enabled, there will be some additional database queries after a grade is assigned or changed. Unless your activity changes grades very frequently, this is unlikely to be an issue. - -## Custom completion rules - -Custom completion rules allow for activity-specific conditions. For example, the forum has custom rules so that a teacher can configure it to mark a user as having completed the activity when that user makes a certain number of posts to the forum. - -Implementing custom completion rules is more complex than using the system-provided 'view' or 'grade' conditions, but the instructions below should help make it clear. - -### Implementation overview - -To implement custom completion rules, you need to: - -1. Return true for FEATURE_COMPLETION_HAS_RULES in your activity's _supports function. -1. Add database fields to your activity's main table to store the custom completion settings. -1. Add backup and restore code to back up these fields. -1. Add information about the completion settings to the activities cm_info object. -1. Add controls to your activity's settings form so that users can select the custom rules, altering these database settings. -1. Add a function that checks the value of these rules (if set). -1. Add function returns descriptions for the completion states. -1. Add code so that whenever the value affecting a rule might change, you inform the completion system. - -### Database fields for completion settings - -When you provide a custom completion rule for a activity, that rule requires data to be stored with each activity instance: whether the rule is enabled for that instance, and any options that apply to the rule. - -Usually the best place to store this information is your activity's main table because: - -- The information in the relevant row of this table is likely to be available in most parts of your code, so code changes are minimised. -- You already read this row with most requests, so there is no need for additional database queries which would reduce performance. -- The main table is used for most other activity options so it is a logical place for this information. -If you are adding a basic completion condition you probably only need to add one field. To add a field to an existing activity, you need to change the db/install.xml and the db/upgrade.php in the same way as adding any other field. - -#### Example - -Throughout this section I am using the forum as an example. The forum provides three completion options but because they all behave the same way, I am only showing one of them. - -The forum adds this field to store a completion option: - -- **`completionposts`** - this may be 0 or an integer. If it's an integer, say 3, then the user needs to add 3 forum posts (either new discussions or replies) in order for the forum to count as 'completed'. - -### Backup and restore for completion fields - -Activities do not need to back up the generic completion options, which are handled by the system, but they do need to back up any custom options. You should add backup and restore logic for the fields mentioned above. - -Remember that your restore code should handle the case when these fields are not present, setting the fields to a suitable default value. - -#### Example - -The following code in `backup_forum_stepslib.php` lists the fields to back up: - -```php -$forum = new backup_nested_element('forum', ['id'], [ - 'type', 'name', 'intro', 'introformat', - 'assessed', 'assesstimestart', 'assesstimefinish', 'scale', - 'maxbytes', 'maxattachments', 'forcesubscribe', 'trackingtype', - 'rsstype', 'rssarticles', 'timemodified', 'warnafter', - 'blockafter', 'blockperiod', 'completiondiscussions', 'completionreplies', - 'completionposts', -]); -``` - -As you can see, I added the **`completionposts`** field (and the others that aren't covered in this example) to the list of fields. - -### Add information about the completion settings to the activities cm_info object - -You will need to add information about the custom rules into the activities `cm_info` object by either adding, or modifying the `module_get_coursemodule_info` callback - -```php -/** - * Add a get_coursemodule_info function in case any forum type wants to add 'extra' information - * for the course (see resource). - * - * Given a course_module object, this function returns any "extra" information that may be needed - * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. - * - * @param stdClass $coursemodule The coursemodule object (record). - * @return cached_cm_info An object on information that the courses - * will know about (most noticeably, an icon). - */ -function forum_get_coursemodule_info($coursemodule) { - global $DB; - - $dbparams = ['id' => $coursemodule->instance]; - $fields = 'id, name, intro, introformat, completionposts, completiondiscussions, completionreplies, duedate, cutoffdate'; - if (!$forum = $DB->get_record('forum', $dbparams, $fields)) { - return false; - } - - $result = new cached_cm_info(); - $result->name = $forum->name; - - if ($coursemodule->showdescription) { - // Convert intro to html. Do not filter cached version, filters run at display time. - $result->content = format_module_intro('forum', $forum, $coursemodule->id, false); - } - - // Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'. - if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) { - $result->customdata['customcompletionrules']['completiondiscussions'] = $forum->completiondiscussions; - $result->customdata['customcompletionrules']['completionreplies'] = $forum->completionreplies; - $result->customdata['customcompletionrules']['completionposts'] = $forum->completionposts; - } - - // Populate some other values that can be used in calendar or on dashboard. - if ($forum->duedate) { - $result->customdata['duedate'] = $forum->duedate; - } - if ($forum->cutoffdate) { - $result->customdata['cutoffdate'] = $forum->cutoffdate; - } - - return $result; -} -``` - -### Form changes for completion settings - -When you have custom completion conditions, you need to add controls to your module's settings form `mod_form.php` so that users can select these conditions. You can add any necessary controls. - -- Implement the `add_completion_rules` function which adds the form controls for your new rules. -- Implement the `completion_rule_enabled` function which is called during form validation to check whether one of your activity's completion rules has been selected. -- Implement other form changes if necessary to set up the form with your data. If your data is in the form of simple text boxes or dropdowns then this is not necessary, but you might want to have a checkbox that enables the rule with a separate control to set its value. This needs form tweaks. - -#### Example - -The forum offers a checkbox with a text input box beside it. You tick the checkbox to enable the rule, then type in the desired number of posts. - -First, the function that adds these controls: - -```php -/** - * Add elements for setting the custom completion rules. - * - * @category completion - * @return array List of added element names, or names of wrapping group elements. - */ -public function add_completion_rules() { - - $mform = $this->_form; - - $group = [ - $mform->createElement('checkbox', 'completionpostsenabled', ' ', get_string('completionposts', 'forum')), - $mform->createElement('text', 'completionposts', ' ', ['size' => 3]), - ]; - $mform->setType('completionposts', PARAM_INT); - $mform->addGroup($group, 'completionpostsgroup', get_string('completionpostsgroup','forum'), [' '], false); - $mform->addHelpButton('completionpostsgroup', 'completionposts', 'forum'); - $mform->disabledIf('completionposts', 'completionpostsenabled', 'notchecked'); - - return ['completionpostsgroup']; -} -``` - -- The function creates a checkbox and a text input field, which is set to accept only numbers. -- These are grouped together so they appear on the same line, and we add a help button. -- The text input field is disabled if the checkbox isn't ticked. -- Note that this function must return the top-level element associated with the completion rule. (If there are multiple elements, you can return more than one.) - - This is used so that your controls become disabled if automatic completion is not selected. -Next, a function for checking whether the user selected this option: - -```php -/** - * Called during validation to see whether some activity-specific completion rules are selected. - * - * @param array $data Input data not yet validated. - * @return bool True if one or more rules is enabled, false if none are. - */ -public function completion_rule_enabled($data) { - return (!empty($data['completionpostsenabled']) && $data['completionposts'] != 0); -} -``` - -- The custom completion rule is enabled if the 'enabled' checkbox is ticked and the text field value is something other than zero. - - This is used to give an error if the user selects automatic completion, but fails to select any conditions. -That's all the 'required' functions, but we need to add some extra code to support the checkbox behaviour. I overrode get_data so that if there is a value in the edit field, but the checkbox is not ticked, the value counts as zero (the rule will not be enabled). - -```php -function get_data() { - $data = parent::get_data(); - if (!$data) { - return $data; - } - if (!empty($data->completionunlocked)) { - // Turn off completion settings if the checkboxes aren't ticked - $autocompletion = !empty($data->completion) && $data->completion==COMPLETION_TRACKING_AUTOMATIC; - if (empty($data->completionpostsenabled) || !$autocompletion) { - $data->completionposts = 0; - } - } - return $data; -} -``` - -You may have noticed the `completionunlocked` check. When some users have already completed the activity, the completion settings are 'locked'; they are disabled and cannot be edited, so there will be no value set for those fields in the `$data` object. Normally this will automatically work but when dealing with checkboxes you need to include a check for the `completionunlocked` value before doing anything that would cause one of those fields to be changed in the database. -Finally, forum already had a `data_preprocessing` function but I added code to this to set up the checkboxes when the form is displayed, and to make the default value of the text fields 1 instead of 0: - -```php -function data_preprocessing(&$default_values){ - // [Existing code, not shown] - - // Set up the completion checkboxes which aren't part of standard data. - // We also make the default value (if you turn on the checkbox) for those - // numbers to be 1, this will not apply unless checkbox is ticked. - $default_values['completionpostsenabled']= - !empty($default_values['completionposts']) ? 1 : 0; - if(empty($default_values['completionposts'])) { - $default_values['completionposts']=1; - } -} -``` - -Phew! That's the form done. - -### Completion state function - -When you create completion conditions, you need to write a function *module*`_get_completion_state` that checks the value of those conditions for a particular user. - -The function receives as parameters `$course`, `$cm`, and `$userid` - all self-explanatory, I hope - and `$type`. This has two values: - -- **`COMPLETION_AND`** - if multiple conditions are selected, the user must meet all of them. -- **`COMPLETION_OR`** (not currently used) - if multiple conditions are selected, any one of them is good enough to complete the activity. -Your function should return: -- **`true`** if your custom completion options are enabled and the user meets the conditions. -- **`false`** if your custom completion options are enabled but the user does not yet meet the conditions. -- `$type` (not false!) if none of your custom completion options are not enabled. - -#### Example - -Here's the function for forum (simplified to include only the one completion option): - -```php title="mod/forum/lib.php" - /** - * Obtains the automatic completion state for this forum based on any conditions - * in forum settings. - * - * @param object $course Course - * @param object $cm Course-module - * @param int $userid User ID - * @param bool $type Type of comparison (or/and; can be used as return value if no conditions) - * @return bool True if completed, false if not, $type if conditions not set. - */ - function forum_get_completion_state($course, $cm, $userid, $type) { - global $CFG,$DB; - - // Get forum details - $forum = $DB->get_record('forum', ['id' => $cm->instance], '*', MUST_EXIST); - - // If completion option is enabled, evaluate it and return true/false - if ($forum->completionposts) { - return $forum->completionposts <= $DB->get_field_sql(" - SELECT - COUNT(1) - FROM - {forum_posts} fp - INNER JOIN {forum_discussions} fd ON fp.discussion=fd.id - WHERE - fp.userid = :userid AND fd.forum = :forumid - ", [ - 'userid' => $userid, - 'forumid' => $forum->id, - ]); - } else { - // Completion option is not enabled so just return $type - return $type; - } - } -``` - -### Add function returns descriptions for the completion states - -When you create completion conditions, you need to write a function `[activityname]_get_completion_active_rule_descriptions` that gives a human-readable description of the completion state. - -The input for the method is the `cm_info` object for that activity. - -You need to return an array of strings for each completion rule that is active. - -```php -/** - * Callback which returns human-readable strings describing the active completion custom rules for the module instance. - * - * @param cm_info|stdClass $cm object with fields ->completion and ->customdata['customcompletionrules'] - * @return array $descriptions the array of descriptions for the custom rules. - */ -function mod_forum_get_completion_active_rule_descriptions($cm) { - // Values will be present in cm_info, and we assume these are up to date. - if (empty($cm->customdata['customcompletionrules']) || $cm->completion != COMPLETION_TRACKING_AUTOMATIC) { - return []; - } - - $descriptions = []; - foreach ($cm->customdata['customcompletionrules'] as $key => $val) { - switch ($key) { - case 'completiondiscussions': - if (!empty($val)) { - $descriptions[] = get_string('completiondiscussionsdesc', 'forum', $val); - } - break; - case 'completionreplies': - if (!empty($val)) { - $descriptions[] = get_string('completionrepliesdesc', 'forum', $val); - } - break; - case 'completionposts': - if (!empty($val)) { - $descriptions[] = get_string('completionpostsdesc', 'forum', $val); - } - break; - default: - break; - } - } - return $descriptions; -} -``` - -### Notifying the completion system - -Finally you need to notify the completion system whenever these values might have changed for a user (in the case of the forum example, whenever somebody adds or deletes a post). The completion system will end up calling the function above - but only if it needs to. - -- To ensure performance is not compromised, you should notify the system only when the completion state might actually have changed. Don't notify the system unless your custom completion rule is actually enabled. -- You need to pass in the 'possible result' of the change. This is used to significantly improve performance. There are three values: - - **`COMPLETION_COMPLETE`** - this change will either have no effect on the user's completion state, or it will make it complete. The change cannot make a user's state *in*complete if it was complete previously. In the forum example, when you add a post, there is no way this can make the user's state incomplete, so this possible result applies. - - **`COMPLETION_INCOMPLETE`** - this change will either have no effect on the user's completion state, or it will make it incomplete. The change cannot make a user's state complete if it was incomplete previously. Deleting a forum post would fall into this category. - - **`COMPLETION_UNKNOWN`** - this change might have either effect. Using this option is much slower than the others, so try to avoid using it in anything that might happen frequently. -- If the user whose completion state would be updated is not the current user, then the optional `$userid` parameter must be included. For example, if a teacher deletes a student's forum post, then it is the student's completion state which may need updating, not the teacher's. - -#### Example - -Here's the code that runs when somebody makes a new forum post: - -```php -// Update completion state -$completion = new completion_info($course); -if ($completion->is_enabled($cm) && $forum->completionposts) { - $completion->update_state($cm, COMPLETION_COMPLETE); -} -``` - -### Completion Checks in Cron Tasks - -If you need to check completion as part of a cron task or another part of Moodle that does not already include the completion_info class, you will need to include it. - -#### Example - -```php -require_once($CFG->dirroot.'/lib/completionlib.php'); -``` - -## See Also - -- [Activity completion and availability](https://docs.moodle.org/dev/Conditional_activities) - Original Specification -- [Course completion](https://docs.moodle.org/dev/Course_completion) - Original Specification -- [Policy - Retroactive effects of completion settings](https://docs.moodle.org/dev/Policy_-_Retroactive_effects_of_completion_settings) -- [Core APIs](../../../apis.md) - -### User Docs - -- [Completion Docs](https://docs.moodle.org/en/Category:Completion) -- [Activity Completion](https://docs.moodle.org/en/Activity_completion) -- [Course Completion](https://docs.moodle.org/en/Course_completion) diff --git a/versioned_docs/version-4.2/apis/core/calendar/_index/my_overview_sam_student.png b/versioned_docs/version-4.2/apis/core/calendar/_index/my_overview_sam_student.png deleted file mode 100644 index 4e33b2d305b029b690fcf9c057cae77a2ceab71d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48765 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 z zecUdpnE&I<&-C%ox`r{G$3C~`3N@~s39QZL=gPX%S&_yOf6`p#*J2*n8?eJT{K5OZ zX0pt&6w%~~8bm^fW;N#TX;8`(x@kFy8x@bdr7AHrW{BH2za}j+u@yX!rfgdX2DVwD zv!O$^V}ki~Ki4Lv6DbR3%sGn6)S*98CB8^+0d^b{xCDl}3(Zvx} zQQXjru{GOAmUg|qrnJwH6hi*`=QrM@{d>%m^t6l^J-3Nd9v2%zaeQOA>_4s@%*n35!fq6jZf0J zSGI6cJ2l|!JViL)aUhzR2T>FM0TbLZQ?_t4wTO;w4I{CrUfpV8lYQuP^#xP4#wZqTPj)!>O4ZMTlCTx7+GH8+O_^KNR8}VCpK3Y|Xr8 zN!-f5?;K7a3J1TR8cVLmGgOL+vx6es&r*-5-psx|+b8Z)92$7-UhcRrY&Y@USnq79 zg+$<1xRNerVrgyuL2><>eS&-*TR+YI+n!O^2E%KJM#T@+P&*wwvG>S9gYxy-7g&pBBc_KPC-Uz10fD(~%bw$2P!bI$TK3Y*Hi5 zUSRh9m8-s$hX9v~QHeKtu5ovFmsYI8N-%xf68277MtS`s#q06wXYyyN^SZ20K3|NP z8-&;z8=YvN7yn$PZZ}L$b>HH6C*LSLnzuKQQ%Y&3f~@ynC^6LGJAB6)v%Oh`?fX3W z+W1u%s8@1$0uQ)^gvNVVXW2^hDWf-t37nBXO?NtMq@_Q+_;bU<;S6(D>dTW>BRtq}G zpz!$@-WUPd7&=$w&dgULe{w7qtQM3!&Y@vJlcrAq3h!j(DtX-%0=*?q#YQ2=D*(v$ z;$qYZ_ZaoyOD}8jPYVDl-;LQ3!HMi4zUn>VY)Xq@NGf zAYD3V1E%lDK3>!>mo77`9fQ*{U z5?7yw;S;7WD`OUhSLId;iK|{D-fYoH`kf(oSphxLGH+t)(L-9OW9F>LI)_Ov&v+x@ z?u_)vwSQhEB<85qWry!~yiA3=EDh|Kqn-}A44CQ@gwB}vK*Hmk(AXaDyW~jMO70}q zE%SSG-4t*Nsfo&%0-r)<6gqJnG;+58cqM;yQW6HzZIYS)O~oLJ@RK26G5i}KJ{)8F;` z2ctk@fGA|3sti^MVft__gKD-38f2kw6zAj`) zd*s%v30Dv6-?BvTklju_4Kr@?3r$VdR}-YVyOjQy9}L*U&9)3s=%$xUEIp%zgBm#D z6qTjL6;xwu9*mj`HA+HTF`7CLtyEU;Z*w*84{!g;5Wo2Y|BYuT4fYam1|IEsmKe%f zBr;Pu>UE?u-pl&ZtaM?sKyuok$`oEuK#`dapKpe+u#BwhYto~pV2t?}M#l=LbHl~g ze}3dGJ*$2KYP1NpQ5O3}TQxwdgOOPfHcM&C2az{UBbSxT(x z=hu)L-Og_QP~auZ5=SCr3*OzNe0#by-)xUSrX%k8R*e#;7K~^UVTztUh-D)+dzL*H&c-7godPHTdY_ z!TtCX{D_K?Y{o-{!RHyG`HTtoI)+(+WXeSE3v#Z349wTvuF&IHoH>!^P1PbZw(goc zYg=gBqn#ppy!)xbGu_1NS=&W##hwcYb2|+|Qq65(MAHXj@1&T)?M&)ALdr~RD9EuF zeG`R5bnn9`x2}hyoeH&w7xiB2?JnbCS9$}JCW;M9V+?f#s<>cD{wB0RWIj^*dZcb$ zgbxbVo;rMC3i13BbCu1(Dz$DDmOJn?rH)8Z1ot67MXFL-QJR8^_UaW;>E6fO0s=ZF zZPd#9dHo4m3AG~HZ!Ye5_?v}f?CoJcT?|7&P7CVL`UeA(JDaHEiJh|6ix{LUGRto% zQ9MOgmdX5-8;U*JtlWmIXX#-q2R__YhvckI4={e7t67?eh~Lged1SP{^AF160&<+3 zj7!?Z={kmYHyr~6=;S0+&T=rbVC5ln_YCMz-%H*W%^fS#F~>oyOOVz|+~)`DoBzq;YhC)yZ@ zTq{UjL*5O(#aNX1(7&c{21&8JO* zC>SShsx-3L?yf$<-m%%<&+@c%`5}{etUi+fHZ@Y)7`teqZTQ6xv|2uiwiG z5MG6xl|6QQ31qQ3+cbOcs7vti@zD{6Ngs_}e3Ww(kZ@O%m@5WNCgl?emKwNR^xxP4 zp3PX+0&<0~k=@_`2roe>rjYG+D(%uzczT1O>1oTi(*gZ@Qng|(VVi2X{_-;P%z<%Q z=XR<~uULG^lL7SfbOH&Jd0L&lcd0OK)eU3a1-|35W~V57J&j}{CUa53huwubH>W3# z7wnN|Q#;JFM|cS0j+F6e8QNTPr0;#C`qb;QK~;Uyl_aeJEQ)nfZ3ykOg#iOf%wUTf zeU?WOJ3wTCZ7eXbS^?LD4Z*OerqX#0D%@88R&Y^qfzwn&vGueAc%n3*g_}aE%5yI| z;*M*BqWux$E?buDl@nd)={$GV*7cBX!Y7+OcmsM)=T zct`@9Hp&-U!DEAF71OyyDJoa^C)CXao2gBha5C+`BXwx=lzBjTSN&(FkR zdydN_QD-?qm43MDG!cy%T!Cr-Zs+3elB!maGqUkr-tSq~0^-CM zlTxC4ZwTrPDYYN{m?c)tF~+H@hbGGfkfcE~Dirq8pmFn3O<+-UH*N#J2Sr+e^-SPP z3;a2_#CbL@YrME5;CcTWJpBFd-xr53(W$TXf%D%+teu?7&44OxZ^YkfXK`7+GpQb02&Tig9IAcg5q%BW~YNqmP0 zlwMdeEKz|)uIN$(ZW(m)CHVBekmnL3`yYMyddVg8Z+-Yz$A0(WcgNnlJvO~Xuqc$G zvbOuHQ(Rm;f602!y9LOLj92(_ivXzjG7Z(S|b6WO6m76bJuL5n~tCzI4 zf;vKo_Ppob(pj-oivnl12@s?c1wu&(dN+1q7DkZP&RJiNmNN?y_B$xT|>Wl5#@#0L?R`9 zf6>m?8A`ax0a>A%<73u*wn+qwKkq%ePVm&$&2q@7-VrzJ1Z_2GKaXbxy1N58Mu@|A z(3_h+2Wf%FtM>!_r$dM~-F;CQNbAhc4NG_ESM1(1Q0tn%8`zJ?5eXF)<_Hvec!Y%oz}X zBQA9)t<>2*PF~1RVUxazqNhhrl-k+P2@3HEfo5s|z^6`z`B@ce2NbXw#nW1|@ex^$ z|6!#jLLEi{tkd=SD<%ib@qKfR+O3riv+=A>sPFKhp{!@1(|Fd-&QA5xfTmoQL#x2k zM0tjQ@6F9txG0{FcZ%}W=4TrOL!R>Sx$iEvZ@0Yw7~^hcL$WKYzAY)(huv{?b(6li z(^8EII)k3-pqb}Cj%WG(8 zqC~g~71Kl?c+i%-Hk9U7)c$+I2YHC?>}Vex*VWa!VuI^}Uf13$VE8b(HlnF&g%DQIAzn;T|H-w_6fb11NsLGd%kh=uXV zNx>@AT%((^vNE6{3JI5m{%F%(_jM&WdCR6kZT$K*zUK%fxZrIDGzOlF)(w~(;i#$0 z19&O%YqYTptrgYP)lEgV1A!8PaRU>Rf+{Jzc@-5EmDw&wCAuWh(Ua#BPMHlk9UUF9 z0Y37~*RMy!mjg6o)zkJjv$-<3A3f?D8e-Hndh>=?jP5521@Qh8Gkwl|Q^2UQb)o%R z-K6tSPH=l$boQiCa?JoERbw*>@W+Dv?O7(X8X4XT8+i0+=o^BttPe@BUtNd_*=|=_OL{Ott6-~l}j6z^+B|e$9N)7>-qlT@L~y^M-n}) z2uPL5XETpMHa9o>`T0$j`Qha+_Lk!dii+|b12F>~K=hheCK#-trFAs3Hd$O;B=_uN zWMpK*+pTpTDDTs!!#*dwJ<-qx)4}wXmW>oLfWa2<=p%F+Oxhu!vvpvdt@NXExS(f) z?b+>4;zt?15KJpRC`fci=jgSQwsvhzjap#|osW*LuFJ-7w#{gfJcd@BeI3Db{!-qm zcOeit8+(B{hWGa;1)$y74KZ&o2dwOwp`jsT^P9lHiw(z|1mIk=!0Ydc;hExoMRFb= zr_Tx6eC+-9r!jqy3K=9FJ zI7ur=05}d<1F*|&tbK=dirroot.'/calendar/lib.php'); - -$event = new stdClass(); -$event->eventtype = SCORM_EVENT_TYPE_OPEN; // Constant defined somewhere in your code - this can be any string value you want. It is a way to identify the event. -$event->type = CALENDAR_EVENT_TYPE_STANDARD; // This is used for events we only want to display on the calendar, and are not needed on the block_myoverview. -$event->name = get_string('calendarstart', 'scorm', $scorm->name); -$event->description = format_module_intro('scorm', $scorm, $cmid, false); -$event->format = FORMAT_HTML; -$event->courseid = $scorm->course; -$event->groupid = 0; -$event->userid = 0; -$event->modulename = 'scorm'; -$event->instance = $scorm->id; -$event->timestart = $scorm->timeopen; -$event->visible = instance_is_visible('scorm', $scorm); -$event->timeduration = 0; - -calendar_event::create($event); -``` - -## Updating an event - -You can update an existing event in database by providing at least the event id. If the event is a part of a chain of repeated events, the rest of series event will also be updated (depending on the value of property `repeateditall`). This function could also be used to insert new event to database, if the given event does not exist yet. The optional parameter `$checkcapability` is used to check user's capability to edit/add events. By default the `$checkcapability` parameter is set to true. You should set it to false if you have already checked that the user has the capabilities required for the event to be updated, for example when an activity is updating an event based on a change to it's settings. - -```php -$eventid = required_param('id', PARAM_INT); -$event = calendar_event::load($eventid); - -$data = $mform->get_data(); -$event->update($data); -``` - -## Deleting an event - -You can delete an existing event from the database. The optional parameter `$deleterepeated` is used as an indicator to remove the rest of repeated events. The default value for `$deleterepeated` is true. Deleting an event will also delete all associated files related to the event's editor context. - -```php -$eventid = required_param('id', PARAM_INT); -$event = calendar_event::load($eventid); -$event->delete($repeats); -``` - -## Event priority - -There might be cases that an activity event will have user and/or group overrides. Therefore we need a way to show only the relevant event on the user's calendar. This is where the 'priority' field comes in. - -The event priority is set to the following: - -- NULL for non-override events. - -```php -$event->priority = null; -``` - -- 0 for user override events. - -```php -$event->priority = CALENDAR_EVENT_USER_OVERRIDE_PRIORITY; -``` - -- A positive integer for group events. - -For integer and non-null event priorities, the lower the value, the higher the priority is. Meaning, user overrides always have a higher priority than group overrides. Group override priorities are currently being determined in two ways in core activities: - -1. In the assignment module, the event priorities for group overrides are being determined from the `sortorder` column in the 'assign_overrides' table. -1. In the lesson and quiz modules, the event priorities for group overrides are being calculated using the functions `lesson_get_group_override_priorities($lessonid)` and `quiz_get_group_override_priorities($quizid)`. - -Should you ever decide to sort out group override priorities by implementing `*_get_group_override_priorities()`, the recommended return structure would be something like - -```php -[ - 'youreventtype1' => $prioritiesforeventtype1, - ... -] -``` - -where '$prioritiesforeventtype1' is an associative array that has the timestamp of the group override event as key and the calculated priority as value. For more details, please see the implementation for the lesson module below: - -```php -/** - * Calculates the priorities of timeopen and timeclose values for group overrides for a lesson. - * - * @param int $lessonid The lesson ID. - * @return array|null Array of group override priorities for open and close times. Null if there are no group overrides. - */ -function lesson_get_group_override_priorities($lessonid) { - global $DB; - - // Fetch group overrides. - $where = 'lessonid = :lessonid AND groupid IS NOT NULL'; - $params = ['lessonid' => $lessonid]; - $overrides = $DB->get_records_select('lesson_overrides', $where, $params, '', 'id, groupid, available, deadline'); - if (!$overrides) { - return null; - } - - $grouptimeopen = []; - $grouptimeclose = []; - foreach ($overrides as $override) { - if ($override->available !== null && !in_array($override->available, $grouptimeopen)) { - $grouptimeopen[] = $override->available; - } - if ($override->deadline !== null && !in_array($override->deadline, $grouptimeclose)) { - $grouptimeclose[] = $override->deadline; - } - } - - // Sort open times in ascending manner. The earlier open time gets higher priority. - sort($grouptimeopen); - // Set priorities. - $opengrouppriorities = []; - $openpriority = 1; - foreach ($grouptimeopen as $timeopen) { - $opengrouppriorities[$timeopen] = $openpriority++; - } - - // Sort close times in descending manner. The later close time gets higher priority. - rsort($grouptimeclose); - // Set priorities. - $closegrouppriorities = []; - $closepriority = 1; - foreach ($grouptimeclose as $timeclose) { - $closegrouppriorities[$timeclose] = $closepriority++; - } - - return [ - 'open' => $opengrouppriorities, - 'close' => $closegrouppriorities - ]; -} -``` - -## Action events - -Action events are calendar events that can be actioned. E.g. A student submitting an assignment by a certain date. These events are displayed on the block_myoverview which by default is on users' dashboard. Creating these is the same as creating a normal calendar event except instead of using CALENDAR_EVENT_TYPE_STANDARD as your calendar event type, you use CALENDAR_EVENT_TYPE_ACTION. The events are also sorted on the dashboard by the value specified in the 'timesort' field (unixtime) for the event. - -Example of the changes to the above code would be to change the `type` and to specify the `timesort` value. - -```php -$event->type = CALENDAR_EVENT_TYPE_ACTION; -$event->timesort = $scorm->timeclose; -``` - -![my overview sam student.png](./_index/my_overview_sam_student.png) - -### The callbacks - -There are 3 callbacks your module can implement that are used to control when and how your action is shown to the user. - -#### mod_xyz_core_calendar_is_event_visible() - -This callback determines if an event should be visible throughout the site. For example, the assignment module creates a grading event for teachers. We do not want this event being visible to users who can not perform this action (eg. students), so we return false for those users. If you do not implement this function then the event will always be visible. - -```php -/** - * Is the event visible? - * - * This is used to determine global visibility of an event in all places throughout Moodle. For example, - * the ASSIGN_EVENT_TYPE_GRADINGDUE event will not be shown to students on their calendar, and - * ASSIGN_EVENT_TYPE_DUE events will not be shown to teachers. - * - * @param calendar_event $event - * @return bool Returns true if the event is visible to the current user, false otherwise. - */ -function mod_assign_core_calendar_is_event_visible(calendar_event $event) { - global $CFG, $USER; - - require_once($CFG->dirroot . '/mod/assign/locallib.php'); - - $cm = get_fast_modinfo($event->courseid)->instances['assign'][$event->instance]; - $context = context_module::instance($cm->id); - - $assign = new assign($context, $cm, null); - - if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) { - return $assign->can_grade(); - } else { - return !$assign->can_grade() && $assign->can_view_submission($USER->id); - } -} -``` - -#### mod_xyz_core_calendar_provide_event_action() - -This function takes a calendar event and provides the action associated with it, or null if there is none in which case the event will not be shown in block_myoverview (but will still be shown in the calendar block). This is used by the block_myoverview plugin. If you do not implement this function then the events created by your plugin will not be shown on the block. - -Eg. - -```php -function mod_scorm_core_calendar_provide_event_action(calendar_event $event, - \core_calendar\action_factory $factory) { - global $CFG; - - require_once($CFG->dirroot . '/mod/scorm/locallib.php'); - - $cm = get_fast_modinfo($event->courseid)->instances['scorm'][$event->instance]; - - if (!empty($cm->customdata['timeclose']) && $cm->customdata['timeclose'] < time()) { - // The scorm has closed so the user can no longer submit anything. - return null; - } - - // Restore scorm object from cached values in $cm, we only need id, timeclose and timeopen. - $customdata = $cm->customdata ?: []; - $customdata['id'] = $cm->instance; - $scorm = (object)($customdata + ['timeclose' => 0, 'timeopen' => 0]); - - // Check that the SCORM activity is open. - list($actionable, $warnings) = scorm_get_availability_status($scorm); - - return $factory->create_instance( - get_string('enter', 'scorm'), - new \moodle_url('/mod/scorm/view.php', array('id' => $cm->id)), - 1, - $actionable - ); -} -``` - -The variables to pass to `create_instance()` are - - -1. `string $name` The name of the event, for example `get_string('dosomething', 'mod_xyz')`. -1. `\moodle_url $url` The URL the user visits in order to perform this action. -1. `int $itemcount` This represents the number of items that require action (eg. Need to write 3 forum posts). If this is 0 then the event is not displayed. -1. `bool $actionable` This determines if the event is currently able to be acted on. Eg. the activity may not currently be open due to date restrictions so the event is shown to the user to let them know that there is an upcoming event but the url will not be active. - -#### mod_xyz_core_calendar_event_action_shows_item_count() - -This function determines if a given event should display the number of items to action on block_myoverview. For example, if the event type is `ASSIGN_EVENT_TYPE_GRADINGDUE` then we only display the item count if there are one or more assignments to grade. If you do not implement this function then the item count is always hidden. This is usually fine as the majority of events only have an item count of '1' (eg. Submitting an assignment) and there is no need display the item count. - -Eg. - -```php -/** - * Callback function that determines whether an action event should be showing its item count - * based on the event type and the item count. - * - * @param calendar_event $event The calendar event. - * @param int $itemcount The item count associated with the action event. - * @return bool - */ -function mod_assign_core_calendar_event_action_shows_item_count(calendar_event $event, $itemcount = 0) { - // List of event types where the action event's item count should be shown. - $eventtypesshowingitemcount = [ - ASSIGN_EVENT_TYPE_GRADINGDUE - ]; - // For mod_assign, item count should be shown if the event type is 'gradingdue' and there is one or more item count. - return in_array($event->eventtype, $eventtypesshowingitemcount) && $itemcount > 0; -} -``` - -## Refreshing calendar events of activity modules - -A new ad-hoc task 'refresh_mod_calendar_events_task' has been created. This task basically loops through all of the activity modules that implement the '*_refresh_events()' hook. - -Sample usage: - -```php -// Create the instance. -$refreshtask = new refresh_mod_calendar_events_task(); - -// Add custom data. -$customdata = [ - 'plugins' => ['assign', 'lesson', 'quiz'] // Optional. If not specified, it will refresh the events of all of the activity modules. -]; -$refreshtask->set_custom_data($customdata); - -// Queue it. -\core\task\manager::queue_adhoc_task($refreshtask); -``` - -## calendar_get_legacy_events() - -This functions accepts the same inputs as 'calendar_get_events()' but is now utilising the new Moodle Calendar API system. It respects overrides and will also add the action properties, whenever appropriate. - -*Note that this function will not work as expected if you pass a list of user ids as the current user session is internally used to determine which events should be visible. More info in https://tracker.moodle.org/browse/[MDL-60340](https://tracker.moodle.org/browse/MDL-60340)* - -## Changes to Behat - -The "And I follow "Course1"" Behat step won't work from the Dashboard anymore and has been replaced with "And I am on "Course 1" course homepage" where 'Course 1' is the fullname of the course. - -## Drag & drop - -The calendar supports dragging and dropping events within the calendar in order to change the start day for the event. Each type of calendar event can be dragged by a user with sufficient permissions to edit the event. - -### Dragging action events - -When an action event is dragged the corresponding property will also be updated in the activity instance that generated the event. For example, dragging the assignment due date event will result in the assignment activity's due date to be changed. - -In order to drag an action event the logged in user must have the `moodle/course:manageactivities` capability in the activity that generated the event. - -For an action event to be draggable the activity that generated it will need to have implemented at least one (but ideally both) callback to handle updating itself after the calendar event is dragged. - -#### `core_calendar_event_timestart_updated` (required) - -This callback is required to be implemented by any activity that wishes to have it's action events draggable in the calendar. - -This callback handles updating the activity instance based on the changed action event. The callback will receive the updated calendar event and the corresponding activity instance. - -Example: - -```php -function mod_feedback_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $feedback) { - global $CFG, $DB; - - if (empty($event->instance) || $event->modulename != 'feedback') { - return; - } - - if ($event->instance != $feedback->id) { - return; - } - - if (!in_array($event->eventtype, [FEEDBACK_EVENT_TYPE_OPEN, FEEDBACK_EVENT_TYPE_CLOSE])) { - return; - } - - $courseid = $event->courseid; - $modulename = $event->modulename; - $instanceid = $event->instance; - $modified = false; - - $coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid]; - $context = context_module::instance($coursemodule->id); - - // The user does not have the capability to modify this activity. - if (!has_capability('moodle/course:manageactivities', $context)) { - return; - } - - if ($event->eventtype == FEEDBACK_EVENT_TYPE_OPEN) { - // If the event is for the feedback activity opening then we should - // set the start time of the feedback activity to be the new start - // time of the event. - if ($feedback->timeopen != $event->timestart) { - $feedback->timeopen = $event->timestart; - $feedback->timemodified = time(); - $modified = true; - } - } else if ($event->eventtype == FEEDBACK_EVENT_TYPE_CLOSE) { - // If the event is for the feedback activity closing then we should - // set the end time of the feedback activity to be the new start - // time of the event. - if ($feedback->timeclose != $event->timestart) { - $feedback->timeclose = $event->timestart; - $modified = true; - } - } - - if ($modified) { - $feedback->timemodified = time(); - $DB->update_record('feedback', $feedback); - $event = \core\event\course_module_updated::create_from_cm($coursemodule, $context); - $event->trigger(); - } -} -``` - -#### `core_calendar_get_valid_event_timestart_range` - -This callback should calculate the minimum and maximum allowed `timestart` property for the given calendar event. This will typically be based on the properties of the activity instance, for example the `timeopen` and `timeclose` properties of the activity could form the minimum and maximum bounds, respectively. - -These values will be used to provide a visual indicator to the user in the calendar UI for which days are valid for the event to be dragged to. It will also be used to validate that the calendar event is being updated to a valid `timestart` value. - -The callback should return an array with two values, the first value representing the minimum cutoff and the second the maximum. - -The callback can return an array for each of the minimum and maximum cutoffs, if it has them. The array should contain the timestamp of the cutoff and an error message to be displayed to the user if they attempt to drag an event to a day that violates the limit. For example: - -```php -[ - [1505704373, 'The due date must be after the sbumission start date'], // Minimum cutoff. - [1506741172, 'The due date must be before the cutoff date'] // Maximum cutoff. -] -``` - -If the calendar event has no limits then it should return null in for either/both of the min and max cutoff values to indicate that it isn't limited. For example: - -```php -[null, null] // No limits. -[null, [1510625037, “This is the maximum cutoff”]] // No minimum cutoff. -[[1510625037, “This is the minimum cutoff”], null] // No maximum cutoff. -``` - -If the calendar event has no valid `timestart` values then the callback should return `false`. This is used to prevent the drag-and-drop of override events in activities that support them (that is Assign, Quiz). - -Example: - -```php -function mod_feedback_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance) { - $mindate = null; - $maxdate = null; - - if ($event->eventtype == FEEDBACK_EVENT_TYPE_OPEN) { - // The start time of the open event can't be equal to or after the - // close time of the choice activity. - if (!empty($instance->timeclose)) { - $maxdate = [ - $instance->timeclose, - get_string('openafterclose', 'feedback') - ]; - } - } else if ($event->eventtype == FEEDBACK_EVENT_TYPE_CLOSE) { - // The start time of the close event can't be equal to or earlier than the - // open time of the choice activity. - if (!empty($instance->timeopen)) { - $mindate = [ - $instance->timeopen, - get_string('closebeforeopen', 'feedback') - ]; - } - } - - return [$mindate, $maxdate]; -} -``` - -## Component events - -Starting from Moodle 3.9 plugins other than activity modules can create calendar events, too. These can be site-level, course category-level, course-level or user events. Events can be standard or action events. - -Example of creating an event: - -```php -$event->component = 'tool_yourtool'; -$event->modulename = ''; -$event->eventtype = 'myeventtype'; -$event->instance = $instanceid; // Whatever instance you want. -$event->type = CALENDAR_EVENT_TYPE_STANDARD; // Or: $event->type = CALENDAR_EVENT_TYPE_ACTION; -// ... Other properties, see section "Create event" above. - -// For site events: -$event->courseid = SITEID; -$event->categoryid = 0; - -// For category events: -$event->categoryid = $categoryid; -$event->courseid = 0; - -// For course events: -$event->courseid = $courseid; -$event->categoryid = 0; - -// For user events: -$event->courseid = 0; -$event->categoryid = 0; -$event->userid = $userid; -``` - -If this is an action event, see the "Action events" section above for supported callbacks. Note that currently category-level action events are not displayed on the timeline (but they will be displayed in the calendar). Timeline only displays the site-wide events, user events and events in the courses where user is enrolled. - -Events created by the plugins can not be edited or deleted by users in the calendar. Drag&drop is currently not supported for component events. - -To change the icon of the event, add the file `pix/myeventtype.svg` to your plugin. You can add font-awesome mapping in `_get_fontawesome_icon_map()` callback. - -To change the alt text for the icon add to the language file: - -```php -$string['myeventtype'] = 'My event type'; -``` diff --git a/versioned_docs/version-4.2/apis/core/conditionalactivities/index.md b/versioned_docs/version-4.2/apis/core/conditionalactivities/index.md deleted file mode 100644 index eac7de5ed4..0000000000 --- a/versioned_docs/version-4.2/apis/core/conditionalactivities/index.md +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: Conditional activities API -tags: [] -documentationDraft: true ---- - -The Conditional Activities API allowsyou to specify whether to hide, or show, an activity when a series of conditions associated with it are met. - -:::note - -This should not be confused with the [completion API](../activitycompletion/index.md) which is used to mark if an activity is completed or not. The Conditional Activities API is used to handle the _availability_ of an activity, whilst the Completion API helps to track the _progress_ of student in an activity. - -::: - -## Files - -The main file containing all key functions is located at `lib/conditionlib.php`.. - -## Functions and Examples - -The class `condition_info` defined in `lib/conditionlib.php` is the main conditional API in Moodle. Following are some important methods of the above mentioned class. - -```php -fill_availability_conditions($cm) -get_full_course_module() -add_completion_condition($cmid, $requiredcompletion) -add_grade_condition($gradeitemid, $min, $max, $updateinmemory = false) -wipe_conditions() -get_full_information($modinfo = null) -is_available($information, $grabthelot = false, $userid = 0, $modinfo = null) -show_availability() -update_cm_from_form($cm, $fromform, $wipefirst=true) -``` - -The basic functionality of these methods can be classified as:- - -1. Fetching information related to conditions -1. Adding/Updating conditional clauses to activities -1. Deleting conditions attached to activities - -### Fetching information related to conditions - -The following functions are normally used to fetch information regarding conditions associated with activities: - -```php -get_full_course_module(); -get_full_information($modinfo=null); -is_available($information, $grabthelot = false, $userid = 0, $modinfo = null); -show_availability(); -``` - -#### get_full_course_module() - -This method can fetches and returns all necessary information as a course module object which are required to determine the availability conditions. - -Example:- - -```php -$cm->id = $id; -$test = new condition_info($cm, CONDITION_MISSING_EVERYTHING); -$fullcm = $test->get_full_course_module(); -``` - -#### get_full_information() - -This function returns a string which describes the various conditions in place for the activity in the given context.Some possible outputs can be:- - -```php - a) From 13:05 on 14 Oct until 12:10 on 17 Oct (exact, exact) - b) From 14 Oct until 12:11 on 17 Oct (midnight, exact) - c) From 13:05 on 14 Oct until 17 Oct (exact, midnight 18 Oct) -``` - -Please refer to the inline documentation in the code for detailed explanation of the logic and all possible cases. - -Example:- - -```php -$ci = new condition_info($mod); -$fullinfo = $ci->get_full_information(); -``` - -#### is_available() - -This function is used to check if a given course module is currently available or not. A thing worth noting is that this doesn't take "visibility settings" and `viewhiddenactivities` capability into account. That is these settings should be properly checked after the result of is_available(), before dumping any data to the user. - -Example:- - -```php -$ci = new condition_info((object) ['id' => $cmid], CONDITION_MISSING_EVERYTHING); -$bool = $ci->is_available($text, false, 0); -``` - -#### show_availability() - -This function is used to check if information regarding availability of the current module should be shown to the user or not. - -Example:- - -```php -$ci = new condition_info((object) ['id' => $cmid], CONDITION_MISSING_EVERYTHING); -$bool = $ci->show_availability(); -``` - -### Adding/Updating conditional clauses to activities - -```php -fill_availability_conditions($cm); -add_completion_condition($cmid, $requiredcompletion); -add_grade_condition($gradeitemid, $min, $max, $updateinmemory = false); -update_cm_from_form($cm, $fromform, $wipefirst = true) -``` - -#### fill_availability_conditions() - -This function adds any extra availability conditions to given course module object. - -```php -$rawmods = get_course_mods($courseid); -if (empty($rawmods)) { - die; -} -if ($sections = $DB->get_records("course_sections", ["course" => $courseid], "section ASC")) { - foreach ($sections as $section) { - if (!empty($section->sequence)) { - $sequence = explode(",", $section->sequence); - foreach ($sequence as $seq) { - if (empty($rawmods[$seq])) { - continue; - } - if (!empty($CFG->enableavailability)) { - condition_info::fill_availability_conditions($rawmods[$seq]); - // Do something. - } - } - } - } - } -} -``` - -#### add_completion_condition() - -In Moodle availability condition of a Module or activity can depend on another activity. For example activity B will not be unlocked until activity A is successfully completed. To add such inter-dependent conditions, this function is used. - -Example:- - -```php -$test1 = new condition_info((object) ['id' => $cmid], CONDITION_MISSING_EVERYTHING); -$test1->add_completion_condition(13, 3); -``` - -#### add_grade_condition() - -This function is used to add a grade related restriction to an activity based on the grade secured in another activity. In the following example a minimum grade of 0.4 is required on gradeitem 666 to unlock the current activity in context. - -Example:- - -```php -$test1 = new condition_info((object) ['id' => $cmid], CONDITION_MISSING_EVERYTHING); -$test1->add_grade_condition(666, 0.4, null, true); -``` - -#### update_cm_from_form() - -This function is used to update availability conditions from a user submitted form. - -Example:- - -```php -$fromform = $mform->get_data(); -if (!empty($fromform->update)) { - if (!empty($course->groupmodeforce) or !isset($fromform->groupmode)) { - $fromform->groupmode = $cm->groupmode; // Keep the original. - } - - // update course module first - $cm->groupmode = $fromform->groupmode; - $cm->groupingid = $fromform->groupingid; - $cm->groupmembersonly = $fromform->groupmembersonly; - - $completion = new completion_info($course); - if ($completion->is_enabled()) { - // Update completion settings. - $cm->completion = $fromform->completion; - $cm->completiongradeitemnumber = $fromform->completiongradeitemnumber; - $cm->completionview = $fromform->completionview; - $cm->completionexpected = $fromform->completionexpected; - } - if (!empty($CFG->enableavailability)) { - $cm->availablefrom = $fromform->availablefrom; - $cm->availableuntil = $fromform->availableuntil; - $cm->showavailability = $fromform->showavailability; - condition_info::update_cm_from_form($cm,$fromform,true); - } - // Do something else with the data. -} -``` - -### Deleting conditions attached to activities - -we have a simple function wipe_conditions() that can erase all conditions associated with the current activity. -consider an example:- - -```php -$ci = new condition_info($cm, CONDITION_MISSING_EVERYTHING, false); -$ci->wipe_conditions(); -``` - -## See Also - -- [Conditional activities Adding module support](https://docs.moodle.org/dev/Conditional_activities_Adding_module_support) -- [Conditional activities](https://docs.moodle.org/dev/Conditional_activities) - original specification for this feature. - -### User documentation - -- [How to make a new availability condition plugin](../../plugintypes/availability/index.md). -- [Conditional Activities](https://docs.moodle.org/en/Conditional_activities) -- [Conditional Activities Settings](https://docs.moodle.org/en/Conditional_activities_settings) -- [Using Conditional Activities](https://docs.moodle.org/en/Using_Conditional_activities) diff --git a/versioned_docs/version-4.2/apis/core/dml/_delegated-transactions/TransactionsAndExceptionsFlow.png b/versioned_docs/version-4.2/apis/core/dml/_delegated-transactions/TransactionsAndExceptionsFlow.png deleted file mode 100644 index 4b1c683898beae408cbd222dc08b7a6f65329338..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41878 zcmc$GcRZGDAGgda6f#1xlVoKjdlN#)4%vHVXK%8S9g>xu6;ftGc2@Q#tL&BW{;ux( zd7iubzW;pR&wGA8$#$K`c^t>@`}>X~R7pYl0ya4|3JS`FyD}2WC@84Y@Xr^43ZF?L z3eAB3&>Y3?sv;1Gu^C198a2vY2~kzo7i+0*8Y=3O2Z}P(vOHphA~8NhAzD>+PD!Fl z{0o&U2%!hqbIMk6&+WsuUv(>9%`eKXtW0$t(28qWD3u>;jf^rJBU@;>Xc!(ps>c7C zI04~@`YaF=aZYUd^ptnq^T#+#0=H;gda!U?`<X9oXZYgem25lz-!I_*?+c}u<1=N6<+<{U#TzyR*hEm3f~vp`W~F>up(CSyX#xz5?&pH+7^U&72sr zii%;s?n9yr)WgAMx}l#k^5YH^N*)_;WBP+$rw0)7=tp7R|Ex{rWRc zLqo%d4<}ySah#o-`!V@pOyv$k>|JIOX(_2MqYqitg*EwWUPxI?p1oSR;rRaH|?9R^{g-UQZ%(oR57S7MlU*&gJs_(qt zgWZ{OyCgGHoHe0iVJkVAd|X3Q^N#r!`tdre5e@<8sXEU`j~P_|Hc?+UhR7;%m{i0QvDe^giIG1Os zmlhWKx`{V&dwP0?mmkY!JFJgZrlzLq)WvQjcJYxY?o590sMIP_$c5iW$FD*-x7{P0 z`+25E+hU77vnxAB?rOa>*Xy9o{k01pshd>0jH9q3D8zQWc~Epia|yd{nps#}3YAbR zh#Ng+6bwy8~Mb9opL3 z_Za%0l5sjXIJ61DByp_KxpU`^;iso=3vucjXXU0nCfK>yPrlbIDJv@{r=+Yq|D0_J zFE1}Y@8`Obm#bE&F=NLo&!A#u#mtk~fs=zC-a<g8wl}_|)}q%Qz=DE-tRI zv9U06cwoScD|vCzB%egBH4kRdCxcSn)Na#sPo5h$&fm_-$`Ux)>A!dH9t;ignW<;u zUruDvQDNwv{`m2uX`0)o8N0-;#XF9RZAKjV_-Ub^GUXZi*}Mn~eh=jT6@p|AK978d5?<0C}Eh{*W#Ny?9U&AC>CxwxpP#Wq#Q zQ>$b+)-yRd8R2&@6HFyRd*9OX=BY3{d-RPLMBnUqpLlw%uB>cmPd(Ybr>aV%f}`l$ z#FSA}s~h69uw9XUnu6WH|B3I=r)HZL<8CEuSi zh~O!ZVs%0lB>#rmVz~cOY5ki=)r`Lk{i}!TD+vK8@2O6?NEy&EF`b>9xOsS#uiRr$ zneq;$i<8~N!|yaHm!T&Ybmy{(3JEbYGo${=7$+MLot~avkGzCWsq~7bFPU*9@$vJw zMp04WBd_S_=-z>Wj{{AHR|?Pr#q4K4hBh@d_4f8wS6Aa)X5ATBINLuvok|n*c%g9J zt9_2QeWp3s(7@oi?811BBTU4kObyBNE*a7aHQZmVc;Kd=l5=C%?Mh4k%Eqwj(@;Wn% zwA*N!w_nPOz3bVn!4PO*zwSxOij}Q=$9l8^rf1@)>)O}S>uIh{urL=KoLpS!0y<4N z4{a1Pvj#0{Yip5@uw!LqWqNwL?rUM689Y@>OG|5>lr9rX3k!}Ud99*&YD7NCFTp?!4KuO{f6 z1Sl_%`+H($vr)ZnK5kCbN_8E&)G&v;M842q-jmIi z-d?2|9j~qVySe>`lO8`}P6jP1`Vy|7hW<64tT~yR%P-+ER>qwcg=PeC} z*zBAfo3C%qd50Gj6x_UVBc|ObG&D3T9`@+z?n2lpUzd~!JFTdCc+|r5XC#`Km=N40 zqNyAygx1PwNiiW&* z_-ia$6$qC%T1B?+H!;^A7SGVeF!J+XiTd2$u37iwPQefQW0UQu?8Z1!K|k(MLFLvT zefpesOWA?b)_blr_+&oqZ@R*~PgeEp?d=_E1gNR?H)mVm&o!*Wa(hrP$d_uFjLzdoh7@+yVTTqN$FGrK&VM=A%uMFfl z*G}{Y3A7Or6Bp^#*S&hx)E|UmLyc#-@$xMV$`iyn9eg`m5)?bf-IYPh;bNKqm{3)= zQ+1D*l@+zocTgCSNXiE*_S2_NSy}WoIznz+^LZ+{HWTj#`$^6TqOfk_o}0$SZa~Yz zLP5d1WETqm!Sw?Jo5&WcjtULlZ^nmTBDCRb>^Z*h{>RT6j~<@YEH^dR2lR zfBiXeP*+lT8u+%K=CuBYG~UomI0?%UZ19_BZf#oJgt~+}G zR&aAW^gbE(Zu#`-nc``K?Z~=wcngQ|=jTud<8NqAi)~op;$UOH#*2uP%~ljTq(AID zrMbZUM$GT&PbIW1YDqNg=QMby@o(W_ynOjGBqRhNA*?Sf42;0QK+lui;c7*|X|l3m zve{qExHL62jV8qyUlTK%eD4M` z?I8T&y?YnR(e8SA)hXnvFvY=iSYKN+iVMR3{5w{EF0fN?Y#%TlvCx(Zs>gr%k0StXQ9_v>*q0jzWm8pE>3H-^XCb8t= z&QAH1F0}^_oPJCSmXExMjcvBLln@P=R4##a#ER#GZoSuudw`O?{jI|mh1~vI{Lw;b z{4U==MO=Y3$jZhxRpWTQfU96IIVs8Q_`p86+5Y5cHy{ArmuKpOhs#V;pzVjdvuPX&rfKYTd()|ZLg@e)tmNKoHKKShpyXhTZ}F7<;p*!CVODJdx{)5gg{`*4Mj zP~20!WVl~`LAjCG=+sytaBy>H=W&FTAx}zAy6{<_G}R`qsUXFDG&wodVpW=-01UK5 zG%{}mEGH~2?UUP-#6#S|1-D7clr3k|`ba zwxVLX3Vl@GVSBNwNV_U1I9Pb^tKr%4l5ouvnl2NI`LcNKX))Zz(s=x68oWzJU+tq) zQc}+QRX;f_(<)kAmfy3rvNCec%%LriU!*9#nA^qH_~8MzB?DqJS#(b6P`dOqTGG6q-3BD>(W-sI#I2l(PmHTgw6iuCe5%F%&P5>;75OsYZ{CzJ6aRf zg&)BJIgMn`vCieG=BqLhhiC2A@(sSJe1Ox{hoR<9MG5LVQ zot&K`sf2~7e_b>*=YGWB^_On@JGL{d;gg}iq^$4i$~!5RI-;4O^n%y^)tfi$TwGkN ztlyggaddb(yn{>{V9tI5NO|?@!v_zHOEnJAn(|{hw1#|eZY7dkL!qJnAMR7gjkQ`z z)`SYz^3Y0Qy1M%iM$Vd>(;# zd4Wi%#U|m-`Qb4AXrz>ti!GFUArd96t{IC)-=#&!J^&}NIIUmj4AUvPtyN- zeczn2RE`*(KP}T8b%05Z{tyv%KxLKu^n@uZ$EAOm&>zWh}a`;jj>)Rw+#@05O z#xVn&ClcQ8-94EyC}n>5PBl*z6BDyoyQ+Kn@m9s$Sf4RRl5UBx-89NBB@wcN{rSUd zpT9`$Wrja&)JhRe4)UNey#-^*}mlmYdv7Nt~w7;w!4EqR2RbeCWj`5o$r-rwL!?Uwu@bk@4vC_|WyB z&hw`#6R|pJQZU_6_4%iqLFD)rTsBj6C%xi$_L{Sm(XCuxnR~~4r6=(2Je8XJ7)m%c zHijjA)u;`vr=X;c&+GUASS_vEJ~P;UnB0;aG)m3-UfoOKnURiNSXg-Q;6Y4%+%_*% zmet{s>r}#=ywT@2-e{_L)dOh|47Fpi|E{ZSAO(4a}yL4rAI;xSyb0ZBc#$IrjAlSf0m7q z>R+Al#B1@Vck9)6%7{`~CU|en`Vt6MeMbA`FWInLb{KI$Pi_2}Xv@vmA8*%eQcrrX ztxaaDW=s6C?avphE&;p;`tsSPzNi=|J~aLv3rD~yegGyfrE3q?3keaCQq?e7ShWso zT0$BJT7#>b#?i0<+hY=Jpl5?{p-MBvw(GMW936$V%#v}Md~9uM9iua91%NA0}W0jm|kARj9mNTUbwq{i)oece}l7k&=BrZZO-^U}a+=k`#P*=Bm zyHGjJj1)I$Z*LDOZ^7U@n+d*Ak;Ny#({^@t&b3DIQ$)g|nd|y6k^FhBH&b7^xy+y? z47wzA#mC~}&4=4d39Ju4KaRe+b{zXGEv>lEtkYy0J}Z3mjn0H#(@>#bD`y zd<(VK8j~mbWb@b8`!{$z-s6YhHW;~@w50O8c>Nrk5`sDbb#ZTP1Q7S9+D@+9w+Yeh zfzPbeitrd+cP`b?(bf*vOZ&wHmVf^wHf9~hgKaC_lJ6H#BZwXQCy*4j4e$T@RVMP9 z-j{iSqi>n%UPm`X@u7JIPK+MWG-C&odT4NP=Hj13;UKOWzozv4-L3Fz*J2;tU}7S_ zZ9~ymT6;mA%d9jzFw&_GIwR?)r1m@C`r_kBDD_^W*6<;48LXWVej!m&X9sgp=l#9{ z@dKPj(#5i%)OS}1)V+>?LL3DOG3g4*Ekgy)sGIFcXo0+P+u_Rx(;}2Z^e1|2C}=36 z_y@IRGW4`TUBkvcSX)m=?K*-tHa39gpbh|{6`GH9&%Kf6U_7~ON|- zY$Zm87rdKG!e?$kaK|#-b6-kz5fc+TxVNw+>B?^2U+S>%8Bh3l0|4JCl=&o6Y4+pg z#<+ALA)!pEh$c2@@e>VT7I6O>0SrDl$&fiTY@Jy$j_6>X>LE1Tv6TQ>C8ge+dnsNA zGg!qJwTj*X4Om=!vAz)AT)eoqy$uvOFkJ|m@{vxyFlxjKBh4qfBH5I#_?Q^`Z@n2g zIXN);dyngYFcKX4_JGPUUTv?EBflI|o(RM6?Afz{0oAf= zw{NS{#z;s@-y{larSd)=t+W)IufDqQ);~R659k+p`OdGUhE#6zG4MpF12pE^i7x~w z>FTCwFki&M>9?qa-aR)@zgt~heK_(eKj5Qz2RG=~ph5dND_7!Q0}BCYnj($TrXqjA zSHKfxWQZ0Fb|-V+ymLpBHe>2>Be^4a=S%wwYm$r6ksk9kj=Gx<qauFn;z;6QN z^ySN!qZ9F?mBE4oE-7p4bwKrkd;GdKm~HmHf6Byb8bxZ}-e+4|Td?u()o%QgL9Cp5 zu#7C!9s5(qwY24hnJUku(7a-NTv%YP;eRik1O>VDZ513zIjIPV59Tk7?q*} zQX!S!I0`Nh0FnPIGXO2PY%!4l2Cnx=K!?0G_>jN}XMjKszU`M606y8U>I1+Cd6l63 z`w#s0n|vPm_L)8JSP*juCJ83KC0DX9kGa_+E^?>|Gv+tPr&Fc2=F?or*RCN4sv)}3 zj0^b9JApsy&+5D%d|ltO9(()ny=$LA=}yV~B+Wcp;V_lM}y~{27 zrl`+G3DE13a^8SV72b;{vF-FE;jlj3jsT>EqF+pFIGed}!yeWK6xZ5yDel25or~wX zU!tI}S2XICL8<>QHamvN!zqwtrjgb#zwh3?pQlP5!Ep2DDk#CQm9KpJ z7TvMX5zk_10TowILqh{J)#jPDwzgg~E{n=hefGzXANLL{EH2KL9}PI745*wGUUG1B zbmB{`ulJUbX#>24F9sV<^IqF8$#~|`9lL1}S6ArX!XqMz3JX6*a2*~u0T=UEV$sGZ zf>Y)4aMqj8Mi(%G%xSDY>#$z#cgfLRWK64=S&>hX(30)7((e*vRovd*hCim9r&H@} zZEAXbR^du)dxhPM7&8wbGWP{&D9sxEFbcI^=fI5q(z&>GdH+$6OE2=-`p`u6FIQ+4 z?f;n4`{2F{ciism-}q8F570@C;}SLwP7+#wf4?V)hO4VLnV3MQg;lMls~f5K<;hN; zv^>jy$vKcOcv6b;^H+dIH7UPy{kn7rACvrfwE}KV&TS~87lY@Hc301zKaa?Oe#t6o z!Uhy)Kwq$#i5XnFdew9J%e9oQoMC`bdQtcWpL5UW-eo7ng-vyEa8Rwl2@0!#y~)b# zO6T)-a%^ReezDQ#A2vT-=`=T3F}~We5UEY9`p`(0J+oCFQ%x~dVF_M8H2?NL_ts%W z19)=CYkq6aMGj==>9Lzd*y#EmmDj-|pjid9WK_&e95Jx=XKtB9QwxOcf8CDVqdCA5 zck}PLy8;BsveZc`@wzplb4nK;t7PYkX=v z#H7dOdAsnoeoPd96sP!%OOlAY*~%$hpR80Fi4Ykvbkfi~xr`EO`wkPy#H|J4 zonCRBX7lgS1p1$n9$dCGRZA+&z&9gaeO@yt7kMd>M?h0FCqSFuO(0H&-l%6|!;V6V zb>H*J6R8ODKt1J>`siVo>I$WM*{3~(6l%kmgw-E8=?QM-6GjcxG*CAP|3JY*>YyQi zQeDX-8MU=3qcps{8X-pi0(oYYm*8@!0XBv}%%nU?8dVIra7?>jlxi@`fp}VJK`bUi zztZ($%Jv}3b^0jfb?09p{&<>M~Q7MRW-hJVS6pfNTu^g8> zOa#ydz|sE_QLyq7uR@(}yEs;5n>#_;L3f9n+o?I|0yq;88Smb`d-m)Ss}o2F4mHQn zXe;Dyf7qX#i&6TWYuX5o)hcr4OFhnYW?v_Ip}gqvIs2762m(KoM(e zYgp~qubUojErjq}ldxz7w1D|!YcUb}C{XI3m;?%^dE#~>aUZ@v$irVQHV}$L_~Fxf z_xnOeF}wUCJ>9lat5VBaM~6b_dq1!1#>?gz#QF1mtGhsx_jGrYm`T~#6id*CMnCtP-!__JrLS53pCelXdLbZe$b`Shhx91)B{>uEN4+FnJLf4Gj&KbzNzo z@usGJ32?Zq?Ah*l2N06zZh+fkZEX!mm`Hf3pP%2T##0fx$9vD@cVM%GEvcl0uX6cv zA%~`a=p(JKwKrD#7)?xz@6P*jlW7Rtn(giF2hvRyRHWM<%YQVI$$Rnjy6yExx+V9i?CHzB-;1S!I)8tt11%Q)YdRKl z0ZdasmRLJ6EDh|ru#p3iNlZ+~+O7KBtwTB5eY(6dvoX-Q8W}kLb)kD*ebWhtyY@CSMc?VmMquLAg}@5h<9W z`0S(p#fB%2#*1|koM3DWd^^{Wlz58 z#pE)8jyhS;<1M&+nBoA)9`5uj{=DxRMLn_BnusUicR^?}Isk!9G~H+@k`SLzsNGw>DKpd+ih6gLjwa!dhySnM_*%Lz5Q3n zVRJi49{THFkVA-#4KJP8aOE0J#}JfNpr;=_99RleS=D0ArstZoKlA*#2fAr?b~a7G z-<(};MjX~Ak&+1R+qZMGv-1Wm;$$lw7G#qz41~}G0N19XtPGlrRAxK4s%ms>1Yaqu ztDABp;bQuil$2;Nr`k(1hazw;wL?HyrZz1;pAai3u&Iy*Z% zw8WC*zcr_ze<|W7LLJNf@2>xJPjB-&*0tG!-_0bnv8erDE6t#-a5lf9=j zC}6ia$XQ9B+yBN3ZlyvR7DmPf#rNM=R+Jfu*gouB5__GKBUPj}_1;b8fX0j0uu_YY zlQW7+_`4l%v0i;zbhOXE@H;InEx&N%*t&D7g0#n7VrUM3qn^eS|3=NQevqf7qwDDC zC}kChCRWR)m$yt+$n7%&Q=ovuJVK0-kM9V2JD!w#B>-FM)8rTmx(W?pE_ir&I5|}g zT0E?>xms|6etCHrbQM@huy{c~bLA)Xih3RJI}vv7BR7HkLz`QqxJ+@Mt$5P;U5ekl ziI$cGF4@C_zrMbZAoCu!wI6$4UY_gqs{)r{Wu6YOW+M7gx^#Vga({`382}3Os{d-N`{bDh9?gZ0gsQi1ljU=O)&&3K zMuqV1fC|_`0L%c-&BLR{5DSP5>E)y85!~1Lr8bvO*yz1?wRd*rNw^F0J_sToKBQU_ z)xY|~?WfG3;@4t85Z(g305xJ3+ROJ(4mq57Zx)J6(Drq()vr0!=z`dAaNt^)Y>uhI z+wWBz4OBYV0E4JQ!06x%rYIl)uOVi^Ti5YQGF;=rbgQMK6ZMyrtiL+g8d)v|H-prT zq(_byQ*1%+HtUy2kzF}MWPr=hkD67lu28Muyx*I#bzoq!8UT~8fZ>$XTJ86(5x zv9|`b+3_BF0qc-I+DJErWU&q<-2^4qYXZ7cM`bfY3F6&vnNeOx%em;H^9u_sI@QtB zGV00K#gk7~l#u%j-^$R)H#_ z4p0@&RAmA$=mu)wofg3DmqG(5wC~^d9W!^&W7w?_d34Wqq-TRP>dxbD_>)))8A@#n z4wOmqDM^Orr(0J#aTP>FPHC&+8_ z?0_$1#EK+T0>to7sdTio8;1{uoK5H+fI)0!ZH+?M>xsy(OH2%PayVs>e(NId(EZ~u zvp2Fzj6~NJUNAB<<6gKB5gtA_LX;NZ6r#%X0AMi9d%{9(8d9~NHDVF?Vd3F7S&&yM zr)jrgl;9qaFLCklvz8klIQ2=(^c(%)^BT62uh`kObwf`CCOpCISh4@Hf-~=6D0EoWU0iO9wOR3$N4|Qe^6(+c$4ji< z9z@m*;73N%qyWHKb*kUEZW;ig_wHRBoze4XAwZ{3<-ts&DBw|HgbAcT5RQ&C$&mA@ z`P)^xC|ARGdbG z()TcT4_52`OD1Y~l&xT2xB#BHgUQJKNslNeRRaUsI~ITx#R_M))LknyLqkG;z&^~( z@&$w6r|Q$Eg8Z@Y_$VTyqwzoJ3VR;ytgTt8t?TsMjFrs>x&;=&_Wpj<)2BcV3|x^j zXLtH5#&(CUxiAwfYakn`6~Om4S7p}*cIeIYEz)vxSAy@3n>)_xQBDCqj9tz8+|trz z=!6LgIbjEvrgSp`xTUk1g_(6(cb_xu-9W%5rH9v-@1EW^%}tIsVvhe+GS<`jY{c)Jb}ew?0RaKSx*lEqQs)}%&N*{pqM+#Kf+n0ZiOTY zJ4KA^D9W_x%i>~I28N(f+JuhwDN$Ga5^mfL6O*1aYc6s@YYY@zm+4D*;nyY|UM2Ze zrJ`X8L=G=nu=(s@qWGZy#!NOu`>wVYG?6j=yuUxuUDulLy-qVye^j&%^h;JZi zHi~n&R{UCl2jE?Cv?t%k2T06nDs(&k0iu5mp2m93QW_mUxLVJq8~tqz z1JiFYCUoq&dxFt!TOO^SN6kaSzggDUcp>X<>>K%GS7Q?qbg9rhqS_kpIlg)GrlNw2 z^$Na=4Lh1#Y&)kW>h(ZroPLF&V+q8jY30W9hSx7eT4wfdP;=-aglcMGg@T{~_!88{ zyQ}zrW5KTc4M^I6*7!Hc@}KmYn3bHO;{NV#5n%n-uNiON^q7md4P`4^`NkxJQf~iw zf+jA0Zf@cq?LPS6`}zY#+TUan6nvQ32PQ`7Exm!+>qPltHCGl)MzK`{1R@w!-rL?0 zW8~l{d;gxI<0E;}IResaYS~}`G~-fJQ=`1&5RjuKWAkPa?EyoN(fM>DHI_oVk>>P4 zf&N>no4sh(-c25Bhj(kMPTiV~&Q1CxTwiIp##3{>0cbFMF?hV_qB?aTr>b#!&>|hZ zn;oxS(H?(vAM%`M`;!a{n6SAV-ZIblw0UL&Zm*!AnXMks0=&B4IJ5`c{XEGVf4b^C z*C+U7xKpS@q^UfiJrur%pk-sT1skG`p>fq1tWB9*7@DLj%)QR~`jx@lyz(lV#$}ii zGS4;Q3~*r2a;s4Be6)ypo=hWIzPR1ss@$7<*a;*SFWk2Jt=0A)^Svj8ZNL)=>kNE+;_~5y}@3#ea;gk^T^Q9`%G~FVu37?L?m^Y#K=fQHYLjE zba!`yB_0bMdC}9;gCqrJ62j{WL?k58CVXmXnYrh4Xq|Z;k`L2UEb$$pIU|USDNrq; zc!?uG`&zqQe;A>CA1q{lTEN6LG)SYa3GBVWY%OBMwG;`E2$ch`9$3!BRLd7JE%h-z z6A9fY6b$T`?^&sn55A0wl;e(z&r{uRCUIDq$uP08uhBs|5zqb*09R^xQdsEd=6W;4 zfpLN|)-p9#p~WJK56?s@a}%CPQBfrbh$%&Rc@XaTr$ks&DP1t=?BWvJR8Uah@9*#N zE?%=s3Xz?ag|sfi5~#78X#$rn2D!M``-u-82_w=W);f&@sK^(e$0mELb9@?`nYh>o zkxoRTbzr<@>NG_+_W-Gz`H&m)q7B}S!v6;oHQ zkLupNi8qhXPC2xI4g-bscg_qL!HH42Ul8N1)yNmn1xq!MHfL~(RBEk1<~vl(uI9c% zLqtGu>rqnxx8)ExITZ6$v2U65y^{P&S}+)9d-{^*BhSz@VkeNBTI|)p1&9}q4-b<3)h3q7YZC`(n4EpblPvNGV1e?$#0Fo$GjjE!H28FMOVWir-JyN|E6!**CdMOV zEhi9zjuWC7@K%gj6hTZx1l~yS5P}a1XhJ#qouU!+(NDOMB53&9A{tkc;&&u(7<61n zYj}4dWaBQutHAo}-fHDiIo?zww-Xz51(@S;;13AV?nUY3SFb&u!Gy8ZUkpkul zujhv-Dypg#UMELkVc3dSI7mfoT<^R}-=FoJcpA)(x6(?Cg5uxsTU`a71gz}tqqHao zcu);NwzA9m_oBK%)o_iHL~gnh9mFy;dvN~y&|tfTVj<-rxc=YdMN=^Lh`%b6qL?+% zt)4^q#;^2p=lp906rWHtJ4>QP6J5bqY#u1PlHA`gKD{T@>cxRi`Jmoz{}t%`zx2Y{nIYN<)lsGgdIW$_V6dW_ zK}J1`%uj9@y?k^*0jP_priBN%_vdQLvZKDcKH&OQ+}iZH$R)vk*|b09Jyp*HX1+hT zIBkuVA+KJq${eU!F1XE60@% z;M)eWIkz7g+!))xUw;yO>7*HEsRo&FbyzYvhhj2OC@QboA7k+ahW+F`*Sx6u*2@O-&7S zJyTP{^z=r<#SaB2|3>qvU9nTt5`w;`in32%tL0j(FrkKNgvlL)tQXNWfVzNS{1^^p zF3Nc#*7;e`%EkIQv~x&D9j@C8h1@}l58h{|AcI4IME>m+TucZUfvG)}UtL3^jRN?u z@8AT{LrUuR)zpxL%hr~|lV^*WQ9=fLF1!>V*PeniP6)ae5YpDZ-cr8W9|ZIX^Jkl? z)yI6}xgbB()p>!%0@_U|>p*$+2%iZInskBz1bCl=A#GcT3z>jwpd-`-9@1i=z>o=bQxZ+x`CPPc}_q;)I zDT3zrkU(pNZ$LaAgt&sVqh7!H-?-IiH*4@`<>p%cM;c6XGkVwD@91-2?qS?xW7syn zFoNXf16Dsd6H?(u-3+T93tmVnq~?K; zaboNJa}4+wwIZ#!#Kdn)OVXTAP5k@Jvcj5>=}sVLfNy0`cwtsG2HZ!gx%x?wp^>)ZU%gIrLTb8s?-8|OOA40enEjWsA>2| zdtW!uvW@Z;g!J}ixzR^)I?*Evm4ZfBRA=$j#v{$Uy z`Piq_cof2(_=M;$M9&@I7ai0K`{0Cp(T5C%HPJ_dTQ+~yAp4Ovf7&g>8{p+)2pfS} z<}2+4IRXhNK?Ya)! zIMeT-45^J-GF!*HO@GFs;S7JI)j}70ozT^!%lh>pe`1#j6&00EDs=z^P6KL@a|$$f z{oq4;ITVVG)(aa%|DsO%p4ANi1W$;M2X7qGXW5@~Z>-jZ?d-?Z#HFA>ar}=EAg%!~ zJQ$53vE$#Uq^_Ru?3vgq0KeaPBYTqn(oeJQ#lIlgd9ttdU%i8b83fBL{;q5eYiN;E ze|K9p7ebWgyKvN)6tR&7Htt26c7U6`V=8?`f$G6NDwH6SwkVC_s7F57oU%%pu4un( z@%GTs1EK~0Kfuw>i+AtdH428tW_yY>96u~H)D2n?m}q*?dV>!KunZ;N%uja|DGDwgr>`}alin}FB;66^%htHD@2YRh-`a=m}+?gZ%8xy5V^_sRg7 zEu|P`@GW0%d+rtOAWn_u9?Oj4dcLIYXayV`v9Ym&)-vggOiWt!UY@Y{axWa>wWS!% zLdm|(Ivu0;3vL2F504$)O zfFG?wgZVgytfJbDp1KFTm5{AyD9%@~r3by5e^BcO&Of=5FXbi(qv<9vrKUgGYR40@JBwyyRPw>{71chZ6#jJXZ_r@i zQYPY#L%2uFKg8 z_+sE;u&9I%CncxiceDD7JJmgZ$wW3kgCiLr5VZg*O$l@yhVk_vRUq}42}tEg{LbMR zz3b!>nQj1!Za{D_SU91J0jxubqv_F|ay#nDs4awM?(hp@BZ$>l5H!hj0<5u<_pO^1 z4UF&MLN!lJ3`sqKP)Ch2!O7BX3az8Q7x{&SFSyJv4I%N`D6y25>FDL_THSL}CcW-6 zI4sm+&wMREYedW&bicR*(Tc?%{;-Mz#20MpPS!ER|s%3Xd;<#e}3!F&%3)6v4^E@fZynG}-KOcUlDNhPmL^Y(r z(l`r)-00B-A?X*w-f2gq1qTNQU%n^@^a3s}8MN3u1F{8D;2=41W&cePoX@!qf5D;> zyfNMoY=#q3K1IN{kVkw1B@o>GfWKa88kdhClSPnD+=X7*5klnEo=;)tWQ^>SxozUqj8BJ^u=1lxw>e zH4@J$fN%jv7{E)msTzX<%y2LH<6taxNP@0=`|z+jQ{3Ci%98~)?~xB4Rbm;@?M7@6 z@dEv@laEP20J&d)ut6sF4bVH3PW3$1`C7=yt$zCk2WB8c*}!K*lW3jWuc@U)PDQ1t zvf@w!;i!J(2^SC})GFGGQ`eeG#2;pz8#>Ab{1=$0z_*V-85F7VZ1N}GR5o9cuAM@FpLMG^brqs+u zAR@T3nc|@07ZepmSjEWDXMtUR1FXUQI*S|)>mmWYf6HOIF&pj8zmh(e(U>2&j7Y#v zc2U(J^uH0@%Emg*ckMl=WjAN=P6C@vtnY)`jlj@9Vvlx~xI~O1c+fe@W?!P22k+Jo z5!I0=K-aq(%3fhPFY^B)xaE}32I z`%eH8d6Y&uY>i3s46KKW!Y7aK-ff4K1)U?1RAQsGo12@+^DB_HBZ$qxLjRxqmFWZv z8Laq7>dYA4*x9isNR5*XWB*DVe&GWU0El!E0Duvs_GkkkX~`bwNH*>KvdaW4FT9Vx zfx^=d6=%~COM}H|J@hM&_qw^r_-OM=2tF~_mfz1OS-tYn3=uSVHI}U%IaT!^5et4hIIRX!B$u~NN`zM0dj#_MP3kkOLJRHf}!A0 zOl)awJ%hv)oX+%IHXG6f-CbR&w+w^Q)2UPp{}!Qi^YRA*4e1Hv*9K2m6C*MP3j=t0 zUhbFKKH?{Ic+=W0fut}F{mW}BE7-WWkNHwTyjd)buDpJcx{hRg)u*~Lc#wdG$?R<@ zLlCfb^78Zx(4(Tcn4Gkv!&uOD!dMK^>B(qZ4-dF`@PX&qJopM=Hx}}yLdU@Fjk3E+ ztuc0}t`H@3A6=_yROVs2rz$os>c6mK;VnPve%iRZyTg_W(bgJFV3}p&^4aL4!f992)Opn*n#5nZTARH1u!)=-8N%p zWQ1dDK!pb%maKw8yv(=SEI8|GB{dE*%@FAVlRm&Y&-oZ>pc!d#@jLFs2yk$W!e3KBP zFhj-2(bLmk6i`>3sf)I|M-p`NKosxB_(X? zwIfzuK zBUXosJfL?4yD9ijsNBENdiBA(!sDsEBWq z0YEj8dK8SXUK#|A?dK1`FM^PSl#l&$Hi0XFicQEM|GKE?;k(D?Vq#5}B_BQwj?iJq zMlqxN)QONV{>lSPUk6hOc)p<^!`jADv4ztvl$D?9u%-*RZGnpq8go9VpwlNLsCbli zn1L;q;CQti96L1fL1O%g5o8Kk9XADL_T*Dq};z?igcX$0bD0dmbl<(ZO8N|L#ot;)mWj1Qx zWq-ilYG9hg)AQ>@Hnj9IrW-dhbUh5D&~P%k5GXs48c-#Tb0#3YQ`<{S`N>58G4FBl#=Z{J)meYEq$j2JFhpSoj$`u!C z{{NzZk?CnqofIW$a=p@QJO;C3e`xWr9B zF)F}b)L>2d1HK6vXZJ6^#(X2??<9rtQo6xWNrRaztw*%6p%%aSaw`~z~w&{yJXDvQ5gkMDRdrc#cCoF*6BYIyoUKi`sj8Ts3U6Guy8lc>jPRv}2$|-9 zR;3LK>dMpByvW(7l5f=d@}Ju(F6VWa7f}44_TD@m%eDO*y^{=ON-8pS7ZHU}ks;AQ zWN4twB+48@W)Y=AA=Hf`sZ^#i-DZ_6qG6c{l__K9A=%%n)@qH<`~LR3pU-FSKej*C zvz`^Xui-q;WToW6dFYr_tao7sHDnqhWfCN1$xcgC3=w%&N=l%3t_+qS=~BTM_U zt)(3r4pVn{*DAQtKZCdt4HQ3SW}OgiKQ_#Bf)W}a z&7}F4n#0er?OfW(wPp<%rhN>uNEVD&@a(M^_m!sZ;DWyaI59m7Pe-*T0~w$xRLR(J zZuuq)hZy@GTX*##s(Ez8)$5)NY?#jOx*W^ee$sJhIVrkBly921`{UO4=AM_ic6`xD z@Y|cz_xUpx<85DfOYRhlUA%Hd!S~x&Y^YYRZmi_y_Jqm+`z6k#saqnNh>+TN?8p(Y zIu;U~2M-+r{B0|}26*s3A>lPwf)a)A3Y1q>iHeI4gD00mmWtIp&X$%IEPPmBIGO0M zkW5Up7*PJ2ynXi$fb|^uws%5T({FaPT<4YQTnOlRdy9X~_F4v+=5Z6jRQ@R31-f(jIl5<;*1?9dEdYQ69Yr~(M{FkL@}VM+L(XF2Csdc^=2_KOY0aAao~L;BO_7I3)YxIAcSMp zTzU;78HF7%m%wnu+@W-1Rh(XnfIP*lz&6_U?130YGFl?@jP#xm!!^vL=(W2Rv1H3G z&3$H1+9eO6>MKiUM@L5si%&TCV2)uV1ENb37QqH_mWP|WCF_CA%=9#t$-dpYFN0-# zdq)i@!7?T$4K1w%1y5Hb5k+o16mty<$@utqa282#h*}~08pKmRNMr+)M)jHBLA{8L zLR>rzY{GfvEqH)%==MR@k4=hjk??-LtrFb(DX5Ls)1U^Q80J104K;S}4m@}tF!|@w zlO2=x9U>Hgs^yiAifZ*W+J(JI3l}C$Irj@yDlcRxELv5vSwKc@6@}cK1GCB zG9?${uORvL;)daW-|RX^uv3Wvw1kIjH$5Za?!UmoPB_olcw5!#g+MO0zClg@e?}ASG-cw6fdGR8^pjl_LKsX4HH`pHbvt@o#ezcTYXJn8w5gMkT_b_y7eoGe*%Fao4n&yF(vo(w{Jd&E za;U;FN!t{y{p#vCKBWYw2AYx}N47qb@aqP{$_vZadmO7wS7xOeykM5A;_{Z+kDF>L zv2pWem|vW@v2WV7Z!?pObscIwi+~u20*W4;&CT#k`y3I;LYEYOVsmcYympX*6SJB^ z%z~+IPhV5FIphccwioI^=nVJuaY6CvdtiKfYTf6qy40P+g=xFwTU(-UOJ7^eBqgkJ zW%pj2^rXZ~%J-f&U66cwKAyi~uE^|6Q9l@?5U7 zPNrUui{oWy|A6Quh%^x7;i$U@u7D0d-P8k`ni~S4)d~s>gpv{oNX2tQu(|Q>a1n+D zctgaVefy%LqPCQuG+1m^GQjNVmo^bUxH~wBEYES7LZRSHU9Jp=5>Qm)h*4HOas+}P zSbY<#($~9KnlKD|)R4P)!U-f6w$u~bzK$gg8+TD6S4JFQ{$s#TCRQ?l+jN+1_vP1{rA zZ-$5w{O1^`BA}<`de}4ZK5d332t_tDPWt-Icpm24ZW3l6(^490HgeXG!eA}I3E4Xs z!fK}VhZdWNQn;^2MDOz{Jb%Ik3fwjv_UR-5HGlut6kYAmnE$ zeR(!87`!y^`r!6BIhSz0tscId-i1R7v2z@?{DxC6-nHew+u7C?Hub5eA%5~zSW7TV zYnf%S+?nuPkKGerONL4p*7vj`i;C@oL%H?Sw_4k_Zq?zKn4fA-JuH%+UTHBpJ`UIX zUEfz#RdBjzKh0Q%NWS+)-UcF3nK!#1zOvm0`98Yx*IGVfueKxIAw}4_`N=5)WZI*H zZ5xfpUEz?dJ9Y+MrEJPELSUPKZcRT}7bv}L+xK60g>%aXc#iOnm#KJQwF0TPw2fUe zo&Vx}cvxEvObo6cYwg=A<4(%iv+OIMxqV9*WKCpLRN?$&OIpEbh;FK#gM-$A14L}z z%sRZOGCXQ{Q@O(dq=qTZUP!zLL`wnrUbu~WyJ2P?_jA@gu|1up)Up1QWGo&)jAopy z^WIyVixv)1Vs_Vmz=?UQ50>k0? zdwXbgAX}WK&{b9V?Dj0|Kq>Ckc0i_lrcaD--F2cwJEj#><>G zN0~w+$V>OJtLwS^k8-C%FA5dl{lnuCphIzl5d!qAT17b|GomtvX1*!=6|bz51#&O} zmptp%3bteRdgN&TvclC0;%d#f9Y=B}_y(}7I~|2>pFevBQ53%Hn=)~0MZsE%ZQ5i} zbi{05Z*`GlZvRYBq_dK4n(=&^@4OA#QuLa|wmq?d8L64vM}tcn-}Jfg@$mtZ-8m2S z>Pi+W{m9DNTfqYsF~=w6G}X)?Y2(;~3i)+08kNjtE@#d(t%5q&>Hao|eXv9kJ4X~g zAY&h^)Ff!*@@b-LG#Q_G6g z3}m_h)F2Zho#hZtp$ew>D##d|wp0l=eDJJO)5TJnHmFR~)^-4f8*!5&d7Ju&cS${_0x^bebhB|m;}C**_*3ilCu~W2*GKy~gZrqz zsZ9SJR=piz-+WIES>WCOBAf>{{v(cZE*~m9?usEEso7 zU|en#da<+t88`n@I)TLl!gv})K9Qn3Hun9p5l9^${~mO2L%)=yB)IFYbP;7$*zHkm zq7Nu2DBxJS#5q(5fvzsDu5`4tkjfL<-HGV75Gn2*pAHJv4D9ZF)4{#8#>NCk3>;Y> z5yl2b_UhHqv9Yo?^_y^g{v$j?%Q__=v)tdGJo_%;+Y`{C6?~r6_8WrO2)$jNp=JWj zM6K_)L$}~SxE>y!ex|=3#*frGeM7_Q)l61#lCic3DjWBKv2c9mAk7woO{@I-)HGGK z>9+3>eLlD1bw!Cp>~1qL`deK+J~PF5h|K1OEi$F zPfu7{dYnCbJ~$Z333zM^ILXGxKxm=P#6PRMy#&t(05pViG4#R(PVDy3lR_rbt#JgY z(tv4Ln3&)TgN+jU@2B2dB_t#i6uhxCAjE*Vt+QX8y0VBFKyBc#O+!FE7mHis$jK4r z=Qs?ks$Tn1Phd|7DoUh`=i>1LmjwTFvL!=qVIJCaO`Wx^5fpJnD6(`WW_rNF0 zkq%!}nTSsRtcM4bwO95!k96!RGM)ZhU0I1;I(}~w_FYY7<#Q!<$6ot${;mc1_0N^2 z%iVw{L&a7@-oeMUzU7MY?O^X|x%<&llgZ`LBO!*qiBpSIwf)|Bk59hIcrXiUFR`Aj`|J(sAYOEt*G>K`O*#m&kB1MZiyuG-xBF;a@L zrom*;Snwk5p6U$lxwoE+SINKAHsNh_4Zp>7T2rh@Usu;M=UnR8GX1xq7D~f*)LZn(D|qO$eXInd$OT@|83WPYV#6P?#=B>GbsIcn?G#o_$uOh|9KE*Ku0HC0bvzN#HBQ3G&Mcy`26+U zb?KJpA_#&SFg}sPxqLa{z(PHNL;LZutnP^h6IN#CE<^nYhh%N)gwYb34g>Oa=eEOi zCX0IX%m%yIAJ%MAU8aEgVG72lNjv74@ii{9XSz8nRN5V#u9W($i+9gA;1@{clH(DL zUS-l{V0X}cmwLCF|8tQUeZatYrEf}~dTa7+bhYafnii+W!`7=wW2q%eGX_p5+aY5{ zNml=SlmoBPhV&w%@awa7jIWCf`3(Y7xejsEVL!8|WQQ7S`Eq37kS*<6e7}t)U?EFO zj{_9+fO7>R8N>vlAs%31Z028>uE6Q;RR3a1z=~Pp9T7PH^-IOZkhlF4uqBO*jp3fp z#d{6`G-a9eT`{{$R~PO{*n}3wb}k&xINEE?$|tW{8>;}ZCMqwf`8#h;8fIBuId~si zq$j|0+w~B)m*5aYH8`;MesXdbCJwt@Tr|R!mEm z5@|%!Ead!VP;*TU4bekoSYb^|V(81vT0+ZlNBF59{R>r=e72|oYlarfavGrdXSNe5V3DYmy8w#c$z=b6e1ybc!ba1*ea1kT~ zK(u;xtotd}_Xeh-Rf6o5c;S3;7m+lVk+kyt^}?dmu>hqs`cB8f14T5H^&cIRwfzN; z4(7iw4xa>v2LlIW(zjPvk!tR5^hgfFxrC4&9J8q7>gwwiVML_7JC3MpFo1U)nqM8e zS>7bxvc^`ZkfHW6FSqBaaG!YRkWgo*t8Al?n{|Eq#KFOl-XOzs`Q3G|K_~m?@Ao~f zk;$|QotcbuY;^r->LxFa`X>H7wfK$!&rj%@slhK7Mdla2~UcBiP@}VjS%EwwytuC2#PZyN$*)Mxz%Nck1 zbl<_I(DbA?C*fm$4}4G0_$+jr**Q5WckdGZK}z`rE)K`*>X*`*oqTqw2bGvdd2POn zaDj>nUjQEd{{9G{r>NVE+Ep31M~Rc7ucw}QIdf*8XECkl=_hLkN1kop3Qa`co&YHJ zL8tcJ_XO1lPlBr;{8BKEeMo)PIS_5f{Ant}*h|XQ)+@_zVB?OON_>iZ$h5InN*-ug zgU3(f95V1oW=d!0E1A*ruQusbiaAgZQ7Fz`m)a{o`X37G3A6iIUV>D2LypXk^3o;O z&pbitoaD2-C(|P3$xAk$%D!|YGwp*}jyvdQFx=bQy&~AI-Ms0Es4ZkAXGGV3xw9(_^#0pB_L>=mED_dl5Qs-~bhdcUy6E-yT6x87RY>$!@~uLR!%G!BZmI89i=swe{L#ny9Cl(ysf)$sA%)reiE&D|bB*_s}< zx5W+}ZzmST>6$=wfou5eH(qrE?tpTz;Ol4=#~zeCTI;SF7W))FdSnNssm2HjEM%tI zB9yhacN$sSu^xDMt2sEvF?b+--zk*Gm@5)lYI;lfL4N-1&V?D)JvvCKolRJn;SWhf z>z;eOg2nZfSBn$f!-jrAc1CBP$Aj7oOy}BsmWLiQ6`fSXe( z>Y-87n&!ZpY(=}9DzN}Jt?f)m{75kr2&|5in+jl6JPMq0qQ7DAGe6#0mL3kfjH%_G zFHW1pK{eSL+L8K zs@@&`^w>dLc`xMRzX&NH>kn`w1Sav^Hk>Xa3HCDX7^wn}8nB*@_YyJBX$o7p>6KV7 z1L^Y>zFqNcx?*QdtW-teR?>ynxUFrxWy7X)=hw4W-zqT$XxF^6Fb1JV5pw zN$;*pjG%HcAE(#!7i|UBN4N10u*`G>_``|z(sx&4CWh=*7v*@j-rO;Wu@s*mEE@j^ zTRl{RQ@M;adk5*VqYHb5Xz2Z977ytycHTNsq5?cIK*QB_644p}Ls04WLXUBd?V!HC z$W>MNx-bYtH`NF^MtG%q%c|9(WxuWcwNJ|zfuq+A%7>${Ftn5G^SUrxh`kK+l9S$^jA1cQ@7e{Hr(O0+dw0tlggK!}B_NIHse|zEqqvRvqn-q!$ z0}<_^p)o!+rI%WVL=SeK;>wyD7DmP|C`sT%@4LauyMtrR8j*-f2oBL=^qRxpgQ^-R zczZh`M{DO4(u;4SZM*bmu<&j=q(}KK_YK8BAAJSs z`>JW#WYEAawv*@5B&5p5r?w8<&VJ67(qyZ7-~h}>B2glOg6EHMUsD*MZ2k$X>492$ zE?@hQzOpIM?jDr8EMaW^kI`fO1qk%oOjwzrn2uj|IV8lKPw&W)Chzi>@0WOaTWsGf zf_6@!TV*WWBbtUTt39}UoRRzqj2`qv=z;k5=+IQjAu@CvRI;lU6h^!X9^)99)7|I)=xE4Fmvkz#6GG!fff0D{j$&F$l;m|1IlN* z89E1U7^i8etIvIk&_W0pE)qeHB@G|Y3&!M?fX1vVKj;IxMCVELLgJMd#3g*%j0L0ry1_zP@z2^IhYgHX1z$m-hK zFwmHGy(np6h#uGx`zrZhA4DJWuqfnD5H2DuE$T`2{rf*T$(oqNZ0I$Guv<8UpmvXl ztTb^Os4xH68t%YGu`P3bCVW${e;}xNl@$eYYLHyW;q@84=}-ibxqN%Nb2erR5zyKi z=rL4w67lVik7k@p6#jniMse@-A>09yAIhiD+}f(KbN%Z?yRX^w1%sUxd08@ZFYWaO z0L8@se6j7(F`Z6tnJa$=YzVgE!Tx@#`SYcg9wnj1X;83@AHRPXC@hZhN(=o$kF8l3 zzv{WRgkrNV3uMH^AxQ7X^Maw0zJDO)otnTk)RAwBiD9ZT7@9`iFTLgfq}NC@n70ACfy5@0@c+zm`Wi#l$FXONAeXVRF+B1JGie2U!$`(3 zwCb2Gz`&nuc7~d;GD4_DvAl_vpL!Rw(3UKnvSpK5hG9_1jGR?RN?MP`r2!eNt(+V; zOshKjoJZI=2BNw!FbEdX zzO>**LL-RKR2&N5u*zRnRY52Ph1P&M#QKVgJ~;oe`M^|#F>;xO4_}1tUZ?5fb>Aoj}1g44!M1R8tm-tvynWTZ~{#71UMWh@S%vg$d-vb_#Ma0 zkSAL@WWJ(i!!(roghH&15NtZm@G;R?bwcZdk$J!{5#mZT;WbZQh93HT#?$%u@Nlc?l$3C(vUXG=v56E8K4azO4-i;^-?FjQg%w0jO0qI`tA8RbPWLIcOg#`iE|QQ(cl z;Gnl4B!o0#Oy{80!4cW+J=KO!D{G^OeF)GKa+Vc=Dt2=Ijr(niWh<|!5Q3+C-8yq5 z4I(VEIor;_)YR0&V|Jh^3!H$h_%8HB;2SV7X3dpuILx!7{#xT9t0^Xer|&UvMj|XW zy9*_GL|h!wWwx$4prOGuZ#=}*L+_uJo|4jotH^<49E|X+;ji(}!H@TKb*<#%d#o+o zU7N4~fAjLkW&&} zvIgML-MeG0)~#EIccjwd`!OneIk;_K&E4m&<=Y=xRxhtKJ@$(8*1`p^tshZ&0Wp(o zuVE5J{LtCX^Q(J3pJJV%8ChnMOjA=;TZ>dC=aVOUfo=|n_3%mdDoVOBvXd**Qn}Xe z>bw9YfZxj%9DYSkm}tbx8iv$XT|GTwRtaDPAS^8fXR~s0a;Pf(QUi)u@To&AA*&;9 zx#!8TqngY?F@w_I+sG*Hu!vEH`EzV~LGKSL4k+f!txNf>FeRDNEg`j@i``YKmWiMF zKjWueUpt>@vg4d}%#k8-u8|0k%q7b$l9Lf2nVtmr5$?zON{M@06Qid$Q}lRu_H5y) zHG_#pPx|Ev8hS*MbKypk(G$7I<}>V;;BiMzH~ez$os^b5f)cJ2e zm|LeX!nv)gWywM zz5K|Kn34%a8YZCn9x*VOi!T1U2l>p-N>24kQ1SJpzPi3EqHIZcGdMc46NW(6R8$ zAw|2DS2c$$^^E|?B+)`106yc>)!7L_SHjJkEg#n~kg=BoQ5$BWD+d6NF+?5K%z)V8 zX5YF7L2k(6I92!Hi1$0Q?YquN7Let*9AD~q!0mu|Vq)moKs2OO5NyG7S7$u|ogtd^ zd9zud(E5+IA$-t>hm%tV+XfH;@ERC-0kKS4@wXfIKfyH**BUn99Xs+7dLhn~-~H#Z zdG;*EE#0_*nK4I1jv!47kzey(n0EnlHpFR;jw1jbsW|a~ddvnmz{D|sF(FM;Sry`Y z)URDmXDuu&FxPADc)n3P#8q3*j#}hj1VBbfTRpJ+qfM2oej+wlWGp8iL`()a-sWuO z79aTGnnHb@oFsc1M<<%?pG~_m%W>9ZtW;E{oH9BJ>jYZr#jNrj>395y=tK-RX=#}Q zU`en z(AOb;7d!K^K(maa;~v-y+JG^}uK5Q=PDe1~$jI{^trW7%B4nAr>Aw$)B=4L?FTv2D z=7!-1AmWLFAMf0N>ARPt4-{t)CQhEw-&laIkGE zv<%~He{4oyzCGJ({!HeC|6xNzc~B61wnvSPF}e+8{B?rD!Y{LRsHzNP^mrV5ydeaDXEjkct7!n#CX$7sVRmr9s3R?%!+$PjZ5x)i zR8Y>mH5wZkF@1n^A*OdWokdyY*><7MqD9%$*&k9{T_bzH^zaxI8E5Ug?Ce})DpR3r z8fj=3cfZMAd_Ff?-lYQ zzg>N({MvII5}uoz#e=ei%r5@JhQQ0ba+7#N0@*NM>EQidAylA{o0BnlqoRTMiuS4Y zTCPIq>r|nIN=U$2G^VewPiqdF!0%=4j%%~Cv*6({zyw`L^1(bvAClgvGGJCDvM=Sa ze8JsA#sKOeE-hl{MsRQi!~ESkTO_SYsxiC+?l!1p_ z^F&dCu#A9jCg3(y-2JBoK{2#L9}96fKVxL4oNgSC1=fcH)(0*T1Q>x5plpk^`g_?L zo?3?&9fn5?HsHSU0x$)NLtB3*ag z>CR08`8L&OOQBZn+|*&+E}P?YcXLQ$%%cH@@v6Fvr`%g=UdaY@UMfx2$+R(&`L#${ z=U0^2menyCpiAHD33^>V&6irkI!c1{i4;(W{3%B;gxz|eQ~3Fdp;$$*8Ga$QSw;%a zFBN~Kbo2A`Aj#XmADLdu=FKqBQNpOU_(H;veOqt%aB@%{d}XLQVS#CSHNl)VzKeiFmf zFcB-kr7yo9MPAO6Cj;%p?UQOfHYk4~Ula=Lb;*aH=oC;Anyrq%Uznt!8bfK*4T+a% zN3bC^DZ+SZv+X9rNf0WI;wct}c;1C)TazpaOe%3?`4;ddFUCPR;C(HrQ z5zz`VkpD^KGXJTxIsxrbxi!3E5K2MsU72>a z>uqD^zRM2It`am`WMuab)bn0mPyQ~_(7YiH^5_K7-|Y*%lTd&_C74PmO%%3K0H6qu zM1p{c7$MrB>Z|P8^Bl_nOh1l1jN)oP+r!(rrm^C|Sb#h!zsI+AZtwH>ASXR}7lE3b z0~H5&-Lx-zwg@qh??m$s^5yXzmTY8?gi;uZ9~0d{>aYc|%8!u7GF}W$xbRPUQ|a^F zY)pRLt=Bc1(dKPReZok#(B{2jAC0-ZAc9aekn8Ki$A5CXX4(xB;rZ7AUN?TQluj{?R0ICC^O`ebg2hr|{E16;shgg*oVU{oHPWIV?k7wTPiwHUw4Chs*uJ=F6^UO! zxa2@}PQa&v)dE)iUX4>)$je1gE{8W=k#U;%rcDSilC`Q-$Ks1JAJR zhg-?r-5nr?bGcwMtObN{tXi?<+p4`^0PMI^CTsKmx2 zm4j=S48`<)iesJ`N+9Ip2q9uqhSUQyO!oUy~`<*@%TtwpWI1@WZ$A<2fU6bGJZ&Rjb1p);G1)*xjKV>&nzBs!=t(SG6Dwp^FY#+D!;yBKkZ-_?z=fF0vCt*q0j_MzT`H%Ax{G>9O_5Vp5X zP4~5h303?GWf(u9XM%-Rsv$Q+Jn3UWbB&nhq%I}tv*Rram*@|%WPVBU!o0)XY*=71 zf&*PjHsYJnOJgqqRRdqH<KKlr{?o^$PTXf0acV zFR#quU-DvKN4R5O=Ke{E5F>uE$kxRlE~Ze==tW<2^H!T}*G+aa@AUNN|6u*Bn6=I5 zBNIo~m`D0B&v5Oaa@bOiaP-7W9AAD=rAM0U!Ot$B#f_0IwgsZws7S_`&VlrEqMfHK108 zoNnpir+5i}XMVP0MO0+K+1Fic&$(B!a|j5Rv$03U3ku`z zynC0GpMT@qRvc`SlA~CKf#JAopzs&Ic}DHuQ*6EMW?^9=;$(VFh}be5`BF!|*q!MA zfm@D$B$5eXn&Q}lH%vjl0FBe0lHsJvtCpCGB2^o#{3|GRM*vXP3LVL+FO* zao~n@AL4bFnQWKMN&aZIzZ=mbd-i-06c*#HEDNSBx7Rw&7cpSQaqsnJLRJ_;Poi5< zRFx}}_I+WsN10F>?q{Tpu|M9Q^6sp=`|E~#E0pm7BD_BpOup)5z{~VQy@!tR4|?_T zl`AWUHd^5WcR1o8JYDqJ@nK`3rFBv*=NLp&kQ`1-B=e889eT5>y_0-ZmC(_G+y)(U zG3};T3xro&1d*iBXCUF|)Tg>iQGinX@R|eXb4JLonKpX_vMbWm&ona#Qsu8J@j(5f7U+2vArKLg1Ld{BWF_z?pbosO5?!edMNXk&zWI z>gNhRexgAa&uEytOHTfu{A$~$mU`=_l7dh#VffAT;|nem=XMvVlqFY*%pK>PV}<;k zQ^PR-a#eDFI;Yq7Tjj+0`I?}5ul9t8f^*ez&FqGU8EM|mmbBnl|6TtUe471nRqr%i z={C)pOT!*7I*&pQLf~zMsEpmhS~4F+jE!J$;U&b5b_B4}EM5#To(#1z=h1hdFU1p~ zzZpmcC=y*~wBym~kRAFHS2YSO8fLmk)#9zQy6;?;1Rr2@JUgR};y z$zx(TXRjr{KhDpGGJBJVhzHcQjAX1kh*k1k`q-_u%d&1pr;c&Mm>x}}m)?**1+bDv zZ}$#gfh_T03u7njdvAA^H)=VidWNb}96Z_DKgY`ywJ3~>wtoJWbAW+d-l0t#l7OJp z)GksNbJ5cE9c_BVMxzj5fS{>yD&~v4<9`TivfE(uMC0+WJh^pW%8vSfcQVW;!-J`) zXe<_uIobh42t~&6VCs7IG#}p78#mU>3@@RlpE8?&%|Eh|b)NvWq(mB_ghSo38X#YJ~y#K{=Fo9wS&r)zKBIu zIV0XC8%0I2>3bV*CKCc!*rv5a#6gmZ7x(OSt)g#MXsY@*hLlrPRXa%Glkj4Orpl83 zlsnIKF_{KSAVJUO&mIBe$#rsab65BAVX1S0-$GjNuAQ*K|C2BsFh=|=^toETvnvYo zhfT3>CxZo@osPP!}qY>W^&8R)kIUzNO+n?f%JYFra(U z0JF`2p(t=EwO2U9S_sXTfWV!5_bz1BKz0M30QA{YeWason4QPWir}I_ODn4s<=fM9 z?F*U=_a6|#CKxs|=d;fl?IhnprWGco0W-xxDJptt-mVJv8 z(`xQ53gfZSQCb?(Rn%SEgujlDv5qgf^c*BPgoKk|y;dmy111Tw>jY9P5wQpgOk}R5 zH8j-KJu)f&hH&Rk4+-|;&!EkCzQli2{oD3;KJ>-+Lr9 z!=PFB4^fzE@>`S#hzDsbLN@cM)gl+xbm@MtrdGGx-}|UAGxId1aF+ad@8yKs^Y2#E zM-ASt8(ZAcbuVt-#21MYKd8ynCR;*!Lpbi{e_$sLdd4DA&Gs$7{<>S|S0eo5;Qhuk zH-5r3$=~4`)!B@_Nm%@zbAvf1XS-G+5d8i7_!~E7(Z5L@7^!pk!8NYMs5Us~r+2vj z@DaFvsy<#M)^g?YBV?Qg2L}_UtDTO{a;m02HoSxPEgp=1kG`53ABXgB79h$D&0S$) zoCkU#24?2C??aNu_^pC|b$vbH%63Q+G1M3{?(8`5`N<#=!~dN*?fVOJny2JeQusSC zvln~RVUgL>aLi)lMIhq}&<2=3m2SGIFn^PCx%OoC??4Oq!^eky@{_e;ymHrN->uuQ z;Vu*w>FJILF~K!JQRHN1cDwDI7i9twa$p1y`=0O((tu34Gk;SQGPoq9Rk^M|Zi8G+ zq`XW{On?GdBDJ^_bE632_kJniN!$=YNPenyDU0QRW&q_u22FHyG$xzMN!_spYot+$ z^sM~+9W|vHsS%jIJq5%7GimcrAt9R3de`f=NW#0ZKlz$CiH#L_yTk=d*>G?eCcw5f z5Qg8yRT{12Xw>*&_0_^`#OvF8m@JSOSg!mPY{Yp($4;)bNnofUnQXVlP z6DpDLt}OhY_|KXlXO@k~ zP(QI>_s9{*2~M+w?oGNa9I~-;WONjI0BBcxY7%y8F(8K)C2`)_vAcG$;Po})xX^I8+E#?| zrxcSj$AWi$B?}6kK$aU3wSor;3)*3kt^vjN@Jx{4_+F1&*r4G%crGggsGUqUL!tnl zq;Bd{jKR8Zh6y|f0@i_X3gyyw0yZ&XkMv{jbEDR@#LsjJp5H zkqLUQ3{yeXf+=S*GQ>0)KsnW(livmSiNp7H?aZF@*{Af6vZ=t%K^+p-JU zhBD)T;1nT^9#Jb>ZoUGB>kHjUOmwd(p?rs_&I<=Iz-i4GiPA~IJj2Jx7(l-Wk!c$i7*BrV21R3UA1Et#(#nv@UPjFm6?h6tM5{P z5=Ed`Y}Ex?h{ObhC61DJEl)+&<>~IO0TclOJd6l1NH;BoUitITEz&d9b9I*&k?1tw z_we#6Fcc#+p%60VLzCyWk9MuAap)y5WW&#%KZhA8Uv8;iDXrB1sqOUtDe3mFM%OP+ zZltxk>~8cD7TQBB2z6%z^SmuQa-6lw;bd=>bs1cSv*e&v zq>|;}*$iCI-MO=~G1S^EbKR~`d^1V&8t){`Ik(#BxZ3Y7A~7icB%(+pia+fV{FyY9 z49QOg72p;|vU`?G#E@Bq0PMBIR`qXmC)Z;~8vOAEPIeAX9uU$nojO?K8S)~xYj}NM zst4{biNH^Sa?Dydp?5}TP%C#>I!t>WAb8-G!2og?oQ7EFNv4j_;fW!;Z-`~rWe_R^ zzRkrHg!x5wjp?OrohW+kQK+>5pTYQXI9(0J(%|F}lEM(9TXoh5k^8&a>_D$1qJbJt zVvIN$sL=Qrh;95UR3-?0g)&}@9OyiT!V$yEqxN?V4?{|2P31)XL`+lU-)gxXW*=!zdW zer#oVXTj>h-3d9kahfkWec9u;>{@f*KxG6k1$Nte_j)lz{i98smcIUtQd41Z@nX-Z z$C@d`6s+$+W8`!5+s9#b`;IfJ1*>5CHMpkT4M7;hC8J|6NEj*HW>ctNzr=t2+WgLV zo=tE4H}75=70f`igPdqil#F2HH;)@J=NrALZ52YsfBGUr5+R@2`(u7Hq(H8s)!jcq z4RN~e45P{)MN3h=tPQ4Rqaeh&Fg}Lq(61n)+!%6Wn_V-ZP0=~5t6L97a%O+?mCJFk z;vn~80jQbR5>AD7w@^15{;v>*4eiQ#HloKs+I?;&z>m;||L_NX1eT3z3`H->xHJgF zvo9;(UK@CsNA_C$6=Fuq-`E-1?cehkEbxx9l&6bgesd#m@Gnnm?*FSq={KVyqw-5a zbMV-3qxLl|8ygJfm~Fu1D<7zIS>#|@r@CJLh|NoS<37|X`x#?^ z?EfL!$;%_oSA>GSFk@PC^-^ptLcqW`uU*>_YZZ@4DcT}Y zAds`gm(bDOO-VuXDkmah{Y&J=vI&^`kW?opA)zf6jStSR;1TIC2CFo*co-S-<|KkM zh1pd8#YR_H^-p4@wq<0q?_~k}iToDSp@`)&4!djoX6I=Kw{Sda=F(2O<<=XwIT5Eien- z5j_ueJq?Mo71vjVV$R#!d*lYo@Ls8?DR{&Q? zeDzQGLlKE_$Zx|u;m}YqQPHIBx2r&Ynk2o!b^vAan_93~f6+}tqVekHjT?x^Jt7iS zT)cqhe9#<|`b;ek{Y~D|8+bA8j3z4Gty_;^3ZW_(*U$`>@I2V)^WnyCD*=o%( zGw~!IaK@DTr$r<`++anps8{zVe^=z34-8~e#$E<63U~?HJbpetA7sP^l(KPgp%byR z6#ZLL0z0C0{}EH5%+S+~j9>r*ph_^jxydS_>#{$Q8-UXsUI%Ox(BELT%ayb(MGh5~50hQ?_A8cAh^_cjK z!w_D-7)j_Y0Iz{>h>>%%N3HAZ>}6I#a`kj%#*qPES|&Jfe^L;MzR*k z-+OzHZOXT`DM&W^>Db#SCf40*NVNOxEdzmJMwPILzo)u|;ROPG|0B@|M+Sto$exBi zg)Q?R>>>@}X$4E)hrCm##^t}Qq>PlOoPRUSv+SG}(|^(nl_f+ZRq$w0T{ri16M;qd z0MrI=IVpVuKB~LOo`V25T-^u=D@qnjO(QfD5||Yaajvo|rt9M1H-`Sp(69ixvi{e~ zghSXl5l8GuhjJM4=m^)4k~ORPtF~cj!=ZoZ7@p@5dWS#h6_SPYWsW1N6!ZlkY#Y3+ zCr>uQtO43$=wJgz`~C<>?CnE|apT-M8s(R`kr+akYgQhFhIDpjhB49tlY#!EUAS1| zKqB3$KzWkm=jUe?e|E#Vb;|b-qt9&c)udT6tIUND3GDyT~kvYsv*?42#Jo1 z^F~N?(JS<5@(K!w*VvmRi|M*bOn>WRA#->I`?fQCliomkPq#xum?Y{LSHf6^jXDZkKf2RIP>Ip$BsdpK= zMjS7%QwV*jP9$|b>1ru?5lLmSCA=#I__vbR|1G`fe<)M%)P80(RaD{Fbz{GXkAbDf zUwtc=`AlouauP!sdFl6rCbu&58YlyyaV3JD?5_<4kw}Z#)pqYX{67hO`tQ~js=dC# zAx>6o>=)aleyjNgKhlwuFNiK&e3`Zo);dRY7>RRNViF|+-il5KEG-FISWSBEX*|SY z`ntT`9G9RN{9jVz{txf&g{!D+aPOF$V|LB(h9tJ~(v&y`E_jek>7|4xM}i@7E*T_} zt^Rl@e+$m~@7}}z@l#tU=9Sx~yq3;%?McpAhhwx}8lRWBifX&BccNWN3SX~H^5gNR zA$?-tAg$epmqV6j3F+l>VUkj)(jwCTr@looho0hGlijj{AC+4B18f= diff --git a/versioned_docs/version-4.2/apis/core/dml/_exceptions/Dml_exceptions.png b/versioned_docs/version-4.2/apis/core/dml/_exceptions/Dml_exceptions.png deleted file mode 100644 index 304093c41424fbc31f099c80917d974be65ba206..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3522 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 diff --git a/versioned_docs/version-4.2/apis/core/dml/database-schema.md b/versioned_docs/version-4.2/apis/core/dml/database-schema.md deleted file mode 100644 index 834c03f675..0000000000 --- a/versioned_docs/version-4.2/apis/core/dml/database-schema.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Database schema -tags: - - Database - - DB - - XMLDB ---- - - - -The files available here are in [DBDesigner4](http://fabforce.net/dbdesigner4/) format. DBDesigner4 is a schema drawing program released under GPL. - -The database schemas have been put together by Alberto Giampani, Dario Toledo, Isaac Cueto and Marcus Green. We are also discussing a means of creating them automatically from the new XMLDB definitions with an XML transform. - -Discussion of the database schemas happens either in the forum of the relevant module, or in the [General developer forum](https://moodle.org/mod/forum/view.php?id=55). - -## Moodle 4.0 - -- [Web view of the Moodle 4.00 schema](http://www.examulator.com/er/4.0) - -## Moodle 3.11 - -- [Web view of the Moodle 3.11 schema](http://www.examulator.com/er/3.11) - -## Moodle 3.10 - -- [Web view of the Moodle 3.10 schema](http://www.examulator.com/er/3.10) - -## Moodle 3.9 - -- [Web view of the Moodle 3.9 schema](http://www.examulator.com/er/3.9) - -## Moodle 3.7 - -- [Web view of the Moodle 3.7 schema](https://www.examulator.com/er/3.7) - -## Moodle 3.6 - -- [Web view of the Moodle 3.6 schema](https://www.examulator.com/er/3.6) - -## Moodle 3.5 - -- [ER Diagram Moodle 3.5 schema](https://www.examulator.com/er/3.5) -- [Downloadable Moodle 3.5 schema](https://www.examulator.com/er/3.5/moodle_35_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 3.4 - -- [ER Diagram Moodle 3.4 schema](https://www.examulator.com/er/3.4) -- [Downloadable Moodle 3.4 schema](https://www.examulator.com/er/3.4/moodle_34_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 3.3 - -- [ER Diagram Moodle 3.3 schema](https://www.examulator.com/er/3.3) -- [Downloadable Moodle 3.3 schema](https://www.examulator.com/er/3.3/moodle_33_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 3.2 - -- [ER Diagram Moodle 3.2 schema](https://www.examulator.com/er/3.2) -- [Downloadable Moodle 3.2 schema](https://www.examulator.com/er/3.2/moodle_32_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 3.1 - -- [ER Diagram Moodle 3.1 schema](https://www.examulator.com/er/3.1) -- [Downloadable Moodle 3.1 schema](https://www.examulator.com/er/3.1/moodle_31_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 3.0 - -- [ER Diagram Moodle 3.0 schema](https://www.examulator.com/er/3.0) -- [Downloadable Moodle 3.0 schema](https://www.examulator.com/er/3.0/moodle30_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 2.9 - -- [ER Diagram Moodle 2.9 schema](https://www.examulator.com/er/2.9) -- [Downloadable Moodle 2.9 schema](https://www.examulator.com/er/2.9/moodle29_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 2.8 - -- [ER Diagram Moodle 2.8 schema](https://www.examulator.com/er/2.8) -- [Downloadable Moodle 2.8 schema](https://www.examulator.com/er/2.8/moodle28_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 2.7 - -- [ER Diagram Moodle 2.7 schema](https://www.examulator.com/er/2.7) -- [Downloadable Moodle 2.7 schema](https://www.examulator.com/er/2.7/moodle2.7_erd.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) - -## Moodle 2.2 - -- [ER Diagram Moodle 2.2 schema](https://www.examulator.com/er/2.2) -- [Downloadable Moodle 2.2 schema](https://www.examulator.com/er/2.2/moodle22.mwb) opened by [MYSQL Workbench](http://www.mysql.com/products/workbench) diff --git a/versioned_docs/version-4.2/apis/core/dml/ddl.md b/versioned_docs/version-4.2/apis/core/dml/ddl.md deleted file mode 100644 index 6e1b866b6f..0000000000 --- a/versioned_docs/version-4.2/apis/core/dml/ddl.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Data definition API -tags: - - DB - - XMLDB - - API - - core_dml - - ddl - - core ---- - - - -In this page you'll access to the available functions under Moodle to be able to handle DB structures (tables, fields, indexes...). - -The objective is to have a well-defined group of functions able to handle all the DB structure (DDL statements) using one neutral description, being able to execute the correct SQL statements required by each RDBMS. All these functions are used **[exclusively by the installation and upgrade processes](https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables)**. - -In this page you'll see a complete list of such functions, with some explanations, tricks and examples of their use. If you are interested, it's also highly recommendable to take a look to the [DML functions page](./ddl.md) where everything about how to handle DB data (select, insert, update, delete i.e. DML statements) is defined. - -Of course, feel free to clarify, complete and add more info to all this documentation. It will be welcome, absolutely! - -## Main info - -- All the function calls in this page are public methods of the **database manager**, accessible from the $DB global object. You will need to "import" it within the upgrade function of your **upgrade.php** main function using the `global` keyword, for example: - -```php -function xmldb_xxxx_upgrade { - global $DB; - - // Load the DDL manager and xmldb API. - $dbman = $DB->get_manager(); - - // Your upgrade code goes here -} -``` - -- All of the `$table`, `$field`, and `$index` parameters are XMLDB objects. Don't forget to read carefully the complete documentation about [creating new DDL functions](https://docs.moodle.org/dev/XMLDB_creating_new_DDL_functions) before playing with these functions. Everything is explained there, with one general example and some really useful tricks to improve the use of all the functions detailed below. -- If you want real examples of the usage of these functions we recommend examining the various core **upgrade.php** scripts. - -:::tip - -Always use the [XMLDB Editor](/general/development/tools/xmldb) to modify your tables. It is capable of generating the PHP code required to make your definition changes. - -::: - -:::danger - -The use of these functions is **restricted** to the upgrade processes and it should not be used in any other parts of Moodle. - -::: - -## The functions - -### Handling tables - -```php -// Detect if a table exists. -$dbman->table_exists($table) - -// Create a table. -$dbman->create_table($table, $continue = true, $feedback = true) - -// Drop a table. -$dbman->drop_table($table, $continue = true, $feedback = true) - -// Rename a table. -$dbman->rename_table($table, $newname, $continue = true, $feedback = true) -``` - -### Handling fields - -```php -// Detect if a field exists. -$dbman->field_exists($table, $field) - -// Create a field. -$dbman->add_field($table, $field, $continue = true, $feedback = true) - -// Drop a field. -$dbman->drop_field($table, $field, $continue = true, $feedback = true) - -// Change the type of a field. -$dbman->change_field_type($table, $field, $continue = true, $feedback = true) - -// Change the precision of a field. -$dbman->change_field_precision($table, $field, $continue = true, $feedback = true) - -// Change the signed/unsigned status of a field. -$dbman->change_field_unsigned($table, $field, $continue = true, $feedback = true) - -// Make a field nullable or not. -$dbman->change_field_notnull($table, $field, $continue = true, $feedback = true) - -// Change the default value of a field. -$dbman->change_field_default($table, $field, $continue = true, $feedback = true) - -// Rename a field. -$dbman->rename_field($table, $field, $newname, $continue = true, $feedback = true) -``` - -### Handling indexes - -```php -// Detect if an index exists. -$dbman->index_exists($table, $index) - -// Return the name of an index in DB. -$dbman->find_index_name($table, $index) - -// Add an index. -$dbman->add_index($table, $index, $continue = true, $feedback = true) - -// Drop an index. -$dbman->drop_index($table, $index, $continue = true, $feedback = true) -``` - -## Some considerations - -1. The `$table`, `$field`, and `$index` parameters are, always, XMLDB objects. -1. The `$newtablename`, and `$newfieldname` parameters are, always, simple strings. -1. All the `*_exists()` functions always return a boolean value. -1. If any issue is encountered during execution of these functions, an Exception will be thrown and the upgrade process will stop. -1. Always use the [XMLDB Editor](/general/development/tools/xmldb) to generate the PHP code automatically. - -## See also - -- [Core APIs](../../../apis.md) -- [XMLDB Documentation](https://docs.moodle.org/dev/XMLDB_Documentation): Main page of the whole XMLDB documentation, where all the process is defined and all the related information resides. -- [XMLDB Defining one XML structure](https://docs.moodle.org/dev/XMLDB_Defining_one_XML_structure): Where you will know a bit more about the underlying XML structure used to define the DB objects, that is used continuously by the functions described in this page. -- [Installing and upgrading plugin DB tables](https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables) -- [DML functions](./index.md): Where all the functions used to handle DB data ([DML](https://docs.moodle.org/wikipedia/Data_Manipulation_Language)) are defined. diff --git a/versioned_docs/version-4.2/apis/core/dml/delegated-transactions.md b/versioned_docs/version-4.2/apis/core/dml/delegated-transactions.md deleted file mode 100644 index 2dc3d7a03c..0000000000 --- a/versioned_docs/version-4.2/apis/core/dml/delegated-transactions.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Transactions -tags: - - core_dml - - DML - - core - - API ---- - -Moodle allows data manipulation to take place within a database transaction, known as a *Delegated transaction*. This allows you to perform CRUD[^1] operations, and roll them back if a failure takes place. - -## General principles - -1. These **delegated transactions** work in a way that, when nested, the outer levels have control over the inner ones. -2. Code should **not** rely on a rollback happening. It is only a measure to reduce (not to eliminate) DB[^2] garbled information -3. Any code using transactions that result in unfinished, unbalanced, or finished twice transactions will generate a `transaction_exception` and the DB will perform a rollback -4. If one transaction (at any level) has been marked for `rollback()` there will not be any method to change it. Finally Moodle will perform the DB rollback -5. If one transaction (at any level) has been marked for `allow_commit()` it will be possible to change that status to `rollback()` in any outer level -6. It will be **optional** to catch exceptions when using transactions, but if they are caught, then it is mandatory to mark the transaction for `rollback()` -7. Any explicit `rollback()` call will pass the exception originating from it, as in `rollback($exception)`, to be re-thrown - -## The API - -1. All the handling must go, exclusively, to a `moodle_database` object, leaving real drivers only implementing (protected) the old begin/commit/rollback_sql() functions -2. One array of objects of type `moodle_transaction` will be stored / checked from `$DB` -3. `$DB` will be the responsible to instantiate / accumulate / pair / compare `moodle_transaction`s -4. Each `moodle_transaction` will be able to set the global mark for rollback. Commit won't change anything -5. Inner-most commit/rollback will printout one complete stack of `moodle_transaction`s information if we are under `DEBUG_DEVELOPER` and the new setting `delegatedtransactionsdebug` is enabled -6. Normal usage of the moodle_transaction will be: - - ```php - $transaction = $DB->start_delegated_transaction(); - // Perform some $DB stuff - $transaction->allow_commit(); - ``` - -7. If, for any reason, the developer needs to catch exceptions when using transactions, it will be mandatory to use it in this way: - - ```php - try { - $transaction = $DB->start_delegated_transaction(); - // Perform some $DB stuff. - $transaction->allow_commit(); - } catch (Exception $e) { - // Extra cleanup steps. - // Re-throw exception after commiting. - $transaction->rollback($e); - } - ``` - -8. In order to be able to keep some parts of code out from top transactions completely, if we know it can lead to problems, we can use: - - ```php - // Check to confirm we aren't using transactions at this point. - // This will throw an exception if a transaction is found. - $DB->transactions_forbidden(); - ``` - -## The Flow - -![The flow of transactions in diagram format](./_delegated-transactions/TransactionsAndExceptionsFlow.png) - -1. Any default exception handler will: - 1. Catch uncaught transaction_exception exceptions - 2. Properly perform the DB rollback - 3. debug/error/log honouring related settings - 4. inform with as many details as possible (token, place... whatever) -2. Any "footer" (meaning some place before ending `` output) will: - 1. Detect "in-transaction" status - 2. Let execution continue, transaction is automatically rolled back in `$DB->dispose()` - 3. inform with as many details as possible (token, place... whatever) -3. `$DB->dispose()` will: - 1. Detect "in-transaction" status - 2. log error (not possible to honour settings!) - 3. Properly perform the full DB rollback - -[^1]: Create Read Update Delete -[^2]: The Moodle database diff --git a/versioned_docs/version-4.2/apis/core/dml/drivers.md b/versioned_docs/version-4.2/apis/core/dml/drivers.md deleted file mode 100644 index efc34f1f6a..0000000000 --- a/versioned_docs/version-4.2/apis/core/dml/drivers.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: DML drivers -tags: - - core_dml - - DML - - core - - API - - RDBM ---- - -A number of native drivers are included with Moodle, including those with support for: - -- MySQLi -- MariaDB -- PostgreSQL -- Oracle -- Microsoft SQL Server - -These drivers are supported using DML Database Driver layer, which has a number of discreet benefits: - -- more optimised and probably faster -- consume less memory -- better possibility to improve logging, debugging, profiling, etc. -- less code, easier to fix and maintain -- and more - -## Query logging - -The native DML drivers support logging of database queries to database table, which can be enabled in config.php: - -```php title="config.php" -$CFG->dboptions = [ - 'dbpersist' => 0, - //'logall' => true, - 'logslow' => 5, - 'logerrors' => true, -]; -``` - -- `logall` - log all queries - suitable only for developers, causes high server loads -- `logslow` - log queries that take longer than specified number of seconds (float values are accepted) -- `logerrors` - log all error queries - -## See also - -- [DML functions](./index.md): Where all the functions used to handle DB data ([DML](https://en.wikipedia.org/wiki/Data_Manipulation_Language)) are defined. -- [DML exceptions](./exceptions.md): New DML code is throwing exceptions instead of returning false if anything goes wrong diff --git a/versioned_docs/version-4.2/apis/core/dml/exceptions.md b/versioned_docs/version-4.2/apis/core/dml/exceptions.md deleted file mode 100644 index f0b6a9b3c8..0000000000 --- a/versioned_docs/version-4.2/apis/core/dml/exceptions.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: DML exceptions -tags: - - core_dml - - DB - - API - - core - - exception ---- - -The [DML](./index.md) API uses a selection of exceptions to indicate errors. - -## Types of exception - -![DML Exceptions](_exceptions/Dml_exceptions.png) - -### dml_connection_exception - -Thrown when can not connect to database for any reason. - -### dml_read_exception - -Problem occurred during reading from database. Originally indicated be returning *false* - this value was often confused with *false* return value meaning *not found*. - -### dml_write_exception - -Problem occurred during writing to database. Originally indicated be returning *false*. - -## See also - -- [Exceptions](https://docs.moodle.org/dev/Exceptions): General guidelines for using of exceptions in Moodle 2.0 -- [DML functions](./index.md): Where all the functions used to handle DB data. ([DML](https://en.wikipedia.org/wiki/Data_manipulation_language)) are defined. -- [DDL functions](./ddl.md): Where all the functions used to handle DB objects ([DDL](https://en.wikipedia.org/wiki/Data_Definition_Language)) are defined. diff --git a/versioned_docs/version-4.2/apis/core/dml/index.md b/versioned_docs/version-4.2/apis/core/dml/index.md deleted file mode 100644 index c504bb394f..0000000000 --- a/versioned_docs/version-4.2/apis/core/dml/index.md +++ /dev/null @@ -1,1115 +0,0 @@ ---- -title: Data manipulation API -tags: - - DB - - XMLDB - - API - - core - - core_dml ---- - -This page describes the functions available to access data in the Moodle database. You should **exclusively** use these functions in order to retrieve or modify database content because these functions provide a high level of abstraction and guarantee that your database manipulation will work against different RDBMSes. - -Where possible, tricks and examples will be documented here in order to make developers' lives a bit easier. Of course, feel free to clarify, complete and add more information to this documentation. It will be welcome, absolutely! - -## General concepts - -### DB object - -- The data manipulation API is exposed via public methods of the $DB object. -- Moodle core takes care of setting up the connection to the database according to values specified in the main config.php file. -- The $DB global object is an instance of the moodle_database class. It is instantiated automatically during the bootstrap setup, i.e. as a part of including the main config.php file. -- The DB object is available in the global scope right after including the config.php file: - -```php title="example.php" -mdl_. This prefix is NOT to be used in the code itself. -- All the `$table` parameters in the functions are meant to be the table name without prefixes: - -```php -$user = $DB->get_record('user', ['id' => '1']); -``` - -- In custom SQL queries, table names must be enclosed between curly braces. They will be then automatically converted to the real prefixed table name. There is no need to access $CFG->prefix - -```php -$user = $DB->get_record_sql('SELECT COUNT(*) FROM {user} WHERE deleted = 1 OR suspended = 1;'); -``` - -### Conditions - -- All the `$conditions` parameters in the functions are arrays of `fieldname => fieldvalue` elements. -- They all must be fulfilled - that is the logical AND is used to populate the actual WHERE statement - -```php -$user = $DB->get_record('user', ['firstname' => 'Martin', 'lastname' => 'Dougiamas']); -``` - -### Placeholders - -- All the `$params` parameters in the functions are arrays of values used to fill placeholders in SQL statements. -- Placeholders help to avoid problems with SQL-injection and/or invalid quotes in SQL queries. They facilitate secure and cross-db compatible code. -- Two types of placeholders are supported - question marks (SQL_PARAMS_QM) and named placeholders (SQL_PARAMS_NAMED). -- Named params **must be unique** even if the value passed is the same. If you need to pass the same value multiple times, you need to have multiple distinct named parameters. - -```php title="Example of using question-mark placeholders" -$DB->get_record_sql( - 'SELECT * FROM {user} WHERE firstname = ? AND lastname = ?', - [ - 'Martin', - 'Dougiamas', - ] -); -``` - -```php title="Example of using named placeholders" -$DB->get_record_sql( - 'SELECT * FROM {user} WHERE firstname = :firstname AND lastname = :lastname', - [ - 'firstname' => 'Martin', - 'lastname' => 'Dougiamas', - ] -); -``` - -### Strictness - -Some methods accept the $strictness parameter affecting the method behaviour. Supported modes are specified using the constants: - -- MUST_EXIST - In this mode, the requested record must exist and must be unique. An exception will be thrown if no record is found or multiple matching records are found. -- IGNORE_MISSING - In this mode, a missing record is not an error. False boolean is returned if the requested record is not found. If more records are found, a debugging message is displayed. -- IGNORE_MULTIPLE - This is not a recommended mode. The function will silently ignore multiple records found and will return just the first one of them. - -## Getting a single record - -### get_record - -Return a single database record as an object where all the given conditions are met. - -```php -public function get_record( - $table, - array $conditions, - $fields = '*', - $strictness = IGNORE_MISSING -); -``` - -### get_record_select - -Return a single database record as an object where the given conditions are used in the WHERE clause. - -```php -public function get_record_select( - $table, - $select, - array $params = null, - $fields = '*', - $strictness = IGNORE_MISSING -); -``` - -### get_record_sql - -Return a single database record as an object using a custom SELECT query. - -```php -public function get_record_sql( - $sql, - array $params = null, - $strictness = IGNORE_MISSING -); -``` - -## Getting a hashed array of records - -Each of the following methods return an array of objects. The array is indexed by the first column of the fields returned by the query. To assure consistency, it is a good practice to ensure that your query include an "id column" as the first field. When designing custom tables, make id their first column and primary key. - -### get_records - -Return a list of records as an array of objects where all the given conditions are met. - -```php -public function get_records( - $table, - array $conditions = null, - $sort = '', - $fields = '*', - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_records_select - -Return a list of records as an array of objects where the given conditions are used in the WHERE clause. - -```php -public function get_records_select( - $table, - $select, - array $params = null, - $sort = '', - $fields = '*', - $limitfrom = 0, - $limitnum = 0 -); -``` - -The `$fields` parameter is a comma separated list of fields to return (optional, by default all fields are returned). - -### get_records_sql - -Return a list of records as an array of objects using a custom SELECT query. - -```php -public function get_records_sql( - $sql, - array $params = null, - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_records_list - -Return a list of records as an array of objects where the given field matches one of the possible values. - -```php -public function get_records_list( - $table, - $field, - array $values, - $sort = *, - $fields = '*', - $limitfrom = *, - $limitnum = '' -) -``` - -## Getting data as key/value pairs in an associative array - -### get_records_menu - -Return the first two columns from a list of records as an associative array where all the given conditions are met. - -```php -public function get_records_menu( - $table, - array $conditions = null, - $sort = '', - $fields = '*', - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_records_select_menu - -Return the first two columns from a list of records as an associative array where the given conditions are used in the WHERE clause. - -```php -public function get_records_select_menu( - $table, - $select, - array $params = null, - $sort = '', - $fields = '*', - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_records_sql_menu - -Return the first two columns from a number of records as an associative array using a custom SELECT query. - -```php -public function get_records_sql_menu( - $sql, - array $params = null, - $limitfrom = 0, - $limitnum = 0 -); -``` - -## Counting records that match the given criteria - -### count_records - -Count the records in a table where all the given conditions are met. - -```php -public function count_records( - $table, - array $conditions = null -); -``` - -### count_records_select - -Count the records in a table where the given conditions are used in the WHERE clause. - -```php -public function count_records_select( - $table, - $select, - array $params = null, - $countitem = "COUNT('x')" -); -``` - -### count_records_sql - -Counting the records using a custom SELECT COUNT(...) query. - -```php -public function count_records_sql( - $sql, - array $params = null -); -``` - -## Checking if a given record exists - -### record_exists - -Test whether a record exists in a table where all the given conditions are met. - -```php -public function record_exists( - $table, - array $conditions = null -); -``` - -### record_exists_select - -Test whether any records exists in a table where the given conditions are used in the WHERE clause. - -```php -public function record_exists_select( - $table, - $select, - array $params = null -); -``` - -### record_exists_sql - -Test whether the given SELECT query would return any record. - -```php -public function record_exists_sql( - $sql, - array $params = null -); -``` - -## Getting a particular field value from one record - -### get_field - -Get a single field value from a table record where all the given conditions are met. - -```php -public function get_field( - $table, - $return, - array $conditions, - $strictness = IGNORE_MISSING -); -``` - -### get_field_select - -Get a single field value from a table record where the given conditions are used in the WHERE clause. - -```php -public function get_field_select( - $table, - $return, - $select, - array $params = null, - $strictness = IGNORE_MISSING -); -``` - -### get_field_sql - -Get a single field value (first field) using a custom SELECT query. - -```php -public function get_field_sql( - $sql, - array $params = null, - $strictness = IGNORE_MISSING -); -``` - -## Getting field values from multiple records - -### get_fieldset_select - -Return values of the given field as an array where the given conditions are used in the WHERE clause. - -```php -public function get_fieldset_select( - $table, - $return, - $select, - array $params = null -); -``` - -### get_fieldset_sql - -Return values of the first column as an array using a custom SELECT field FROM ... query. - -```php -public function get_fieldset_sql( - $sql, - array $params = null -); -``` - -## Setting a field value - -### set_field - -Set a single field in every record where all the given conditions are met. - -```php -public function set_field( - $table, - $newfield, - $newvalue, - array $conditions = null -); -``` - -### set_field_select - -Set a single field in every table record where the given conditions are used in the WHERE clause. - -```php -public function set_field_select( - $table, - $newfield, - $newvalue, - $select, - array $params = null -); -``` - -## Deleting records - -### delete_records - -Delete records from the table where all the given conditions are met. - -```php -public function delete_records( - $table, - array $conditions = null -); -``` - -### delete_records_select - -Delete records from the table where the given conditions are used in the WHERE clause. - -```php -public function delete_records_select( - $table, - $select, - array $params = null -); -``` - -## Inserting records - -### insert_record - -Insert the given data object into the table and return the "id" of the newly created record. - -```php -public function insert_record( - $table, - $dataobject, - $returnid = true, - $bulk = false -); -``` - -### insert_records - -Insert multiple records into the table as fast as possible. Records are inserted in the given order, but the operation is not atomic. Use transactions if necessary. - -```php -public function insert_records( - $table, - $dataobjects -); -``` - -### insert_record_raw - -For rare cases when you also need to specify the ID of the record to be inserted. - -## Updating records - -### update_record - -Update a record in the table. The data object must have the property "id" set. - -```php -public function update_record( - $table, - $dataobject, - $bulk = false -); -``` - -## Executing a custom query - -### execute - -- If you need to perform a complex update using arbitrary SQL, you can use the low level "execute" method. Only use this when no specialised method exists. - -```php -public function execute( - $sql, - array $params = null -); -``` - -:::danger - -Do NOT use this to make changes in database structure, use the `database_manager` methods instead. - -::: - -## Using recordsets - -If the number of records to be retrieved from DB is high, the 'get_records_xxx() functions above are far from optimal, because they load all the records into the memory via the returned array. Under those circumstances, it is highly recommended to use these `get_recordset_xxx()` functions instead. They return an iterator to iterate over all the found records and save a lot of memory. - -It is **absolutely important** to not forget to close the returned recordset iterator after using it. This is to free up a lot of resources in the RDBMS. - -A general way to iterate over records using the `get_recordset_xxx()` functions: - -```php -$rs = $DB->get_recordset(....); -foreach ($rs as $record) { - // Do whatever you want with this record -} -$rs->close(); -``` - -Unlike get_record functions, you cannot check if $rs = = true or !empty($rs) to determine if any records were found. Instead, if you need to, you can use: - -```php -if ($rs->valid()) { - // The recordset contains some records. -} -``` - -### get_recordset - -Return a list of records as a moodle_recordset where all the given conditions are met. - -```php -public function get_recordset( - $table, - array $conditions = null, - $sort = '', - $fields = '*', - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_recordset_select - -Return a list of records as a moodle_recordset where the given conditions are used in the WHERE clause. - -```php -public function get_recordset_select( - $table, - $select, - array $params = null, - $sort = '', - $fields = '*', - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_recordset_sql - -Return a list of records as a moodle_recordset using a custom SELECT query. - -```php -public function get_recordset_sql( - $sql, - array $params = null, - $limitfrom = 0, - $limitnum = 0 -); -``` - -### get_recordset_list - -Return a list of records as a moodle_recordset where the given field matches one of the possible values. - -```php -public function get_recordset_list( - $table, - $field, - array $values, - $sort = *, - $fields = '*', - $limitfrom = *, - $limitnum = '' -); -``` - -## Delegated transactions - -- Please note some databases do not support transactions (such as the MyISAM MySQL database engine), however all server administrators are strongly encouraged to migrate to databases that support transactions (such as the InnoDB MySQL database engine). -- Previous versions supported only one level of transaction. Since Moodle 2.0, the DML layer emulates delegated transactions that allow nesting of transactions. -- Some subsystems (such as messaging) do not support transactions because it is not possible to rollback in external systems. -A transaction is started by: - -```php -$transaction = $DB->start_delegated_transaction(); -``` - -and finished by: - -```php -$transaction->allow_commit(); -``` - -Usually a transaction is rolled back when an exception is thrown: - -```php -$transaction->rollback($ex); -``` - -which must be used very carefully because it might break compatibility with databases that do not support transactions. Transactions cannot be used as part of expected code flow; they can be used only as an emergency protection of data consistency. - -::: More information - -For more information see [DB layer 2.0 delegated transactions](https://docs.moodle.org/dev/DB_layer_2.0_delegated_transactions) or [MDL-20625](https://tracker.moodle.org/browse/MDL-20625). - -::: - -### Example - -```php -global $DB; -try { - $transaction = $DB->start_delegated_transaction(); - $DB->insert_record('foo', $object); - $DB->insert_record('bar', $otherobject); - - // Assuming the both inserts work, we get to the following line. - $transaction->allow_commit(); - -} catch(Exception $e) { - $transaction->rollback($e); -} -``` - -## Cross-DB compatibility - -Moodle supports several SQL servers, including MySQL, MariaDB, PostgreSQL, MS-SQL and Oracle. These may have specific syntax in certain cases. In order to achieve cross-db compatibility of the code, the following functions must be used to generate the fragments of the query valid for the actual SQL server. - -### sql_bitand - -Return the SQL text to be used in order to perform a bitwise AND operation between 2 integers. - -```php -public function sql_bitand( - $int1, - $int2 -); -``` - -### sql_bitnot - -Return the SQL text to be used in order to perform a bitwise NOT operation on the given integer. - -```php -public function sql_bitnot( - $int1 -); -``` - -### sql_bitor - -Return the SQL text to be used in order to perform a bitwise OR operation between 2 integers. - -```php -public function sql_bitor( - $int1, - $int2 -); -``` - -### sql_bitxor - -Return the SQL text to be used in order to perform a bitwise XOR operation between 2 integers. - -```php -public function sql_bitxor( - $int1, - $int2 -); -``` - -### sql_null_from_clause - -Return an empty FROM clause required by some DBs in all SELECT statements. - -```php -public function sql_null_from_clause() -``` - -### sql_ceil - -Return the correct CEIL expression applied to the given fieldname. - -```php -public function sql_ceil( - $fieldname -); -``` - -### sql_equal - - - -Return the query fragment to perform cross-db varchar comparisons when case-sensitiveness is important. - -```php -public function sql_equal( - $fieldname, - $param, - $casesensitive = true, - $accentsensitive = true, - $notequal = false -); -``` - -### sql_like - -Return the query fragment to perform the LIKE comparison. - -```php -$DB->sql_like( - $fieldname, - $param, - $casesensitive = true, - $accentsensitive = true, - $notlike = false, - $escapechar = ' \\ ' -); -``` - -```php title='Example: Searching for records partially matching the given hard-coded literal' -$likeidnumber = $DB->sql_like('idnumber', ':idnum'); -$DB->get_records_sql( - "SELECT id, fullname FROM {course} WHERE {$likeidnumber}", - [ - 'idnum' => 'DEMO-%', - ] -); -``` - -See below if you need to compare with a value submitted by the user. - -### sql_like_escape - -Escape the value submitted by the user so that it can be used for partial comparison and the special characters like '_' or '%' behave as literal characters, not wildcards. - -```php -$DB->sql_like_escape( - $text, - $escapechar = '\\' -); -``` - -```php title="Example: If you need to perform a partial comparison with a value that has been submitted by the user" -$search = required_param('search', PARAM_RAW); - -$likefullname = $DB->sql_like('fullname', ':fullname'); -$DB->get_records_sql( - "SELECT id, fullname FROM {course} WHERE {$likefullname}", - [ - 'fullname' => '%' . $DB->sql_like_escape($search) . '%', - ] -); -``` - -### sql_length - -Return the query fragment to be used to calculate the length of the expression in characters. - -```php -public function sql_length( - $fieldname -); -``` - -### sql_modulo - -Return the query fragment to be used to calculate the remainder after division. - -```php -public function sql_modulo( - $int1, - $int2 -); -``` - -### sql_position - -Return the query fragment for searching a string for the location of a substring. If both needle and haystack use placeholders, you must use named placeholders. - -```php -public function sql_position( - $needle, - $haystack -); -``` - -### sql_substr - -Return the query fragment for extracting a substring from the given expression. - -```php -public function sql_substr( - $expr, - $start, - $length = false -); -``` - -### sql_cast_char2int - -Return the query fragment to cast a CHAR column to INTEGER - -```php -public function sql_cast_char2int( - $fieldname, - $text = false -); -``` - -### sql_cast_char2real - -Return the query fragment to cast a CHAR column to REAL (float) number - -```php -public function sql_cast_char2real( - $fieldname, - $text = false -); -``` - -### sql_cast_to_char - - - -Return SQL for casting to char of given field/expression. - -```php -public function sql_cast_to_char(string $field); -``` - -### sql_compare_text - -Return the query fragment to be used when comparing a TEXT (clob) column with a given string or a VARCHAR field (some RDBMs do not allow for direct comparison). - -```php -public function sql_compare_text( - $fieldname, - $numchars = 32 -); -``` - -```php title="Example" -$comparedescription = $DB->sql_compare_text('description'); -$comparedescription = $DB->sql_compare_text(':description'); -$todogroups = $DB->get_records_sql( - "SELECT id FROM {group} WHERE {$comparedescription} = {$comparedescriptionplaceholder}", - [ - 'description' => 'TODO', - ] -); -``` - -### sql_order_by_text - -Return the query fragment to be used to get records ordered by a TEXT (clob) column. Note this affects the performance badly and should be avoided if possible. - -```php -public function sql_order_by_text( - $fieldname, - $numchars = 32 -); -``` - -### sql_order_by_null - - - -Return the query fragment to be used to get records with a standardised return pattern of null values across database types to sort nulls first when ascending and last when descending. - -```php -public function sql_order_by_null( - string $fieldname, - int $sort = SORT_ASC -); -``` - -### sql_concat - -Return the query fragment to concatenate all given parameters into one string. - -```php -public function sql_concat(...) -``` - -There is a gotcha if you are trying to concat fields which may be null which result in the entire result being null: - - - -```php -public function sql_concat('requiredfield', 'optionalfield'); -``` - - - -You must cast or coalesce every nullable argument, for example: - - - -```php -public function sql_concat('requiredfield', "COALESCE(optionalfield, '')"); -``` - - - -### sql_group_concat - - - -Return SQL for performing group concatenation on given field/expression. - -```php -public function sql_group_concat(string $field, string $separator = ', ', string $sort = '') -``` - -### sql_concat_join - -Return the query fragment to concatenate all given elements into one string using the given separator. - -```php -public function sql_concat_join( - $separator = "' '", - $elements = []] -); -``` - -### sql_fullname - -Return the query fragment to concatenate the given $firstname and $lastname - -```php -public function sql_fullname( - $first = 'firstname', - $last = 'lastname' -); -``` - -### sql_isempty - -Return the query fragment to check if the field is empty - -```php -public function sql_isempty( - $tablename, - $fieldname, - $nullablefield, - $textfield -); -``` - -### sql_isnotempty - -Return the query fragment to check if the field is not empty - -```php -public function sql_isnotempty( - $tablename, - $fieldname, - $nullablefield, - $textfield -); -``` - -### get_in_or_equal - -Return the query fragment to check if a value is IN the given list of items (with a fallback to plain equal comparison if there is just one item) - -```php -public function get_in_or_equal( - $items, - $type = SQL_PARAMS_QM, - $prefix = 'param', - $equal = true, - $onemptyitems = false -); -``` - -Example: - -```php -$statuses = ['todo', 'open', 'inprogress', 'intesting']; -[$insql, $inparams] = $DB->get_in_or_equal($statuses); -$sql = "SELECT * FROM {bugtracker_issues} WHERE status $insql"; -$bugs = $DB->get_records_sql($sql, $inparams); -``` - -An example using named params: - -```php -[$insql, $params] = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED, 'ctx'); -$contextsql = "AND rc.contextid {$insql}"; -``` - -### sql_regex_supported - -Does the current database driver support regex syntax when searching? - -```php -public function sql_regex_supported() -``` - -### sql_regex - -Return the query fragment to perform a regex search. - -```php -public function sql_regex( - $positivematch = true, - $casesensitive = false -); -``` - -Example: Searching for Page module instances containing links. - -```php title="Example: Searching for Page module instances containing links." -if ($DB->sql_regex_supported()) { - $select = 'content ' . $DB->sql_regex() . ' :pattern'; - $params = ['pattern' => "(src|data)\ * = \ *[\\\"\']https?://"] -} else { - $select = $DB->sql_like('content', ':pattern', false); - $params = ['pattern' => '% = %http%://%']; -} - -$pages = $DB->get_records_select('page', $select, $params, 'course', 'id, course, name'); -``` - -### sql_regex_get_word_beginning_boundary_marker - - - -Return the word-beginning boundary marker if the current database driver supports regex syntax when searching. - -Defaults to `[[:<:]]`. On MySQL `v8.0.4+`, it returns `\\b`. - -```php -public function sql_regex_get_word_beginning_boundary_marker() -``` - -### sql_regex_get_word_end_boundary_marker - - - -Return the word-end boundary marker if the current database driver supports regex syntax when searching. - -Defaults to `[[:>:]]`. On MySQL `v8.0.4+`, it returns `\\b`. - -```php -public function sql_regex_get_word_end_boundary_marker() -``` - -### sql_intersect - - - -Return the query fragment that allows to find intersection of two or more queries - -```php -public function sql_intersect( - $selects, - $fields -); -``` - -## Debugging - -### set_debug - -You can enable a debugging mode to make $DB output the SQL of every executed query, along with some timing information. This can be useful when debugging your code. Obviously, all such calls should be removed before code is submitted for integration. - -```php -public function set_debug(bool $state) -``` - -## Special cases - -### get_course - -From Moodle 2.5.1 onwards, you should use the `get_course` function instead of using `get_record('course', ...)` if you want to get a course record based on its ID, especially if there is a significant possibility that the course being retrieved is either the current course for the page, or the site course. Those two course records have probably already been loaded, and using this function will save a database query. - -Additionally, the code is shorter and easier to read. - -### get_courses - -If you want to get all the current courses in your Moodle, use get_courses() without parameter: - -```php -$courses = get_courses(); -``` - -## See also - -- [SQL coding style](/general/development/policies/codingstyle/sql) -- [Core APIs](../index.md) -- [DML exceptions](./exceptions.md): New DML code is throwing exceptions instead of returning false if anything goes wrong -- [DML drivers](./drivers.md): Database drivers for new DML layer -- [DDL functions](./ddl.md): Where all the functions used to handle DB objects ([DDL](https://en.wikipedia.org/wiki/Data_Definition_Language)) are defined. diff --git a/versioned_docs/version-4.2/apis/core/grading/index.md b/versioned_docs/version-4.2/apis/core/grading/index.md deleted file mode 100644 index 1a3112c82f..0000000000 --- a/versioned_docs/version-4.2/apis/core/grading/index.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Advanced grading API -tags: - - Plugins - - Grading - - Activity grading -documentationDraft: true ---- - -Advanced grading was introduced in Moodle 2.2 for grading of assignments. It is intended to be used for grading of other types of activities in the later versions. - -## Glossary - -In advanced grading we operate with three main entities: - -- a grading area; -- a grading form definition; and -- a grading form instance. - -### Grading area - -The grading area is basically the area that can be graded, for example, a submission in an assignment module. Each grading area may have several grading definitions but only one for each grading method. In an assignment's edit form (or its Advanced grading page) the teacher may set one of the advanced grading methods as current. The class called **`grading_manager`** is responsible for grading method operations in the specified area. - -### Grading form definition - -Grading form definitions are the set of rules defining how the grading is performed. For example, in rubrics this is the set of criteria and levels and their display options. The basic information about definition is stored in the DB table grading_definitions. A separate entry is created for each grading area (that is for each module). Users with permission `moodle/grade:managegradingforms` are able to edit the definitions and mark them as "Ready". - -### Grading form instance - -A grading form instance is created for each evaluation of a submission, using advanced grading. One instance (usually the latest) has the status INSTANCE_STATUS_ACTIVE. Sometimes it may be the case that a teacher wants to change the definition after some students have already been graded. In this case their instances change status to `INSTANCE_STATUS_NEEDUPDATE`. The grade pushed to the gradebook remains unchanged but students will not see the grade in advanced grading format until teacher updates them. Plugins are also welcome to use these status levels. - -## Functions - -## Examples - -### Using advanced grading in grade-able modules - -The following example is drawn from **/mod/assignment/lib.php**. - -1. In order for module to support advanced grading, its function **`[activityname]_supports(FEATURE_ADVANCED_GRADING)`** must return true. - - ```php title="mod/[activityname]/lib.php" - function [activityname]_supports(string $feature): ?bool { - switch ($feature) { - // ... - case FEATURE_ADVANCED_GRADING: - return true; - // ... - } - } - ``` - -1. The module should define a function called **`[activityname]_grading_areas_list()`**. -1. There needs to be a check to see if there is an advanced grading method for this area and it is available. If it is, retrieve it and set the grade range used in this module. - - ```php - if ($controller = get_grading_manager(...)->get_active_controller()) { - $controller->set_grade_range(...); - ... - } - ``` - -1. There are two ways to create an grading object instance. Choose one of the following. - - ```php - $gradinginstance = $controller->get_current_instance(...); - $gradinginstance = $controller->get_or_create_instance(...); - ``` - -1. During population of the grading form, simple grading elements can now be substituted with advanced grading element. - - ```php - $mform->addElement( - 'grading', - 'ELEMENTNAME', - '...', - ['gradinginstance' => $gradinginstance] - ); - ``` - -1. On submission of a grading form, the advanced grading information shall be also submitted. The grade for the gradebook retrieved from plugin and saved to the gradebook. - - ```php - $grade = $gradinginstance->submit_and_get_grade($data->ELEMENTNAME, ...) - ``` - -1. When the grade is displayed to the student it is displayed using the grading objects renderer. - - ```php - $output .= $controller->render_grade(...); - ``` - -1. To show the grading method to students before they are actually graded: - - ```php - $output .= $controller->render_preview($PAGE); - ``` diff --git a/versioned_docs/version-4.2/apis/core/htmlwriter/index.md b/versioned_docs/version-4.2/apis/core/htmlwriter/index.md deleted file mode 100644 index 4740676734..0000000000 --- a/versioned_docs/version-4.2/apis/core/htmlwriter/index.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: HTML Writer API -tags: - - API - - HTML - - DOM ---- - -Moodle has a class called _HTML writer_ which allows you to output basic HTML tags. This is typically used within renderer functions, for example `question/type/*pluginname*/renderer.php`. - -:::tip - -Please consider using [templates](../../../guides/templates/index.md) as an alternative to the _HTML writer_. - -::: - -:::note - -There is no documentation for most of this class. Please read [HTML Writer Class Reference](https://phpdoc.moodledev.io/main/d4/d78/classhtml__writer.html) for further information. - -::: - -## Methods - -### div - -```php -html_writer::div(content, class="", attributes=""); -``` - -Example usage: - -```php -html_writer::div('anonymous'); //
anonymous
-html_writer::div('kermit', 'frog'); //
kermit
-``` - -Attributes can be set by an array with key-value pairs. - -```php -html_writer::div('Mr', 'toad', array('id' => 'tophat')); -//
Mr/div> -``` - -### span - -```php -html_writer::start_span('zombie') . 'BRAINS' . html_writer::end_span(); -// BRAINS -``` - -### Generic tags - -```php -html_writer::tag(tag_name, contents, attributes=null); -html_writer::start_tag(tag_name, attributes=null;); -html_writer::end_tag(tag_name); -html_writer::empty_tag(tag_name, attributes=null); -html_writer::nonempty_tag(tag_name, content, attributes=null); -html_writer::attribute(name, value); -html_writer::attributes(attributes_array); -``` diff --git a/versioned_docs/version-4.2/apis/core/index.md b/versioned_docs/version-4.2/apis/core/index.md deleted file mode 100644 index 68027faa93..0000000000 --- a/versioned_docs/version-4.2/apis/core/index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Core APIs -tags: - - core - - API ---- - -Moodle provides a series of Core APIs which can be used by any part of Moodle. diff --git a/versioned_docs/version-4.2/apis/core/lock/index.md b/versioned_docs/version-4.2/apis/core/lock/index.md deleted file mode 100644 index 7b80a348f2..0000000000 --- a/versioned_docs/version-4.2/apis/core/lock/index.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Lock API -tags: - - API - - Lock ---- - -Locking is required whenever you need to prevent two, or more, processes accessing the same resource at the same time. The prime candidate for locking in Moodle is cron. Locking allows multiple cron processes to work on different parts of cron at the same time with no risk that they will conflict (work on the same job at the same time). - -## When to use locking - -When you want to prevent multiple requests from accessing the same resource at the same time. Accessing a resource is a vague description, but it could be for example running a slow running task in the background, running different parts of cron etc. - -## Performance - -Locking is not meant to be fast. Do not use it in code that will be triggered many times in a single request (for example MUC). It is meant to be always correct - even for multiple nodes in a cluster. This implies that the locks are communicated among all the nodes in the cluster, and hence it will never be super quick. - -## Usage - -The locking API is used by getting an instance of a lock_factory, and then using it to retrieve locks, and eventually releasing them. You are required to release all your locks, even on the event of failures. - -```php -$timeout = 5; - -// A namespace for the locks. Must be prefixed with the component name to prevent conflicts. -$locktype = 'mod_assign_download_submissions'; - -// Resource key - needs to uniquely identify the resource that is to be locked. E.g. If you -// want to prevent a user from running multiple course backups - include the userid in the key. -$resource = 'user:' . $USER->id; - -// Get an instance of the currently configured lock_factory. -$lockfactory = \core\lock\lock_config::get_lock_factory($locktype); - -// Get a new lock for the resource, wait for it if needed. -if ($lock = $lockfactory->get_lock($resource, $timeout)) { - // We have exclusive access to the resource, do the slow zip file generation... - - if ($someerror) { - // Always release locks on failure. - $lock->release(); - print_error('blah'); - } - - // Release the lock once finished. - $lock->release(); - -} else { - // We did not get access to the resource in time, give up. - throw new moodle_exception('locktimeout'); -} -``` - -## Use a different lock type from the default - -Change the $CFG->lock_factory setting to one of the other lock types included with core. These are all documented in config-dist.php. - -## Implementing new lock types - -If you really want to do this you can. I probably wouldn't recommend it - because the core lock types should be very reliable - and the performance is not really a concern. - -Add a new local_XXX plugin with an autoloaded class that implements \core\lock\lock_factory. -Set the site configuration variable "lock_factory" to the full namespaced path to your class in the config.php for example - -```php -$CFG->lock_factory = '\local_redis\lock\redis_lock_factory'; -``` - -:::note - -See `lib/tests/lock_test.php` for an example of unit tests which can be run on a custom lock instance to verify it for correctness (run_on_lock_factory). - -::: diff --git a/versioned_docs/version-4.2/apis/core/navigation/_index/Moodle-IA.png b/versioned_docs/version-4.2/apis/core/navigation/_index/Moodle-IA.png deleted file mode 100644 index b081cfa5302e5526b7f3d846eed99fecb58a6245..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 252363 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
    6;;vMHciX}}-`{Dm`e})%ybTSH z96H33K|!ajt^MboJ#lISD80qyQNe%`VexRfkXa-IezCEg05hY_ z!sG=RIQ6AiU1XpXJZBve1Ih2Qu&&~E@^csxc)cwTs(0_>GI9@~eT8AZY0t0T&q-ub* zG$qoBHyIiG0Po>ZaaSBH>jxLJG4ZVFfQ9a!Jy2>>i}zt?R}5h$?b{Bl zvOR$h$a)tYTx#dp=DagRCy)fPS_)1J8!zpD%3LdJ>xjOy6;4i{@P9ru?ii43O;vWy z(#x+t9axEikR4hB$+Wkc3ouPd)OrqjmJ*W@+k=$a2^J4&+2D-}*D3q7ge+~ueIb#G z>hb1rJMDJgOedrZgD40Z4I6IYxC5IRIKR#3o2{mJ&zlhBQ>m%^J#HE!7OK;xn^pCe!QtBS%^ekTTd_Z{{7D!DMZx4WY}A_w0NN;d6Nz03`%@4s{TU8 zl#>zRY5U%EO&%mZ7U02QOm5ANWgy0B0IIF={fM#CUY{>|O{oAibm|D)_JG8eELrmO za}itdzFs+`1D~(WDIVsq5f{=)33I zkdM<@6+=P*H=J8be11-vGKEyEMa}Y2 z9je0;{#^V0!w8_x;$=)#S>3_v1y2jFf%xgs8qkDD%B5?0JU0k=MY*nlm!|jGTmQzR zM_;i5urQL;S25{I!lrRA95Wp%y92`|62re((ZGht5QbL_$DxP+=2{eYsWeu6ef6C7 zSxk%=XbSql!T;&wN7q-Ewo%UP$FBhjIw!ASKy~ka5n3^1NxiUZY(A=!NfRf=%)Dl3 zY&=72oA5t?o>g%91U))}D{Q}n)2D4FPZrS|_SUOco}}Y+%LH^!DFxUAy^tf4SpV+J zmse#ksF6h92o^iSLK_>KOL+8L|8$1Ip@(txOo$Z0KtN0+}j=BH%`~-|sC4e341cQd6 z!qgNKf^vs5D?!?T1F6WcTW`~J0~9V!I$|Cf8+|D3b*SBDV`j>KalbqGR$+0P(piO#8Pt0ADt5UJG`&_f<2ky|`;+u4c&zFH;U&#i zd>}!FQb)fJ!bEx>c_ZeLC1^@USeQ@1_(R&fIYM!7Slp~`QOn0oY7mqN6G5Qz=yotK zqB8Ynr3p@TynBF5c;X$KuopiAc$e+lSHRsXef39BVm!qa_Z%Ohh|o~l_O1#h8T8TB z#r5lYRMb0oM;JOU|9D>{6*x0oFY>lTpFugqo`x9!4gc2LC0d<311Nzz7iE6kH1ys@+Is+bp_P3n6QCYzyk*|8g!>8fLyc$N@21ZfJ=wpZhL5@H~88BIE8;hP>%qLdi!no~l+~F7RjQocXL!j{ItvCctoU&$d$y)n8}N(z&Z54m9xhA`bD8zlk}y z3bFxE{jlBHmzK`K+8IixUkLG9tX7fL#fVBBUZApqF{8rv6PgD*1rzH%vh6T<3ks4Q z`?H=XO-IcOZXdLD>(`gUpkju}f(&i7AOe1Onba}=5ca=JaODZm>-C?xIs<_9;lnR9 z4aR&Oj>#3r9E+7gLq_PCMVWl33XCK5XY8Rvh`}?51)*08nCV3WeGwu4?03?qn5pMB z%F@Ykx%`CHKaMBvr6}}bY%&lI^<1xBCy>)A?(%d^=BIa2++}HS)He~#f6D9g_XK8|ai4|9cePD_o=@80xy+%5qXYJ$WWLK!?_)kR?> z7B%bq4}t>knf$;~Ya2{EualITd~#ryJKl}*d|70a{TQ@E9`a(*LGCz;iV0Jm(0g6{ zc+)|9u31QzdU#|r5xUrrCRc6)>Y>zB%`4L?vJ5)5^t~C`j6oQo8CyZFz2tHWm^Dkg z#=N!;(tR2Q>=}RgGBZBKs8^=kY@d4p^?dt|9Z8@cI`*gTnQNps=ooaBWgPe57_fLn zdltb-6FKMGS-nHM-EjK!g!~lVRLk$`nx9*%zg;+~$DJ}9oaER)?|Wc;pq4+;`fwzm77OYX@eFXf7YoK`+!`bI*}^zksM7J&L@6l;tT239rg5 zi(7ONo_9UFZw!kM3K!Py)q@!Uj-U50=oqMVd8(!iziD}O9%$K_DWh#wtK#|KSibDv zTYRy)s)~Gs9w5C_>@fjo@88GtfsBLEG9#tix~|;&l3^ykH_N~pruNRHI?faJ#27$T z{JFn8gOr7e0$gp-^-?$puBI=@%rU<3J<7~PpB1-2I*b0{I zWBOwf!M2T{0>qp{N{jpSg$ppA@}8XFDxr3>DL^t@#ytVx!1-)Cq;x4%3CtdvH=0A5 zP12`oIikyUHnh;P)Ku^1+@b~>6I-)u&z>HtO{p+nJ#u-u%9PF)ys2G(xQG$3f)H`_ zYe)H^OP8KKe7ITAc4&WAvy;?fb?Ec=>o@z%6tEr`NFj(ZO2bt<5!E18dmTQn#NMymxqF-Q?a!`EseWcM67hY!7F&yV$w*6MlnJ8&mM>ctPp*z-wcHUBKA9NlInpy+xGX}C11i${Ct)FY zeJv=!r$d~+aN-D_v~GA+(luhY{^id^+hJQu3SRzP{B6%o`!8A7jQaQg9;ADH3TCR# z&PO+H9A*^3zio1wKYuD335?RzytzM9wpnF3w!4P19zHI(5NMh+sitXV;m{zL3Y=s8 zHf>@XtOfLi1PrX zg@lqhZ3_#8O#qTg!baO7+__Sd``P`v($?pvnu-buG+LweM|`XuBOUFJTC`g0Q=zwqYr=)CmgUIN}{9#h+ z=OmFf)_v7v5Z{qWjrS@m> zN;Fd5&(0fM`(5q-@##}fygK+QXC>*ZbJMa9@GhTaWSlQ>+X^vXgOUVM^6~N}hs+AcGAYEqr4WLPr|P5^Jii6MMWH5 z5m?at!G$=r%EIgrt1j5ab{Ytu3knRho@%c+;7+h&|9WMu_!|L#A5?!=_etXo8(G>q zH_Y8!lLCiSj7Aw#FXEQjJ?B+NAKt%T@hNQapQAs~MJB4*UELL>&Ca1S)>;u56hzAW z@xxxH+^#AC_&8-|j9tvV%o`4D9zBNsLoEqaJA8{%&w{KzH=nF?WP&eH0_v5}1T|i8v5*O7RPWC7J4jJ+a zpIO+bCt|N3kBQ-hMX1r&$K(+|qTbrtZQ;q273PKt2!HnNjns>b)1;VQz}9Dw%d!+E3S8MecHNtafv=+mQz+>hx>Tq+Ljt5PG)=^HbN zvx}djlM~+cl#ea&rRdXVs|-ntiF0Zs?`&vfq89HZxtld?OZ&O@_7JM+jt?Q3gpR*jWqV-YNXWTR zFqP`xgqfJP+gU}i<@VV`Ni)18i;DIPb~^&bfu0#+*xa{&vi8L<&L0DWG&f&&9r&fIuC5^Gvqqvu;olp_5J_?=(%(RI0#R(- zF|`aQp|p;Gd3gnG`W;JH0YI516}#|C6D+~jSbdmz8=;M2vow)Yqg>;VrZvaq=I+dg zA_K;OWw(w(8g6fvvi6~cmU3{COHr*`JQ*u(U6_ybRu}e*XGykJusf9Mn?n@Ho3q-X zvD}d+lb@_p@H}MO6kM4KE45;sY6A4G>%D6G1(oDCYHiwJzNDg1)1Ar3dcC5>kWRWl zs5&}hFd{HCv>Q6Kf%@xX5G`0eMF^*m{3M7soEJS$A0GTV4Xt{t$eQHC`_H$m|YozWamG-XmHDCU&?^w9id&vnp; z0iQ#cah^Z_p4!=`>FGTgnQnc%RIV`?h&eN}LGKOrdUfCJx2g5+IGy8Ry*wrF+cz~aaV|rdJWaeI4ds4( zG-u($leNb?bT@2a!KCf-AKzKiX3*DJhJo!j$>hTH9wi){rI`uBwX zNnsYY9R^7%56+H>3vpTF+ovw!_}VDDi6R>0sBnHS>iiW2dtoZnd_+DGov>xQm-(!j zGqYZJRIrGV#8Dr+bQrLbBouX>e4 z((I&ZFREiU<2k@YlnFh%ilQ&gX#IKH24TrF$!0+_0rI&WEV9(Ja0_i!Kylzi(vla? zo}EvNu5llD`aj8ai_iFF8rTRj>2wy0AUDTq`G!WN#hAz*c z8Ek3UF#HxjOdziZzI*xLCP91Zlqt-u-6QLd^*qa!-e_y_`H`|(MYy52+qbWy;x2wy z?6HRR%>l9jRGP^DX$^RVzI0xjQrIswJ>4$e{n+l^lgXYa_5hwvoWOSB80=frwOczG z+tChAO+8)bdma~ki!-jZf{F~MD@Mr&$-6XrkXip^6E1@@tfLrsbe630&a9$~Q+zjV z8t&;iL~en%1lu}0t9ti~=h3dCMvPdxe0j{VV`wM)4j6y~K=P>e3GV59YO!_#VMQ9F|}pkF+(Jop$SU_EsaenOe%?| zK-#Q8JSsupS-JorTm_WJdt<*cbZA0Pcq;nW9QQpWe&fYh=DBwEYzBKB0g8oc73A`G z&;?FR+QVR2vrzP)LB%Ep7=ZvF+C5EZ;eVufW5ZLVu#4I?zXN_mr=AoQ*aV-<9@vY~ zAf38_KRLUm6YzKZuY+eHfKmH+k~{MV=|Gdx*j<*x1D=d4V8@WC33h)xvh%9h*r@t64KQ9>$3iFzc|iv@*)Km}hPj zXK*r3dD)gt2Io7~?r`^M%`5AvyKjVcjjkV^Mr4mS9XBdE|Egf ziU-e&QZ8K%_b8XHy_MRj!SLvx4K~@{DWH+^T=Q=%Ui3YE!_s z-EtC%Wwh4b37E*IcK3;wTl_a9%Gn(R%4AoIm1IG@-+D+H@%@Dq2n{tiXB03#B)fZ{ zKt)~eiFbXIEy!aVcI~19mwa<&LxBym^lN@jL;&Lfku`FV!Zq6xL5 z>Tkl^n>n`~&QLtq&za)}b_QG$GvmrG8MHihhK9QOH5N4O{iMW1=A`{(!%&^j9$o0^ z3UCOIN1&KUZkZd2N#m|v!t_O$d3ctmKX}k<$dF1(C}2g<*Mqu)ksy%nlbZsg#e3IO zQ}ke=!E6BBqJN&6I%bS3IR%jcwVYoFuhL9uyy(^}HUC?NG4C9?#^HQvV*^RecJzo)is?V6siuBx zJhIWoktJ^$AJtg5NrcvV0ZEMq4vHLF&s-{58QfrX(`w(^TBG+rAd|R^H=PB|RqY>| ztN2;rHWBKY)$(1%_u{MUE+|%b!{3zJ+Mm^;Pmk8uQbB8fKx`f^=&}E=w}{X?HX$At zS0=fF&vy#ehunb9NAHm-*2$aVCk9wR2vMy;tw|YA-uL*7F7&2#N6T8-sEUe~(+#Yt zR2zal0vCzD|So9}#CwCx<-zSVbOF;yYQ6oOPEVZNrV>LBw8ws>#dk8G7L z1Z2I;u`O%ig8AcswBTNe0X3N$uT#6lUax36rbX?g)B>$jIfOi4R9001ntRhzW3S_} zwaw}S8l4wyVlhku=D(fA2x+E0@>LGD#4*LR!xmq43Ai6_=MnvpzUJbP19GDBL`V-mz442B4M>`HGt z-@}LJqNud18}A)C7`*SCecs?QKT1gQ7&tpZ6bi8nV1q@cYN>9#dWQ`9l(3zs7+vw~ z$&)zn>Q}FZ0PYzZdx7bAnq=R+`BnhZA(-Q#rWr8c932^kJt`~6X%HIIl?M%EwDwvk zBk1YqJk!)of5NYjdA4oW4n`d{i%jufFv}6WMf)Fo9E%>&*f_j;Dc}*OAs>w10t`4! zKafSxr7gG`YsxUx4mHsMOMCU|D&PXuFYUg5az{`GiZ%iu=i`I!WA-uxT8C8buVK+t zP1si(BTP_V$$2C2L|Aga>9h!!A-&Nzy-xcae!}K0V%nkikIxe;zQZ(yBs$g3Zsw&W z=9A_XOBiScT;C76CnoVjRpaBi*YJh*Q&^+nq98_h8oYHYx|o>QSds*KUStQ*YO^^u z=Z;8%SIFjfyZlOs2o9P@Vid{w%uzuwfYL>8dg!mAjcJiv8ANU-s0 zTNpKvxu3_urR7e!6to_%we8ZCDC;|Y=$3%L{L^yBDobiIa#V!Sr6D#XxHqeojTbQhbEQSz))y*|+I z4z>D+Crhou$w5EfPw|!|gLGIb2WG+@C0{uIbB}0ur0*Ws%7=%{^MXP!OIsC4QQyR* zQ*w2aON@X*UkZKDu`BzP5^|y5FK!ehTS^(P+LnBHZ=Dic0@&lM0dZCVh8Jikk^4i; ztZsA>W2;EM%4o;R)XuhCXkQ!Xx=L1&mc2P%}$ zFq&SRFN+!yNiF`IpcK)QbMt-CUe)jAm9Tv;=%V4D&tzssO~@TVd&nxlu;6S(UK|GJ zgq#FQ>Xvt0-%*o`*4_@lk#>6i~%Z6Aoxl2JEViXtFK*nBB5>1qI@uNr)OYs(&ae+Y&&*VljVJORhfF za_ag2OIGGyjz@6k?%nY=p>vAPIHTI!=fCo(gKp^(^~1OvL62ueUSM){K}YH?h;*BU zQ{Qqx>`&d#mjz&U@De({LQDZ_pEC6CET^T&9ud^kiZu%Jg!m96y>Zx`Y5!757(`qK zf4gZfQ&7@_!jpTE!^}`fF>wOh>E?%IBaKZvp5kZ)B6H2(nV3@jbyOL^-T+qi_K{G= z0Z7U`s}UxIC6utUnNDY;4O+yWV(>eKb#FCr;eb=38$sfHR$tdElF8J>pISognBA#s z0v_x4=;c?_yO7P6H-|1Pm>plh5D)Z{w*L@R9WkN@`2(%&^Z`aR(N9i;6@=2U9&L1{ zRWPsKLU*B<@iy>RwDMp&13J~mi>^%5t4{q^b?5fjUybW=>(q@_5ZEDtVK#UEf?J0h zrgQ%jXbP(__S^jB+@H7Ko-b=NN@uNuUcjn>!k2}7s~7oJcUW+LZPqI5!s?Z7P(0T& z^^+Z&(4G-Vi_>8f=f!>^(}EGue%8^L7(C&J)m*^S3K+5u6H>K|&=i=^qL;Cca*D&l z!`-UK&767a;KAEY=XUE%qpQ1$1{_Ns0)|@b$7PpUI@8ZO2Am`gO-lO#JWP2X+-J9| z3eXb213z`)*$EW!EbP3n9Um{gNto^8g3QdSX5A1d0nx1)!Ek?U(Bft< zYXa(g(^JQsPE|@>MHk=mmM|xIUnIs*g3q^Q2|%Z14YotNcRf z`q3um3tk%I%^$yb5g$iV{e+aEolF)&BM-q5N1HjL9S)C!(O&Z_q2{1Kwz*oWMBy`b zEp7zm4d5WHkNx|zprh=~7);o}f663+5kdaXawkB{9uKF4wYNcm&Qml^Xu<jIU(6wvBg1V>px?KZrNz3pY2nvJr^^<1iiV|$t&-Oi`1~E(P)TutJ3vXv; zzpmfv+tMK|BcY+zc7E2&B!!(Cm#BJ%NN>Vx382KN-K;mfts#}Q-Hc8pe(8bOSY0g9 zth%UIF9TkrVIE$jsXpzTg%-?~l?g6$TQAt45E`T=@|!nrhL?x|Z<3mR6auY(H~y(l zr%o+rF;MxJ1j99lEkhEkk@FhCPR*N%0@+G7s9~lcX0^jK0Bq6%qBuua5Fq>q@^WQL zq7@pJHq@Hm#`tLzN45YhAd{pG>vX*L@$*0 zY>5XCA9nE@0ul_sBtDnEJ`ihm6X6EU3Whbag6BMF&@~27;hDo+Zx)ng!mfve7aRfY znR^a7kw%z`g1m`_>Juibf@ouEsjNUd$(T1t9&pIw_&l5;{27kS-8D6Ru3scXj71&(+}RDfq?-`8fNi0Lr9d`irc+X+-?D|bW!C$umEY84%48-g8%x4q?Vkouby7k>DdkBeu)lLDx@5_5Ec1|h}67;o?KYz z>IP&;1!g285c5{$aPSU2(s$2Q%d13JcGG07zGUAvkH!5$sPfYiwM_nZ+UEKTh0f ztKSQoZ$QXIo1L_ldYM?n%HY)7)rY4^)3S$ga^k&vdDO-3mysg{Cw2ZC2D~_Bp376c zrPY8roUNSDjs49w%_9?wGsXG1q0!XnY>Y zcqhTxA@l-G9gm-rVH-Am1O)?c+9@$^4DmR0Dkn5?D&rBHte{^+w8(e7@cAL~; z@6}15h+n3zhN`E52@4H1@=e}LNlB@)@OG=eFR%8A{|2u-%^-D%UAe>nSmEp~GFs{h zLJrzo`c-Hh=ETf+_)p7;(u)@jX&6$%Hrt?3+y$2U^5u);WA_(FIM^}Q zg)N}4qF#xPj_y6;u~JwvO0P)mk&}c$F##9;TA-}I{S67T&g}bk8?*QP;%t+^C=P3i zZ))qh7N*9oWG57G7Z%T_Y~mcE(M_IPvTTK)45><4*-C}4~yGHpgG8-?I8>%%EOs1q;)AzCJS}d}8169-|WD zPo8@C;=pbD=o?cuh5H|jIrrqrf}x51{f3RYaxi`B$p@n?o7z2_DmP!(?52}^-G{Fl z9^GbLf7bKXwVdJKS63~+c6r1@HAg;Jj(p+`G6{d-wNS^k=Rq zh)dk+YDr@V4(G?L>W{O812VR9iBrurP(LiS9#Vwa?`@7CA;7taNa6;&{HwH>rRKol{Z_h?F;{^v4&?Mr?IeK zAl(Ku?7Dk8^b{|Cb8`p%uckG{rU```bSv`{s`Dpb|GqQ0tVVd&$6U->eUD%D`tbx7 zQBNlYwEUmqmyrQg-)g424-_6$KE_(2Des?DJ-)s6WinI2LNbv3k-j?Wp}|DM_5D1( znx%ZZq>;3~;apywBWS^v0)ulPqO`_qKWp2zRiovuNtyI`kFCkdKr$m ztRPTg&Yo43MM+PTBv$>+l|TNm@qoJUjcBedo&xvhSWAgnPiN!dtD4j~FKC`ovfQz| z)+ItB37N89>;8kyTKs`TV%3|!Km4O()x-lfP+Fh!KwwocP7Dg#RT7ZaH6^=euAWb^ zbKif%rkxGc`m#8#idT#DuU>%ABY4Pnj_=1bQ=fuClE#v0@<+ovt@wmZ2c3`ZCWH|3py}(j7#$&lNgyiEt1TcmFW1&iZ-XCb`l(_v>Ol*YxX6E&pk2c!&fL&hRX z%A{a#f&`!4h+bBT=cfS?xf(We-cIFHO}Qbi3k=|A-;w=jWAN`gqS~DYtIlzgho+56za5R@|WZ#={eKq~r(< z!FpYc!h5PVwKo2d!Idw%Qg9*GyDC3vtx)yyF8S0Hs9w}PUKJHb)LbpAY@z>3rgU>~ z&OSG!ToJ5;#3XnOfs6ljwPsD41ZwNXL?-s-Tx+tCSyhVDBWvF?D*41aZhJL z*!*L=J7lX|}*dGXrf zXS&!a9VKi1LnEiSoSL|Yu3D!_EvMXIm2Ok!wQ1Lp%p9rrIOW5#%i=G0OJ^9*=oa1dl>`=~yv_(NaKqfB@|dh}0X4k9T`g&ryn^rZ`Z z?vY_W%iol{-)YU4GvC(!ypp)vtDMjw#7Bp9z4BsfDq_JfFlFzs@hvOQq;#5TMef1G zCNC*7DB^TX03<8lxBp`QuV;ND>Aq^yh7%)C_CX@0QI$Kq%`DF|<3ci9&%JXjU3v4{ z{AnxKCRG`z9n#P^e5YQbmQv-`_g2a`o1Qu7e|EqTtOPV2HYmg_BS!UsA9kcQPg!bW zJF4(^IFL&E%A|qXSEl#rE`&V(>3pO5kEf234m?;}&S zUEw5rW-R8D#kPVCkFxgH^OUt01jKuxR0w`(&eIpe*oz^)LAv>CDzAO>`u55#1uv_2 ze@vc!h841@(`sjW{1;y>8wGFXIDHps8TxJ=O7t569?O*i?&sQ*vJHZ+? z?}Bs*10INIBFZ1mGf6wr6&;d-M>k(s8Oshoow+6kqbSriUMbDd`JOqmltffxZ4rx# zY_pP+=4$aHBOV(|ZYm5*&ZvmhpO3MwG-}F{kR!g!r-;p*ws^UR2Stj3bUnm#ZUmaS zEY1{;&g#sI*W<_@__>IEfvqGVhD74A`Ec-jv_BS?3r^IVAeL~`4Y$Ty8^^&lddbGm zpH)+FMq>uclEX?!Xes2A)IBOIb4+zjyl=PAXAM7M<9n4pC-%=QT8cj9T?5IXt&#p` z&k1V1=19>~`uW+@1G+WOlyqU?*S8iv_ zFE@7Wj}tZDb!$|V%<%(iwYJa~PG2yyw<+dnBt$T~ed@gM-| zX#(7anztI&Z;1{2=)E1Vx%B;huQt7>6rRbhNE@zkt?*VeMA_+CStita3BRr+G+S?v zmJ(6w)fOWpk|sNflG?(edAZp8ZL?Vhr&0!))m+};G<|eEiAU!terodC>?5X^MgHKr z1t*UFZtXhHeTqRK#0#Lj!;*@e!x^T}>PcR0u~)Y9d*jh@cwojUnGt(@q23x|Seu;4 zI^_SJTwAN@<>_O8*0D#e+M6reN^kd#NI6lb!2*%-*Y=z3{I|JOmo0oN{W}v`*K>!D z6iKE;Vq>yrv~YGZ7`$F9%3l1J*&bq+r6h9n>NRWdjeSzDLO&+Qe|=`HCI?@aq}WWB0s8&qWVVsdK#!cwHCHyX5Bh*fcq$n0|m{k5Of znPbgA!ykn$iqGR5I}sBzu|@9BFMKTEMDMcO8p8YF`N;+1HO!()N=t>7j9Q(F!~4^o zd41w@qe!tv28fWTyiKHe!tixxeTk3h0!UWW<7*4zo?^~2GfyQPg(&6SmVtcYk$R4trMc_*xCv!U=)Ox8R$tr`z^7EGgYi*)S{63wPe zV#XW9wsG6jN|qLX{mCt?K8k4kmHXo{+2xNsX0CkO@CmVe{|;#*174V|CvNlBbMT|z z?fZaF&@tL{W+emNG_?}jS$-yiI`cK5ruv&_j?p-N(dW`LTMLWxNb%knP+3+MEcQO} z9;DA~Gq*;|4rj6@`yeEFf9y5Omayy7wh4q~k-B!w5t+xU9Fu6_an?^oRasd)GJ{9l z0%UtnI5ISct=H0W5KAhFYfIsx{^zG+@g#kQS4&@H;N6HWyvEY+liMk$VOZufr$xK| zwQLQC?tgy>@levGyfufC_}V_q#=-(@fQQyn!{nqWJV}#fEX&Xb9~ah7)xD8Vf)l71)KJghYFnZ%chrHzHV(!c(E zPOZ(EL?U)i?%(SeeU!GAp}28;VHe6f*6oJ6cbxNkhmAa9qkXh~TJG1cm>#e6@VGcm zQuTS<-lhE-E@|3OBJp^7X!!;njXRD};{Zr+HrCMQ$9#2J7wKhv)A<{QW7H@hNxI)+5}Pjy$xvzb|YPfAaiqYq{F@ zs?7!d4{L7%mgD;M{omP!WV$0$h6Yn%XDVZoWGF*PLL@SkF@z{;r^t{(nJFoisf~!z zfDD^W0~sQPP*H|5q}2O4?_u-Xzvp@1XUi zxP*v=+wyqg5@irGptqmd(B}SQ4qM}g5(QbRl!uOXxqeL}Ri7z)>ag=cbJoZB*lUCU z_m0ZUgJe`KY*T|@o?ApB_qXcT5_k9ZWloKTvUvD(^bPZmezk0X@~^yKwCtSYXZ0DF z`O5bb^S)29a)b+U|8K>-%kHL}cOB+^tT@{Fh`}3wPdV@6l6U{xB_&(&8%ZYsUj@sa zQSzdbo^IU)#R_Q3cMmn#Ep|H}(|5Ipr===-nu<5=^{W+58*OdgQ29k2dDGvN&sP86 zm&r8>*$Afpw@XZwuOq%GL-9JYOO(sFwvVop%#!nPVr8`wn7Qn17N7#3G{PL?D?R^y zQ-tx^^(>LEgf7bG7dM!# zFdJgc98f-gE1rMnFC#ck`TXKme<{aBJd4sci4_)wGn)kFpO`pRU-q=xYZ#!pW8^zO z4NLsDTc~`1#4Jo{wV}dux?C?p{+kLrEBj650u#TvS2CLi}bVgBD*PY`r( ziR3i9e28*0U}vh9T|A%|tZ-KSx?h)@KO-5cu({F(><^_;5wn`Ed}2TDuC#)(yDOi# z1v4ZI{8&_z8HrHk6N_6ZN5ToaxlTFR-Q_E65}r4n48cxFtx>Nc4PQE`!?7ppBhEDwT zvcf$29}4p~SK2u-80t#XSSaqGTzKLRLlt&Tc8Stz$SzSX=)ptPH!1C$xfPG6G$EO{ zMbxcbpTIM|X#r^3nc%p`UX2dks~$fQ&2~Eb}qe<~B-0sm{o0D9xU@TsauJc+>jI zMa`-hrKX%?#_vDBQD``kU7R#&w@4{*02%U-{-yGgaA~KZ>h+s$m}wF^Nj_Kp8^Zi+ zpH^&&aQ6MspUY9V1AkS{fS5z6at17!0mevnfBzlaL1_kMcTm~^*(J*7v}|rETnLFo zFBJG0hz-%+B#H*Ye!Qdns~Kzt5_KePLbz#Ltf7yXF4F;q5IV_RoIl@nILrrPS5!;I zdkvSF`;KWKe?kZg5zk0TmYe>a3wvsH{Hl?IDDy*yRVVGwbrs?9RQkQpf)kkG54&Qp zE%F$&b^TIaUVErD)t^q+)DpJ{=VX>2hhx*oA69BKs zzg_7`7o6v4r~m=fU3MAF3}V7X=ge@y!PFX(eDUIH((?~=B;JV&>V8u@?KWx`8-)N| zD4klWTxjx}tJ>h^#NLypExpG5=H5L}LA^D40V6JNf&RXj{3mH(vMedzi;sV4uEK(x z>m3_3^w_X)qBUU+qe@RDmUcaAj{a;&({>9G(c!-!c8Ch}(uB7LbyOtYDx9)s3gnJb zR5T9-tUt4r37v6{eH=NM|2MPMDf@HBE?%5sB$3R}X4!RDZrFTVlnCn#{nPcina8GT zp}5t3+J!%3VeO}SM=sF$i_WVx@m`hjz($rT5wC5I)#+(^W!zz22>|!6xo6w8YsZ8Z zS4Fw4T#54R*Ya{2b?>!BovL)7N}?G-#uTxT^EHGjr>YN)*Yq<-GMaQ8dV8F9^gVmB z(prd>)_*vJrY1f!P_wZ7czW~1u67M2l2&_I&RfJzIuH)_t*y#+Aunb%KW=;CpNo}i zPVC0vilYm7a(j2>K{Q)=4_1=2^-%S{!WHMRIZ?(Lu^W53q9?;bJ;sS+%DL5Xi!j5# z-N3y79Y3jvfVThHe1NkxQXeoqaRtNji2KUWi8`VDdH=r5U_&Wtzk=|f42GI^X*f(c z9Cdv}oSSZ3wpHX0#2NZRK4+<>0(KP9F6dsTs(nJSFMjdC9K6i~+SoM_Q;?Vd^RCz4 zeFkWAmrpNl08RQdFt|Cpcgtz6muCeIUiow+Vp}WH2Y)5GGHxQy&bR|%{%K;X&d7(D zwie)?(D-Oz?xgZZ{60xZ2tM64)cDi$+w+Z;XToQ72nUdxzAATx8ahp`K8(XQahm>i z3s8pA=x@gzf6Tw)Tc7GlFX&0I+5!5O_Mqx{HNZ{Cr0K0|U*^xp$T?75o>%p{-;ELG za6Dn)o!B8><^s5l3oIMp^ZP1_$9nG9l3SyERV*+>07__-0LTMN=UfYpe*Y0t2ynE0 zRXRFxAuAuSAyOqXN2+fUu2gEOA>)P)T~c}0Xe44v*?SFYQotNjfNIwESobPq5*jO2 z6bMs#Gep&g{5i7wXTRMdHD%pP3{en6BnwHKBqE{(EWTw*X1CZ&S&tqGbk1>25v5E9 zRB+6b)&>Mf1RqC|GE&sEbYaiE5Eky+pKL}_+Dpi-?j19iKS34tla=^5j5_AQeGSB1 zF5}B&b4mCrjx5hd5GctRoTLH>gz|Hw`Pyv(SS3mSq1Yr@bUH4F{BLYx=|JI(%Kmwz z@~FXzr_s8%^xZp{CD97QKZT8?yPpT*qg{)=p!d(Q8}^i`9RJJ76?TGu*sgRnR5+kI zDqI~^RqmoR{NgS*m41hJn19DCMTnuRt*5)G_Hfe#a1?nk?!sZRiJhJ`hxCl>Axt&J z1NGVL?S@9(S=s3kgcG@A)Y}2t4pf`P$|C&;97A#2QM*Bh<%i^`4m?l9=e9uxEgjr4 zDJQ$HqP=GCnAaEPG4|)kHr=d-cF_OBSCW$gnK^Nysyu4QkANkfFPnIMTmO=k7U9ob zHTy1{jOH*J8pH;F{@gv5D$*k;h2<_!AI#-j-VK7`U7qmvlm}QX&s9Sx9v2rUux0qV zWv62i-DylQM$l|#=GIYN?cu;5p&q3dL7M(b*7cs;wvBoTlg=Hsysk_J7NqL6s>sS~ z4LhzeT~pbn-~O^%_erEIhETNnBV$+-s6*kjON&qWQ38VA3#2^d+ZF_GueDsSJ^9RR z3y!{zA!`HY-PyN-?C09*GWtzbl`Tp7{D6#b{|i{Di;Qk`&xQf|wQOdChzV>bJ9eEB zbUFG^ryxpz;A4FJq&bpXC6D}_;ped!1Kv#)JEPxI*Q+j32OoSDRi>o296aeEn-6*m zw^OuS0LxjtaA8$0nU5tkUzPys-)6^F7q%pM_MwMY#chr(k?>lTQkhGheoxEuj>GZ-LkYcHv`s)xR1UD;sZw;OER&P@Kqd1sKUsH%If%ZTsdG^ zC9}OXKQR!t7`jZ?ZiE7P0Sar>zC3Y~L-xboi>bL7Dy5R8%kJBA=mxa&;A}VG0&cx2gPiznHq;EG`L;w9Z>@9S#(dRhVoE%w80=o|$yvXQ z)7x5vGOj+?x3%+FI8EeVos-|AXf*^iY5>7S^m2%gUq!J>-nZ-h*eMzPjz$;0JDXlD zwh6NI^@e`fpI0Rm04GgfJqIQ+9MARI0^@*(RXM$iIbTwuEWR(`S z+JGBD#*mzD3QSX!UmwTk6&^c&DuK}<>vjU77xbI{C&ctvG#?)W1puduwq!G?+2dY zjBLpql~#_*DF1^|Ht(Tr%(25cl*EGO6G|YA#;F*{zLIjWmzP>Yd5;u#Y|?a&X~c- zxm}!gR{)aZo>I8!qy6a2oGmtpjUibNb$zCs5#DjmyZSoWw> zc+H8W2@8lghDxby#m3`*(W10T+(2@7BxE9ay{M=zsy;k-^KN#dHc2Gkn=P?+&FYqx zrBigs^V46Ha@Bm;IK)=OUy?3S5J@14(uP!@!6W5-r&BFSq1UCMmn~w0)UtJ+%i{@X z9(>{;|D#U{tMRu#>p75oWHu3>nb{IY(X}lDK2P`*oyJd?Fsln^c1u7EOmei%U0v{01V506P4J8&KZm6Q% zLjU*cwH3bHvYRsK<2hOx!kptd=+y~Ili~9`zW?5Sdi{$8KCf>*eta)-%0Q)E>xeg# z1mhRG{fb=6{-LK}A@H%p^&P0l9)=b0D#LzaB;qyeDIZh(Y`t=)lefwms@SQWKzrIL zErl4j#>$=km$+VOi2nO}g$JxhPN3+YVVWjOwZsU20qKp#njLd%H(e8=$&Fj#q?_`A62|+BjuyU@v0k? zuWHYX4pY3U?1su${eN7qI8ZDBMCL2;E7|pQJ$Oc!S@T#XttUPrk z`v+O}kXP2z8LIB0t9az5JaT6;!^+3ub;c?mNA@%25m2AkVF!o_md(GR66F!&vrqXr zo$&L=DvzN5zFs*Tz6{4E<#3qsu;$8{7uSy)R1&waFV&ba^4D=K=GVs<>^`eFaV!B! zZz=IbF#&UaoslS(->rY&iAV5@R?0hezn-$!=$|NVO9 zc#r@L{%1ToP0-V@{X>H~RvN)0JRWExu~4M;CEj~hulLzGo!rCr-j5f4!P^=F+g=`` zrRp;mCgQZ5yu&8nwMZ@|JitYNBa5ZSur z1b;JXryN%0B64v|TNT6=@-Iw4VE%gc?cf08d}ncT-n-XKM#q2)w6L8dN;OJVlG;Y& zK)JxrLIDe=Ex%&~{n=Wa2Mwk41mh$m79QDZ1Eq0L(idarO$|ozE}XIG>cnv<0-=E& zTJ7z9ZQx}dR6J_k-pW&EEl#j2Bs{JDuBQ5uuQPi}IX4`aUTe;`>>+wbTh@e5RYv+m zc8Nc}JmC}-45i}Zu{nm`6MXrf+LDH|pM~W|O!AK$))hFM#P-6z$2Ghwdlr6$S8aFF z-Utu?v8H3!H#)#NgsqON%K>`qj|sKMsY`m!kS~i}jbjYqQUOUqNV)DrsK&pPQ@0V3s_EtTg zXm4-nnhC+Nf5dbTm+JWJn>y#{t~nR&7EfN;{930zy9=CLc3B$4m`*ct9X(ooSmGxC z@E3K@H1g@*^>$Tt{~>Q~q~C8iX79_gj}LqPePFqJ`kMpk1Ik`_nn)yu_!4eSm&+f5 z9h%`fx^D=ci98{ z`wJ$*W!wiLjG|e27LZ?z*7DIU>^VZ7{NwLoI;u3847QB4KS>;~_}nMK?AB`4&+(S> zcr&|(Y*yHK+_5zs=&?1cP@eDSGBHd8w;q;}h{Ro-RmJx(i~;707X7YxajVhPb5N_a z!t{q!W9UW($a};Kuw2C#8UK#F&yvjWI=}v07eNW^Cm-*qPSi;fecV_1%=zE$I>Vv4 z36w*T4EzxHE-xkT_U$bL!`6wH!iO?!is0p7<+tAkTE*e_D)#=aBc7h5OMp2{QxFBq zcHSGT^)$Y&ed-GH(;fC61rn6)z_c9%=mT3bB{2w)6iM~hLsO`ezC<&DAAMtW-q$%a z2WaC7BHKxM)zJ3Vez;t3MJR1_hrkcK+OK=BUYSpx2q8|yeFSTgBukt0?K7!`;Prpv_Mlq5D#KVK61p51r8Z#zB!*tdJ%m>6h^zC?MWK)&{1;Qqe zz4Xa4_o1_)rdplCAd(kj4-U+}d-qhYg<}YRaR!0y7U+o9 zr(IqCzI%5uon+z|;ew9nV(98R!LkcJ5!il#k_%Al^9bc&*QZq!q<8AI_Ec{6zTVlu zpp@bt067Ai#n4f~{JvgoGUS9qqTTnCety^F6`m*n1hySON1NxA#L-iGtno^KXwc;N z1rJN1kzaCs?o&=v)Ey5Uy>h9jf`3dUMAoT7pte;@m!3X%E@azpggKPBabD7(BsS@b zJyLa2vy*mBTK7)7cI_3EwEaBB;Qh1~KS7}$2d{}y{?OtP=7?~WAl@{xU{rj|_ zrO1#;+EE=3ci&J~HypaOsC=dDo~nJCtF2#ul_)M!0DU)zVqtEUe$?sR`wUB#IF2l6NHHPReZhy)DGdJmZ-HHspCD|# z#PX+^4MhgjjDLq*oHgXDC@QAME-j78<>alaT$HO4L(1k7>yU<56e=+b>FXfeCa7o5 z3tjsFWezW=;fS2EvaLWRZ{5q~ zn_{ZH1XC22@`{#^Ai%q%0A}%cw9pm(Zc!A+mtmtKz*7l>l(IW!?Giv3GQmTZzut;q zFw{vu;qm0qcL6C9kV+Ii&M$j)YeUT+jDIyKUc`;34z(rT1}HAy`RgwWOUr%84buh# zrVF#Me*OBGhMMNT751)IZzJz8p`OGlbMV0;wwJE1E}fAg>W}Y#PolXPNbd8qVH9?? zR#(><{OsI<-Jcy;J6X<#JVOm=Vq_jFScpw7Fx}7&2ls=tI(Xri;r(Qbp95 z6;&V*L>(?0sptmtf$GT;P!720N%Qu?57#hbdMt)~udEzh?*O$T!;WM�$iBWW|CU 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 zanoÑU6ii&Jm4((DYb9fGoB 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 diff --git a/versioned_docs/version-4.2/apis/core/navigation/_index/assignmentmenu.png b/versioned_docs/version-4.2/apis/core/navigation/_index/assignmentmenu.png deleted file mode 100644 index 94abeec2bd4db312c05cbe9dbfcce2f00b74dae2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13625 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 MRgnavigation` - The main navigation structure, it will contain items that will allow the user to browse to the other available pages -- `$PAGE->settingsnav` - The settings navigation structure contains items that will allow the user to edit settings -- `$PAGE->navbar` - A special structure for page breadcrumbs - -A conceptual view of the information architecture that sits behind the navigation tree is here: - -![Information Architecture](./_index/Moodle-IA.png) - -This diagram represents the major entities and how they are related to each other. Examples are given of the type of functions available on each kind of entity. - -## What the navigation is not - -The navigation is **NOT** the navigation block or the settings block! These two blocks were created to display the navigation structure. The navigation block looks at `$PAGE->navigation`, and the settings block looks at `$PAGE->settingsnav`. Both blocks interpret their data into an HTML structure and render it. - -1. The navigation is a back-end structure that is built behind the scenes and has no immediate method of display. -1. The navigation and settings blocks display the back-end navigation structure but add nothing to it at all. - -In a model-view-controller pattern, `$PAGE->navigation`, `$PAGE->settingsnav`, and `$PAGE->navbar` are the models, and the blocks are views. - -The navbar is just the path to the active navigation or settings item. The navbar is not displayed by a block; instead it is added into the theme's layout files and displayed by the core renderer. - -## How the navigation works - -The main navigation structure can be accessed through `$PAGE->navigation`. The navigation and settings are contextual in that they will relate to the page that the user is viewing. This is determined by other `$PAGE` object properties: - -- `$PAGE->context` is a Moodle context that immediately outlines the nature of the page the user is viewing. -- `$PAGE->course` is the course the user is viewing. This is essential if the context is CONTEXT_COURSE or anything within it. However, it is also useful in other contexts such as CONTEXT_USER. -- `$PAGE->cm` is the course module instance. This is essential if the context is CONTEXT_MODULE. -- `$PAGE->url` is used to match the active navigation item. - -Nearly every page sets `$PAGE->url` through a call to `$PAGE->set_url()` however not many explicitly set the context, course, or cm. When you call `require_login()` with a course or context_module, it automatically calls the following: - -```php title="Set up the global course" -if ($cm) { - $PAGE->set_cm($cm, $course); // sets up global $COURSE -} else { - $PAGE->set_course($course);// sets up global $COURSE -``` - -A page will only be required to explicitly set a context, course, or cm under one of these conditions: - -1. `require_login` is NOT being called correctly -1. The page is using CONTEXT_SYSTEM, CONTEXT_COURSECAT, or CONTEXT_USER (call `$PAGE->set_context()`). -1. The page is using a course or cm but it is also using one of the above contexts (call `$PAGE->set_course()` or `$PAGE->set_cm()`). - -:::important - -The navigation structure cannot be generated before the `$PAGE` object is configured. It is only generated when it is first used, either when something tries to access the structure or when code tries to add to it. The navigation is initialised in a specific order: - -1. Main navigation structure -1. Settings navigation -1. Navbar (does not need to be generated because of its simple contents and rendering) - -::: - -## Extending the navigation - -### Code extension - -This method of extending is when the code arbitrarily extends the navigation during its execution. Extending the navigation through this means allows you to extend the navigation anywhere easily, however it will only be shown on pages where your extending code gets called (you should probably put it in a function within `lib.php`). - -Navigation extensions that apply all the time (even when not on pages including your code) can be made by putting them in your plugin's settings.php file. - -These examples are taken from the [General Developer Forum: Moodle 2 - how to set up breadcrumbs for a module page](http://moodle.org/mod/forum/discuss.php?d=152391). It has further information that is well worth reading. - -#### Navigation - -##### Extending the main navigation structure - -```php -$previewnode = $PAGE->navigation->add( - get_string('preview'), - new moodle_url('/a/link/if/you/want/one.php'), - navigation_node::TYPE_CONTAINER -); -$thingnode = $previewnode->add( - get_string('thingname'), - new moodle_url('/a/link/if/you/want/one.php') -); -$thingnode->make_active(); -``` - -The above lines of code adds a preview node to the bottom of the navigation and then adds a thing node to the preview node (adding a leaf to our tree). -The final line of code makes the thing node active so that the navbar finds it however if the URL you give it is the same as the url you set for the page it will automatically be marked active and you won't need this call. - -##### Extending the navigation for the course - -This example assumes that you already know the course ID and have already called `require_login()`. This loads the navigation data for the specified course. - -```php title="Extending the navigation for the course." -$coursenode = $PAGE->navigation->find($courseid, navigation_node::TYPE_COURSE); -$thingnode = $coursenode->add( - get_string('thingname'), - new moodle_url('/a/link/if/you/want/one.php') -); -$thingnode->make_active(); -``` - -The first line of this code finds the course node using a combination of the ID of the course, and the node type `navigation_node::TYPE_COURSE`. - -This example relies on the navigation API to generate the navigation up to the course, and the example then adds to that structure. - -:::note - -Moodle loads plugins in alphabetical order. This means that plugin_b can find a node added by plugin_a but not the other way around. However, plugins must abide by the [Component communication principles](/general/development/policies/component-communication). - -::: - -#### Settings navigation - -Adding to the settings navigation is very similar to the general navigation, only using the `settingsnav` property of the `$PAGE` API. - -```php -$settingnode = $PAGE->settingsnav->add( - get_string('setting'), - new moodle_url('/a/link/if/you/want/one.php'), - navigation_node::TYPE_CONTAINER -); -$thingnode = $settingnode->add( - get_string('thingname'), - new moodle_url('/a/link/if/you/want/one.php') -); -$thingnode->make_active(); -``` - -##### Add Settings folder to navigation - -This example adds a settings folder to the navigation API at Site administration / Plugins / Activity modules / Assignment. - -![The structure of the Assignment plugin in the Settings navigation](./_index/assignmentmenu.png) - -An example of adding a navigation folder to a settings.php for a block with a link to the settings page and a external page is bellow. - -```php -// Create a submenu in the block menu. -// This can be found in: -// - blocksettings for block plugins -// - modsettings for activity modules -// - localplugins for Local plugins -// The default menus are defined in admin/settings/plugins.php. -$ADMIN->add( - 'blocksettings', - new admin_category( - 'blocksamplefolder', - get_string('pluginname', 'mod_sample') - ) -); - -// Create settings block. -$settings = new admin_settingpage($section, get_string('settings', 'block_sample')); -if ($ADMIN->fulltree) { - $settings->add( - new admin_setting_configcheckbox( - 'block_sample_checkbox', - get_string('checkbox', 'block_sample'), - get_string('checkboxdescription', 'block_kronoshtml'), - 0 - ) - ); -} - -// This adds the settings link to the folder/submenu. -$ADMIN->add('blocksamplefolder', $settings); - -// This adds a link to an external page. -$ADMIN->add( - 'blocksamplefolder', - new admin_externalpage( - 'block_sample_page', - get_string('externalpage', 'block_sample'), - "{$CFG->wwwroot}/blocks/sample/sample.php" - ) -); - -// Prevent Moodle from adding settings block in standard location. -$settings = null; -``` - -#### Navbar - -The following example extends the navbar navigation. - -```php -$PAGE->navbar->ignore_active(); -$PAGE->navbar->add( - get_string('preview'), - new moodle_url('/a/link/if/you/want/one.php') -); -$PAGE->navbar->add( - get_string('name of thing'), - new moodle_url('/a/link/if/you/want/one.php') -); -``` - -The above code tells the navbar to ignore the automatically detected _active page_ and to instead use what is manually added, at which point we add two items as shown. - -### Plugin Callbacks - -These are specific functions that the navigation looks for and calls if they exist for the plugin, presently only three plugin types can extend the navigation through these call-backs. - -Ideally all entries in "Administration / Site administration" tree should be done via settings.php files but sometimes it may be easier to directly modify the navigation structure created from the admin settings tree (such as when adding links to external pages). - -#### Module - -Modules have two call-back methods, first to extend the navigation, and second to extend the settings. These call-backs get called when ever the user is viewing a page within the module and should only extend the navigation for the module. - -```php -function {modulename}_extend_navigation( - ${modulename}node, - $course, - $module, - $cm -); -function {modulename}_extend_settings_navigation( - $settings, - ${modulename}node -); -``` - -You may be required to add a node in a specified order within the menu navigation menus. To do this you need to examine the node object as given in the respective parameters in the functions above, then find the key of the child node you wish to place the link before. For example, applying the code below will put a direct link to grade report. - -```php -function my_plugin_extend_settings_navigation($settingsnav, $context){ - $addnode = $context->contextlevel === 50; - $addnode = $addnode && has_capability('gradereport/grader:view', $context); - if ($addnode) { - $id = $context->instanceid; - $urltext = get_string('gradereportlink', 'myplugin'); - $url = new moodle_url('/grade/report/grader/index.php',[ - 'id' => $id, - ]); - // Find the course settings node using the 'courseadmin' key. - $coursesettingsnode = $settingsnav->find('courseadmin', null); - $node = $coursesettingsnode->create( - $urltext, - $url, - navigation_node::NODETYPE_LEAF, - null, - 'gradebook', - new pix_icon('i/report', 'grades') - ); - - // Add the new node _before_ the 'gradebooksetup' node. - $coursesettingsnode->add_node($node, 'gradebooksetup'); - } - - // ... -} -``` - -#### Course Formats - -Course formats are able to completely redefine the way in which navigation is generated for a course, as well as this they also have several methods to ensure the navigation is generated correctly. - -#### Course Reports - -By default reports don't add themselves or anything else to the navigation however there is a call-back that can be implemented to allow them to do so. - -#### Local Plugins - -Local plugins have two call-back methods, first to extend the navigation, and second to extend the settings. - -```php -function local_{pluginname}_extend_navigation( - global_navigation $nav -); - -function local_{pluginname}_extend_settings_navigation( - settings_navigation $nav, - context $context -); -``` - -#### Course settings - -Any plugin implementing the following callback in `lib.php` can extend the course settings navigation. - -```php -function _extend_navigation_course( - navigation_node $parentnode, - stdClass $course, - context_course $context -); -``` - -#### User settings - -Any plugin implementing the following callback in `lib.php` can extend the user settings navigation. - -```php -function _extend_navigation_user_settings( - navigation_node $parentnode, - stdClass $user, - context_user $context, - stdClass $course, - context_course $coursecontext -); -``` - -#### Category settings - -Any plugin implementing the following callback in `lib.php` can extend the category settings navigation. - -```php -function _extend_navigation_category_settings( - navigation_node $parentnode, - context_coursecat $context -); -``` - -#### Frontpage settings - -Any plugin implementing the following callback in `lib.php` can extend the frontpage settings navigation. - -```php -function _extend_navigation_frontpage( - navigation_node $parentnode, - stdClass $course, - context_course $context -); -``` - -#### User profile - -Any plugin implementing the following callback in `lib.php` can extend the user profile navigation. - -```php -function _extend_navigation_user( - navigation_node $parentnode, - stdClass $user, - context_user $context, - stdClass $course, - context_course $coursecontext -); -``` - -### Boost theme - -The navigation API is specifically about allowing the manipulation of nodes in an in-memory tree structure that is used as the basis of building navigation components in the page. The navigation and settings blocks are 2 examples of such components and the flat navigation and settings menus in the Boost theme are another example. The navigation component itself can decide to show all or only part of the navigation tree in order to not overwhelm the user viewing the page. Whether a node is actually displayed depends on where in the tree the node was added, what is the current page in the navigation tree, and the specific navigation components that are used to provide navigation functionality in the current theme. - -:::important - -If you are testing in the Boost theme - all nodes that are added to settings tree are displayed in the course or activity settings menu. This is shown as a cog on the front page of the course or activity. - -Only the most important pre-selected nodes are displayed in the flat-navigation drawer in order to provide consistency and avoid overwhelming the user with too many links. - -It is possible, but _not recommended_, for plugins to add nodes to the flat navigation (see [FAQ's and troubleshooting](#faqs-and-troubleshooting) for more information). - -::: - -## FAQ's and troubleshooting - -### **Q.** My page is on the navigation but it doesn't find it? - -The first thing to do here is check the URL you are setting for the page. It should match the URL your page has within the navigation. If it doesn't you have two options, first change your `$PAGE->set_url()` call, or second override the URL the navigation is using to find the active node as shown below: - -```php -navigation_node::override_active_url( - new moodle_url('/your/url/here.php', [ - 'param' => 'value', - ]) -); -``` - -### **Q.** How do I add a node to the "flat" navigation in the Boost theme? - -After creating a node and adding it to the navigation tree - you can set the property `showinflatnavigation` to true in order for this node to be displayed in the flat navigation. - -```php -$node = navigation_node::create(...); -$node->showinflatnavigation = true; -$navigation->add_node($node); -``` - -:::danger - -This is highly discouraged because the number of nodes in this flat navigation has been deliberately restricted to a very small number of the most important links that are applicable to all user roles. - -Adding more links to this menu will make it harder to use, inconsistent for different users, and inconsistent for different sites. - -Consider carefully if you really need to fill an additional 230x44 pixels of every single page in Moodle for every single user with a link to your thing. There are many other places to include links to your thing and most are automatically built from the navigation tree without forcing nodes to display in the flat navigation. For example, in the settings menu of a course, profile page, preferences page, reports, and so on. - -::: - -## See also - -- [Core APIs](../../../apis.md) -- [Forum discussion - adding navigation to local plugins](https://moodle.org/mod/forum/discuss.php?d=170325&parent=753095) diff --git a/versioned_docs/version-4.2/apis/core/preference/index.md b/versioned_docs/version-4.2/apis/core/preference/index.md deleted file mode 100644 index b71b7a83fd..0000000000 --- a/versioned_docs/version-4.2/apis/core/preference/index.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Preference API -tags: - - API - - User Preferences - - User ---- - -The Preference API is used for the storage and retrieval of user preferences. These preferences are stored in the database for users with an account, however for guests or users who are not currently logged in the preferences are stored in the Session. - -All of these functions operate on the current user by default, however you can specify the user you wish to operate on by passing a user ID or a moodle user object to the $user parameter. Normally this is used for state indicators, where it can be as simple as a yes or no, however you can also use it to store more complex user data, such as a serialized PHP object. - -It is considered good practice to abstain from storing default values as a user preference as this creates a lot of redundancy. Instead you should apply the default value at the code level if there is no stored value for a given preference. - -## Primary functions - -### get_user_preferences() - -This function can be used to fetch the value of a requested (via $name) preference, or if it doesn't exist the value given in the $default parameter will be returned. If you do not specify a $name then all preferences will be returned. - -```php -get_user_preferences( - string $name = null, - mixed $default = null, - stdClass|int|null $user = null -): mixed; -``` - -### set_user_preference() - -This function can be used to set the value of a preference named $name. - -```php -set_user_preference( - string $name, - mixed $value, - stdClass|int|null $user = null -): bool; -``` - -### set_user_preferences() - -This function takes an array or preferences containing the name and value for each preference. For each element in the array this function passes the keys and values of each element as the $name and $value parameters (respectively) in calls to `set_user_preferences()`. - -```php -set_user_preferences( - array $preferences, - stdClass|int|null $user = null -): bool; -``` - -### unset_user_preference() - -This deletes the requested preference, specified by the $name parameter. - -```php -unset_user_preference( - string $name, - stdClass|int|null $user = null -): bool; -``` - -## Example usage of the API - -```php title="Set a preference and then retrieve it" -set_user_preference('foo_nameformat', 'long'); - -// Returns the string - "long" -get_user_preferences('foo_nameformat'); -``` - -```php title="Set another preference and then retrieve all preferences" -set_user_preference('foo_showavatars', 'no'); - -// returns [ -// foo_nameformat => "long", -// foo_showavatars => "no", -// ]; -get_user_preferences(); -``` - -```php title="Add an array of preferences and change foo_nameformat to short" -$preferences = [ - 'foo_displaynum' => '100', - 'foo_nameformat' => 'short', -]; - -set_user_preferences($preferences); - -// returns [ -// foo_nameformat => "short", -// foo_showavatars => "no", -// foo_displaynum => "100", -// ]; -get_user_preferences(); -``` - -```php title="Delete a preference" -unset_user_preference('foo_showavatars'); - -// returns [ -// foo_nameformat => "short", -// foo_displaynum => "yes", -// ]; -get_user_preferences(); -``` diff --git a/versioned_docs/version-4.2/apis/core/user/index.md b/versioned_docs/version-4.2/apis/core/user/index.md deleted file mode 100644 index 3aa64cb00c..0000000000 --- a/versioned_docs/version-4.2/apis/core/user/index.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: User-related APIs -tags: - - User -documentationDraft: true ---- - -This is a collection of miscellaneous APIs that can help with doing things with lists of users. - -:::note - -Please note that, in many cases, more specific APIs may be more appropriate, for example: - -- [Access API](../../subsystems/access.md) -- [Groups API](../../subsystems/group/index.md) -- [Enrolment API](../../subsystems/enrol.md) - -::: - -## User field display - -The [User fields](https://docs.moodle.org/dev/User_fields) class is mainly used when displaying tables of data about users. It indicates which extra fields (e.g. email) should be displayed in the current context based on the permissions of the current user. It also provides ways to get the necessary data from a query, and to obtain other generally-useful fields for user names and pictures. - -## User fields definition - -To guarantee the sanity of the data inserted into Moodle and avoid security bugs, new user fields definition methods have been created for use in Moodle 3.1 onwards. The purpose of these new methods is to create a central point of user fields data validation and guarantee all data inserted into Moodle will be cleaned against the correct parameter type. Another goal of this new API is to create consistency across Moodle core and avoid different parameter validations for the same user fields. For now on, user data must validate against the user field, not using clean_param() directly. - -### `$propertiescache` - -Cached information of each user field and its attributes filled by the fill_properties_cache. - -### `fill_properties_cache()` - -The main method of the user definition is to keep the definition of each user field and its properties. It verifies if the **`core_user::$propertiescache`** is already filled and caches all user fields attributes into this same attribute. -Each field matches the exact field name on the user table. That said, every new field added to the user table should be added to fill_properties_cache $fields array, otherwise it won't be validated or cleaned. -Each field has four possible properties, being choices and default optional: - -- **`null`** - Whether the field is NULL or NOT_NULL, it SHOULD NOT be used as form validation, as many fields in the user table have NOT_NULL property but have the default value as (``). -- **`type`** - The expected parameter type (PARAM_*) to be used as validation and sanitizing. -- **`choices`** - A list of accepted values of that field. For example the list of the available countries, timezones, calendar type etc. -- **`default`** - The default value in case the user field didn't pass the validation or cleaned and we must set the default value. For example if the user country is invalid and it is not in the list of choices, set $CFG->country. - -### `validate()` - -A static method to validate user fields, accepts an array or the user object as parameter, validate each parameter individually and can return true if all user data is correct or an array of validation errors. The purpose of this method is to just validate the user data, it won't do any cleaning of the data. - -### `clean_data()` - -A static method that has the purpose of clean the user data and return the same user array/object. It receives an array with user data or a user object as parameter and it checks if the data is in the list of choices and if the property has a default value and clean the data if the user object doesn't have a choices property. -It will display a debugging message if one the operations above has problems. - -### `clean_field()` - -A static method to clean a single user field. It has two parameters, the data to be cleaned and its user field. The behaviour of the method is similar to the clean_data. It will do the validations and cleaning and can display a debug message if an error has been found. It returns the cleaned data. - -### `get_property_type()` - -A helper method to get the type of the property. It receives the user field name as parameter and if it doesn't exist will throw an exception. If the property has been found, it will return its type. - -### `get_property_null()` - -A helper method to get the null property of the user field. It receives the user field name as parameter and if it doesn't exist it throws an exception. If the property has been found, it will return the null value. - -### `get_property_choices()` - -A helper method to get the list of choices of a user field. It receives the user field name as parameter and if it doesn't exist will throw an exception. If the property has been found, it will return the list of accepted values. - -### `get_property_default()` - -A helper method to get the default value of a property. It receives the user field name as parameter and if it doesn't exist or if it doesn't have a default attribute will throw an exception. If the property has been found, it will return its default value. - -## User selector - -The base class `user_selector_base` defined in `user/selector/lib.php`, which you can subclass to make a widget that lets you select users in an AJAX-y way. It is used, for example, on the Add group members page. The best way to learn how to use it is to search the code for other users, and see how they work. The base class also has good PHPdoc comments. - -## Sorting lists of users - -When you fetch a list of users from the database, they should always be sorted consistently, by using the `users_order_by_sql` function to generate the order-by clause. Again, the best way to see how that works is to search the code for existing uses. - -## See also - -- [Core APIs](../../../apis.md) -- [Access API](../../subsystems/access.md) -- [Groups API](../../subsystems/group/index.md) -- [Enrolment API](../../subsystems/enrol.md) diff --git a/versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.mdx b/versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.mdx deleted file mode 100644 index 0b614a3177..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.mdx +++ /dev/null @@ -1,13 +0,0 @@ - - - -The `classes/scanner.php` class must be defined in the correct namespace for your plugin, and must extend the `\core\antivirus\scanner` class. - -It is responsible for implementing the interface between Moodle and the antivirus scanning tool. - -The following methods are compulsory: - -- `is_configured(): bool` - returns true, if this antivirus plugin is configured. -- `scan_file($file, $filename, $deleteinfected): void` - performs the **$file** scanning using antivirus functionality, using **$filename** as filename string in any reporting, deletes infected file if **$deleteinfected** is true. - -If a virus is found the `scan_file()` function _must_ throw an instance of the `\core\antivirus\scanner_exception` type. diff --git a/versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.tsx b/versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.tsx deleted file mode 100644 index 167d78e6ff..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/antivirus/_files/scanner-php.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../../../_utils'; -import type { Props } from '../../../../_utils'; -import DefaultDescription from './scanner-php.mdx'; - -const defaultExample = ` -namespace antivirus_scanmyfile; - -class scanner extends \\core\\antivirus\\scanner { - - public function is_configured() { - // Note: You will likely want a more specific check. - // This example just checks whether configuration exists. - return (bool) $this->get_config('pathtoscanner'); - } - - public function scan_file($file, $filename, $deleteinfected) { - if (!is_readable($file)) { - // This should not happen. - debugging('File is not readable.'); - return; - } - - // Execute the scan using the fictitious scanmyfile tool. - // In this case the tool returns: - // - 0 if no virus is found - // - 1 if a virus was found - // - [int] on error - $return = $this->scan_file_using_scanmyfile_scanner_tool($file); - - if ($return == 0) { - // Perfect, no problem found, file is clean. - return; - } else if ($return == 1) { - // Infection found. - if ($deleteinfected) { - unlink($file); - } - throw new \\core\\antivirus\\scanner_exception( - 'virusfounduser', - '', - ['filename' => $filename] - ); - } else { - // Unknown problem. - debugging('Error occurred during file scanning.'); - return; - } - } - - public function scan_file_using_scanmyfile_scanner_tool($file): int { - // Scanning routine using antivirus own tool goes here.. - // You should choose a return value appropriate for your tool. - // These must match the expected values in the scan_file() function. - // In this example the following are returned: - // - 0: No virus found - // - 1: Virus found - return 0; - } -} -`; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx b/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx deleted file mode 100644 index 2b457d8e21..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Antivirus plugins -tags: - - Plugins - - Antivirus -description: Integrate your preferred Antivirus tool to with Moodle to automatically check new file uploads. ---- - - - - - - -import { - Lang, - VersionPHP, - SettingsPHP, -} from '../../_files'; -import ScannerPHP from './_files/scanner-php'; - -Moodle supports automatic virus scanning of files as they are uploaded by users. To enable this developers can write an antivirus plugin, which acts as a bridge between Moodle and the antivirus tooling. - -A plugin to support the Open Source [ClamAV](https://www.clamav.net/) antivirus engine is included with Moodle core as standard. - -## File structure - -Antivirus plugins are located in the `/lib/antivirus` directory. - -Each plugin is in a separate subdirectory and consists of a number of _mandatory files_ and any other files the developer is going to use. - -
    - View an example directory layout for the `antivirus_scanmyfile` plugin. - -```console - lib/antivirus/scanmyfile/ - |-- classes - | `-- scanner.php - |-- db - | `-- upgrade.php - |-- lang - | `-- en - | `-- antivirus_scanmyfile.php - |-- settings.php - |-- tests - | `-- scanner_test.php - `-- version.php -``` - -
    - -Some of the important files for the antivirus plugintype are described below. See the [common plugin files](../commonfiles) documentation for details of other files which may be useful in your plugin. - -### version.php - - - -### settings.php - -export const settingsExample = ` -if ($ADMIN->fulltree) { - $settings->add( - new admin_setting_configexecutable( - 'antivirus_scanmyfile/pathtoscanner',", - new lang_string('pathtoscanner', 'antivirus_scanmyfile'),", - new lang_string('configpathtoscanner', 'antivirus_scanmyfile'),", - ''", - ) - ); -} -`; - - - -### lang/en/antivirus_scanmyfile.php - -export const langExample = ` - $string['pluginname']= 'ScanMyFile antivirus'; - $string['pathtoscanner'] = 'Path to scanner'; - $string['configpathtoscanner'] = 'Define full path to scanner'; -`; - - - -### classes/scanner.php - - - -### tests/scanner_test.php (optional) - -Writing unit tests is strongly encouraged as it can help to identify bugs, or changes in behaviour, that you had not anticipated. - -Since antivirus plugins typically rely on an external dependency, it is usually a good idea to replace the real component with a test "double". You can see an example of this in Moodle in the [antivirus_clamav unit tests](https://github.com/moodle/moodle/blob/81407f18ecff1fded66a9d8bdc25bbf9d8ccd5ca/lib/antivirus/clamav/tests/scanner_test.php#L45-L56). - -The PHPUnit Manual contains a dedicated [section on Test Doubles](https://docs.phpunit.de/en/9.6/test-doubles.html). - -You may also wish to include some tests of the real system to ensure that upgrades to the Antivirus software do not break your plugin. diff --git a/versioned_docs/version-4.2/apis/plugintypes/assign/_files/submission_settings.php b/versioned_docs/version-4.2/apis/plugintypes/assign/_files/submission_settings.php deleted file mode 100644 index 60e7a7248f..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/assign/_files/submission_settings.php +++ /dev/null @@ -1,22 +0,0 @@ -// Note: This is on by default. -$settings->add( - new admin_setting_configcheckbox('assignsubmission_file/default', - new lang_string('default', 'assignsubmission_file'), - new lang_string('default_help', 'assignsubmission_file'), - 1 - ) -); - -if (isset($CFG->maxbytes)) { - $name = new lang_string('maximumsubmissionsize', 'assignsubmission_file'); - $description = new lang_string('configmaxbytes', 'assignsubmission_file'); - - $element = new admin_setting_configselect( - 'assignsubmission_file/maxbytes', - $name, - $description, - 1048576, - get_max_upload_sizes($CFG->maxbytes) - ); - $settings->add($element); -} diff --git a/versioned_docs/version-4.2/apis/plugintypes/assign/feedback.md b/versioned_docs/version-4.2/apis/plugintypes/assign/feedback.md deleted file mode 100644 index ce7dad1e04..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/assign/feedback.md +++ /dev/null @@ -1,540 +0,0 @@ ---- -title: Assign feedback plugins -tags: - - Assign - - Assignment - - Feedback - - Subplugin -toc_max_heading_level: 4 -description: Assign feedback plugins allow you to define different ways that a teacher can provide feedback to their students. ---- - -import { - SettingsPHP, - LocalLib, -} from '../../_files'; -export const plugintype = 'assignfeedback'; - -An assignment feedback plugin can do many things including providing feedback to students about a submission. The grading interface for the assignment module provides many hooks that allow plugins to add their own entries and participate in the grading workflow. - -:::tip - -For a good reference implementation, see the [file](https://github.com/moodle/moodle/tree/main/mod/assign/feedback/file) feedback plugin included with core because it uses most of the features of feedback plugins. - -::: - -## File structure - -Assignment Feedback plugins are located in the `/mod/assign/feedback` directory. A plugin should not include any custom files outside of it's own plugin folder. - -:::important Plugin naming - -The plugin name should be no longer than 13 characters - this is because the database tables for a submission plugin must be prefixed with `assignfeedback_[pluginname]` (15 chars + X) and the table names can be no longer than 28 chars due to a limitation with Oracle. - -If a plugin requires multiple database tables, the plugin name will need to be shorter to allow different table names to fit under the 28 character limit. - -::: - -Each plugin is in a separate subdirectory and consists of a number of _mandatory files_ and any other files the developer is going to use. - -:::important - -Some of the important files are described below. See the [common plugin files](../../commonfiles/index.mdx) documentation for details of other files which may be useful in your plugin. - -::: - -
    - View an example directory layout for the `assignfeedback_file` plugin. - -```console -mod/assign/feedback/file -├── backup -│   └── moodle2 -│   ├── backup_assignfeedback_file_subplugin.class.php -│   └── restore_assignfeedback_file_subplugin.class.php -├── classes -│   └── privacy -│   └── provider.php -├── db -│   ├── access.php -│   ├── install.php -│   ├── install.xml -│   └── upgrade.php -├── importzipform.php -├── importziplib.php -├── lang -│   └── en -│   └── assignfeedback_file.php -├── lib.php -├── locallib.php -├── settings.php -├── uploadzipform.php -└── version.php -``` - -
    - -### settings.php - - - - -export const settingsExample = ` -$settings->add( - new admin_setting_configcheckbox( - 'assignfeedback_file/default', - new lang_string('default', 'assignfeedback_file'), - new lang_string('default_help', 'assignfeedback_file'), - 0 - ) -); -`; - -export const settingsExtra = ` -All feedback plugins should include one setting named 'default' to indicate if the plugin should be enabled by default when creating a new assignment. -`; - - - - - -### locallib.php - - - - - - - -This is where all the functionality for this plugin is defined. We will step through this file and describe each part as we go. - -```php -class assign_feedback_file extends assign_feedback_plugin { -``` - -#### get_name() - -All feedback plugins MUST define a class with the component name of the plugin that extends assign_feedback_plugin. - -```php -public function get_name() { - return get_string('file', 'assignfeedback_file'); -} -``` - -This function is abstract in the parent class (feedback_plugin) and must be defined in your new plugin. Use the language strings to make your plugin translatable. - -#### get_settings() - -```php -public function get_settings(MoodleQuickForm $mform) { - $mform->addElement( - 'assignfeedback_file_fileextensions', - get_string('allowedfileextensions', 'assignfeedback_file') - ); - $mform->setType('assignfeedback_file_fileextensions', PARAM_FILE); -} -``` - -This function is called when building the settings page for the assignment. It allows this plugin to add a list of settings to the form. Notice that the settings should be prefixed by the plugin name which is good practice to avoid conflicts with other plugins. (None of the core feedback plugins have any instance settings, so this example is fictional). - -#### save_settings() - -```php -public function save_settings(stdClass $data) { - $this->set_config('allowedfileextensions', $data->allowedfileextensions); - return true; -} -``` - -This function is called when the assignment settings page is submitted, either for a new assignment or when editing an existing one. For settings specific to a single instance of the assignment you can use the assign_plugin::set_config function shown here to save key/value pairs against this assignment instance for this plugin. - -#### get_form_elements_for_user() - -```php -public function get_form_elements_for_user( - $grade, - MoodleQuickForm $mform, - stdClass $data, - $userid -) { - $fileoptions = $this->get_file_options(); - $gradeid = $grade ? $grade->id : 0; - $elementname = "files_{$userid}"; - - $data = file_prepare_standard_filemanager( - $data, - $elementname, - $fileoptions, - $this->assignment->get_context(), - 'assignfeedback_file', - ASSIGNFEEDBACK_FILE_FILEAREA, - $gradeid - ); - $mform->addElement( - 'filemanager', - "{$elementname}_filemanager", - html_writer::tag( - 'span', - $this->get_name(), - ['class' => 'accesshide'] - ), - null, - $fileoptions - ); - - return true; -} -``` - -This function is called when building the feedback form. It functions identically to the get_settings function except that the grade object is available (if there is a grade) to associate the settings with a single grade attempt. This example also shows how to use a filemanager within a feedback plugin. The function must return true if it has modified the form otherwise the assignment will not include a header for this plugin. Notice there is an older version of this function "get_form_elements" which does not accept a userid as a parameter - this version is less useful - not recommended. - -#### is_feedback_modified() - -```php -public function is_feedback_modified(stdClass $grade, stdClass $data) { - $commenttext = ''; - if ($grade) { - $feedbackcomments = $this->get_feedback_comments($grade->id); - if ($feedbackcomments) { - $commenttext = $feedbackcomments->commenttext; - } - } - - if ($commenttext == $data->assignfeedbackcomments_editor[]('text')) { - return false; - } else { - return true; - } -} -``` - -This function is called before feedback is saved. If feedback has not been modified then the save() method is not called. This function takes the grade object and submitted data from the grading form. In this example we are comparing the existing text comments made with the new ones. This function must return a boolean; True if the feedback has been modified; False if there has been no modification made. If this method is not overwritten then it will default to returning True. - -#### save() - -```php -public function save(stdClass $grade, stdClass $data) { - global $DB; - - $fileoptions = $this->get_file_options(); - - $userid = $grade->userid; - $elementname = 'files_' . $userid; - - $data = file_postupdate_standard_filemanager( - $data, - $elementname, - $fileoptions, - $this->assignment->get_context(), - 'assignfeedback_file', - ASSIGNFEEDBACK_FILE_FILEAREA, - $grade->id - ); - - $filefeedback = $this->get_file_feedback($grade->id); - if ($filefeedback) { - $filefeedback->numfiles = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA); - return $DB->update_record('assignfeedback_file', $filefeedback); - } else { - $filefeedback = new stdClass(); - $filefeedback->numfiles = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA); - $filefeedback->grade = $grade->id; - $filefeedback->assignment = $this->assignment->get_instance()->id; - return $DB->insert_record('assignfeedback_file', $filefeedback) > 0; - } -} -``` - -This function is called to save a graders feedback. The parameters are the grade object and the data from the feedback form. This example calls `file_postupdate_standard_filemanager` to copy the files from the draft file area to the filearea for this feedback. It then records the number of files in the plugin specific `assignfeedback_file` table. - -#### view_summary() - -```php -public function view_summary(stdClass $grade, & $showviewlink) { - $count = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA); - // show a view all link if the number of files is over this limit - $showviewlink = $count > ASSIGNFEEDBACK_FILE_MAXSUMMARYFILES; - - if ($count <= ASSIGNFEEDBACK_FILE_MAXSUMMARYFILES) { - return $this->assignment->render_area_files( - 'assignfeedback_file', - ASSIGNFEEDBACK_FILE_FILEAREA, - $grade->id - ); - } else { - return get_string('countfiles', 'assignfeedback_file', $count); - } -} -``` - -This function is called to display a summary of the feedback to both markers and students. It counts the number of files and if it is more that a set number, it only displays a count of how many files are in the feedback - otherwise it uses a helper function to write the entire list of files. This is because we want to keep the summaries really short so they can be displayed in a table. There will be a link to view the full feedback on the submission status page. - -#### view() - -```php -public function view(stdClass $grade) { - return $this->assignment->render_area_files( - 'assignfeedback_file', - ASSIGNFEEDBACK_FILE_FILEAREA, - $grade->id - ); -} -``` - -This function is called to display the entire feedback to both markers and students. In this case it uses the helper function in the assignment class to write the list of files. - -#### can_upgrade() - -```php -public function can_upgrade($type, $version) { - - if (($type == 'upload' || $type == 'uploadsingle') && $version >= 2011112900) { - return true; - } - return false; -} -``` - -This function is used to identify old "Assignment 2.2" subtypes that can be upgraded by this plugin. This plugin supports upgrades from the old "upload" and "uploadsingle" assignment subtypes. - -```php -public function upgrade_settings(context $oldcontext, stdClass $oldassignment, &$log) { - // first upgrade settings (nothing to do) - return true; -} -``` - -This function is called once per assignment instance to upgrade the settings from the old assignment to the new mod_assign. In this case it returns true as there are no settings to upgrade. - -```php -public function upgrade( - context $oldcontext, - stdClass $oldassignment, - stdClass $oldsubmission, - stdClass $grade, - &$log -) { - global $DB; - - // now copy the area files - $this->assignment->copy_area_files_for_upgrade( - $oldcontext->id, - 'mod_assignment', - 'response', - $oldsubmission->id, - // New file area - $this->assignment->get_context()->id, - 'assignfeedback_file', - ASSIGNFEEDBACK_FILE_FILEAREA, - $grade->id - ); - - // now count them! - $filefeedback = new stdClass(); - $filefeedback->numfiles = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA); - $filefeedback->grade = $grade->id; - $filefeedback->assignment = $this->assignment->get_instance()->id; - if (!$DB->insert_record('assignfeedback_file', $filefeedback) > 0) { - $log .= get_string('couldnotconvertgrade', 'mod_assign', $grade->userid); - return false; - } - return true; -} -``` - -This function upgrades a single submission from the old assignment type to the new one. In this case it involves copying all the files from the old filearea to the new one. There is a helper function available in the assignment class for this (Note: the copy will be fast as it is just adding rows to the files table). If this function returns false, the upgrade will be aborted and rolled back. - -#### is_empty() - -```php -public function is_empty(stdClass $submission) { - return $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA) == 0; -} -``` - -If a plugin has no data to show then this function should return true from the `is_empty()` function. This prevents a table row from being added to the feedback summary for this plugin. It is also used to check if a grader has tried to save feedback with no data. - -#### get_file_areas() - -```php -public function get_file_areas() { - return [ASSIGNFEEDBACK_FILE_FILEAREA => $this->get_name()]; -} -``` - -A plugin should implement `get_file_areas` if it supports saving of any files to moodle - this allows the file areas to be browsed by the moodle file manager. - -#### delete_instance() - -```php -public function delete_instance() { - global $DB; - // will throw exception on failure - $DB->delete_records('assignfeedback_file', [ - 'assignment' => $this->assignment->get_instance()->id, - ]); - - return true; -} -``` - -This function is called when a plugin is deleted. Note only database records need to be cleaned up - files belonging to fileareas for this assignment will be automatically cleaned up. - -#### Gradebook features - -```php -public function format_for_gradebook(stdClass $grade) { - return FORMAT_MOODLE; -} - -public function text_for_gradebook(stdClass $grade) { - return ''; -} -``` - -Only one feedback plugin can push comments to the gradebook. Usually this is the feedback_comments plugin - but it can be configured to be any feedback plugin. If the current plugin is the plugin chosen to generate comments for the gradebook, the comment text and format will be taken from these two functions. - -```php -/** - * Override to indicate a plugin supports quickgrading - * - * @return boolean - True if the plugin supports quickgrading - */ -public function supports_quickgrading() { - return false; -} - -/** - * Get quickgrading form elements as html - * - * @param int $userid The user id in the table this quickgrading element relates to - * @param mixed $grade grade or null - The grade data. May be null if there are no grades for this user (yet) - * @return mixed - A html string containing the html form elements required for quickgrading or false to indicate this plugin does not support quickgrading - */ -public function get_quickgrading_html($userid, $grade) { - return false; -} - -/** - * Has the plugin quickgrading form element been modified in the current form submission? - * - * @param int $userid The user id in the table this quickgrading element relates to - * @param stdClass $grade The grade - * @return boolean - true if the quickgrading form element has been modified - */ -public function is_quickgrading_modified($userid, $grade) { - return false; -} - -/** - * Save quickgrading changes - * - * @param int $userid The user id in the table this quickgrading element relates to - * @param stdClass $grade The grade - * @return boolean - true if the grade changes were saved correctly - */ -public function save_quickgrading_changes($userid, $grade) { - return false; -} -``` - -These 4 functions can be implemented to allow a plugin to support quick-grading. The feedback comments plugin is the only example of this in core. - -```php -/** - * Run cron for this plugin - */ -public static function cron() { -} -``` - -A plugin can run code when cron runs by implementing this method. - -```php -/** - * Return a list of the grading actions supported by this plugin. - * - * A grading action is a page that is not specific to a user but to the whole assignment. - * @return array - An array of action and description strings. - * The action will be passed to grading_action. - */ -public function get_grading_actions() { - return []; -} - -/** - * Show a grading action form - * - * @param string $gradingaction The action chosen from the grading actions menu - * @return string The page containing the form - */ -public function grading_action($gradingaction) { - return ''; -} -``` - -Grading actions appear in the select menu above the grading table and apply to the whole assignment. An example is "Upload grading worksheet". When a grading action is selected, the grading_action will be called with the action that was chosen (so plugins can have multiple entries in the list). - -```php -/** - * Return a list of the batch grading operations supported by this plugin. - * - * @return array - An array of action and description strings. - * The action will be passed to grading_batch_operation. - */ -public function get_grading_batch_operations() { - return []; -} - -/** - * Show a batch operations form - * - * @param string $action The action chosen from the batch operations menu - * @param array $users The list of selected userids - * @return string The page containing the form - */ -public function grading_batch_operation($action, $users) { - return ''; -} -``` - -These two callbacks allow adding entries to the batch grading operations list (where you select multiple users in the table and choose e.g. "Lock submissions" for every user). The action is passed to "grading_batch_operation" so that multiple entries can be supported by a plugin. - -## Other features - -### Add calendar events - - - -From Moodle 3.1 onwards, feedback plugins can add events to the Moodle calendar without side effects. These will be hidden and deleted in line with the assignment module. For example: - -```php -// Add release date to calendar -$calendarevent = new stdClass(); -$calendarevent->name = get_string('calendareventname', 'assignsubmission_something'); -$calendarevent->description = get_string('calendareventdesc', 'assignsubmission_something'); -$calendarevent->courseid = $courseid; -$calendarevent->groupid = 0; -$calendarevent->userid = $userid; -$calendarevent->modulename = 'assign'; -$calendarevent->instance = $instanceid; -$calendarevent->eventtype = 'something_release'; // For activity module's events, this can be used to set the alternative text of the event icon. Set it to 'pluginname' unless you have a better string. -$calendarevent->timestart = $releasedate; -$calendarevent->visible = true; -$calendarevent->timeduration = 0; - -calendar_event::create($calendarevent); -``` diff --git a/versioned_docs/version-4.2/apis/plugintypes/assign/index.md b/versioned_docs/version-4.2/apis/plugintypes/assign/index.md deleted file mode 100644 index 120ab233f0..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/assign/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Assignment sub-plugins -tags: - - Assign - - Assignment - - Subplugin - - Plugintype ---- - -The `mod_assign` activity can be extended using two sub-plugin types, namely: - -- submission plugins, used to provide different ways for students to submit their content -- feedback plugins, used to extend the ways in which feedback may be provided to students on their submissions diff --git a/versioned_docs/version-4.2/apis/plugintypes/assign/submission.md b/versioned_docs/version-4.2/apis/plugintypes/assign/submission.md deleted file mode 100644 index 6f153d1c2d..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/assign/submission.md +++ /dev/null @@ -1,656 +0,0 @@ ---- -title: Assign submission plugins -tags: - - Assign - - Assignment - - Submission - - Subplugin -toc_max_heading_level: 4 -description: Assign submission plugins allow you to define different ways for a student to submit their work ---- - -import { - SettingsPHP, - LocalLib, -} from '../../_files'; -export const plugintype = 'assignsubmission'; - -An assignment submission plugin is used to display custom form fields to a student when they are editing their assignment submission. It also has full control over the display the submitted assignment to graders and students. - -:::tip - -For a good reference implementation, see the [onlinetext](https://github.com/moodle/moodle/tree/main/mod/assign/submission/onlinetext) submission plugin included with core because it uses most of the features of submission plugins. - -::: - -## File structure - -Assignment Feedback plugins are located in the `/mod/assign/submission` directory. A plugin should not include any custom files outside of it's own plugin folder. - -:::important Plugin naming - -The plugin name should be no longer than 11 characters - this is because the database tables for a submission plugin must be prefixed with `assignsubmission_[pluginname]` (17 chars + X) and the table names can be no longer than 28 chars due to a limitation with Oracle. - -If a plugin requires multiple database tables, the plugin name will need to be shorter to allow different table names to fit under the 28 character limit. - -::: - -Each plugin is in a separate subdirectory and consists of a number of _mandatory files_ and any other files the developer is going to use. - -:::important - -Some of the important files are described below. See the [common plugin files](../../commonfiles/index.mdx) documentation for details of other files which may be useful in your plugin. - -::: - -
    - View an example directory layout for the `assignfeedback_file` plugin. - -```console -mod/assign/submission/file -├── backup -│   └── moodle2 -│   ├── backup_assignsubmission_file_subplugin.class.php -│   └── restore_assignsubmission_file_subplugin.class.php -├── classes -│   ├── event -│   │   ├── assessable_uploaded.php -│   │   ├── submission_created.php -│   │   └── submission_updated.php -│   └── privacy -│   └── provider.php -├── db -│   ├── access.php -│   └── install.xml -├── lang -│   └── en -│   └── assignsubmission_file.php -├── lib.php -├── locallib.php -├── settings.php -└── version.php -``` - -
    - -### settings.php - - - - - - -import settingsExample from '!!raw-loader!./_files/submission_settings.php'; - -export const settingsExtra = ` -All submission plugins should include one setting named 'default' to indicate if the plugin should be enabled by default when creating a new assignment. -`; - - - - - -:::info - -This example from the submission_file plugin also checks to see if there is a maxbytes setting for this moodle installation and, if found, adds a new admin setting to the settings page. - -::: - -### locallib.php - - - - - - - - -This is where all the functionality for this plugin is defined. We will step through this file and describe each part as we go. - -```php -class assign_submission_file extends assign_submission_plugin { -``` - -All submission plugins MUST define a class with the component name of the plugin that extends assign_submission_plugin. - -#### get_name() - -```php -public function get_name() { - return get_string('file', 'assignsubmission_file'); -} -``` - -Get name is abstract in submission_plugin and must be defined in your new plugin. Use the language strings to make your plugin translatable. - -#### get_settings() - -```php -public function get_settings(MoodleQuickForm $mform) { - global $CFG, $COURSE; - - $defaultmaxfilesubmissions = $this->get_config('maxfilesubmissions'); - $defaultmaxsubmissionsizebytes = $this->get_config('maxsubmissionsizebytes'); - - $settings = []; - $options = []; - for ($i = 1; $i <= ASSIGNSUBMISSION_FILE_MAXFILES; $i++) { - $options[$i] = $i; - } - - $name = get_string('maxfilessubmission', 'assignsubmission_file'); - $mform->addElement('select', 'assignsubmission_file_maxfiles', $name, $options); - $mform->addHelpButton( - 'assignsubmission_file_maxfiles', - 'maxfilessubmission', - 'assignsubmission_file' - ); - $mform->setDefault('assignsubmission_file_maxfiles', $defaultmaxfilesubmissions); - $mform->disabledIf('assignsubmission_file_maxfiles', 'assignsubmission_file_enabled', 'notchecked'); - - $choices = get_max_upload_sizes( - $CFG->maxbytes, - $COURSE->maxbytes, - get_config('assignsubmission_file', 'maxbytes') - ); - - $settings[] = [ - 'type' => 'select', - 'name' => 'maxsubmissionsizebytes', - 'description' => get_string('maximumsubmissionsize', 'assignsubmission_file'), - 'options'=> $choices, - 'default'=> $defaultmaxsubmissionsizebytes, - ]; - - $name = get_string('maximumsubmissionsize', 'assignsubmission_file'); - $mform->addElement('select', 'assignsubmission_file_maxsizebytes', $name, $choices); - $mform->addHelpButton( - 'assignsubmission_file_maxsizebytes', - 'maximumsubmissionsize', - 'assignsubmission_file' - ); - $mform->setDefault('assignsubmission_file_maxsizebytes', $defaultmaxsubmissionsizebytes); - $mform->disabledIf( - 'assignsubmission_file_maxsizebytes', - 'assignsubmission_file_enabled', - 'notchecked' - ); -} -``` - -The "get_settings" function is called when building the settings page for the assignment. It allows this plugin to add a list of settings to the form. Notice that the settings are prefixed by the plugin name which is good practice to avoid conflicts with other plugins. - -#### save_settings() - -```php -public function save_settings(stdClass $data) { - $this->set_config('maxfilesubmissions', $data->assignsubmission_file_maxfiles); - $this->set_config('maxsubmissionsizebytes', $data->assignsubmission_file_maxsizebytes); - return true; -} -``` - -The "save_settings" function is called when the assignment settings page is submitted, either for a new assignment or when editing an existing one. For settings specific to a single instance of the assignment you can use the assign_plugin::set_config function shown here to save key/value pairs against this assignment instance for this plugin. - -#### get_form_elements() - -```php -public function get_form_elements($submission, MoodleQuickForm $mform, stdClass $data) { - if ($this->get_config('maxfilesubmissions') <= 0) { - return false; - } - - $fileoptions = $this->get_file_options(); - $submissionid = $submission ? $submission->id : 0; - - $data = file_prepare_standard_filemanager( - $data, - 'files', - $fileoptions, - $this->assignment->get_context(), - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $submissionid - ); - - $mform->addElement( - 'filemanager', - 'files_filemanager', - html_writer::tag('span', $this->get_name(), ['class' => 'accesshide']), - null, - $fileoption - ); - - return true; -} -``` - -The get_form_elements function is called when building the submission form. It functions identically to the get_settings function except that the submission object is available (if there is a submission) to associate the settings with a single submission. This example also shows how to use a filemanager within a submission plugin. The function must return true if it has modified the form otherwise the assignment will not include a header for this plugin. - -#### save() - -```php -public function save(stdClass $submission, stdClass $data) { - global $USER, $DB; - - $fileoptions = $this->get_file_options(); - - $data = file_postupdate_standard_filemanager( - $data, - 'files', - $fileoptions, - $this->assignment->get_context(), - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $submission->id - ); - - $filesubmission = $this->get_file_submission($submission->id); - - // Plagiarism code event trigger when files are uploaded. - - $fs = get_file_storage(); - $files = $fs->get_area_files( - $this->assignment->get_context()->id, - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $submission->id, - 'id', - false - ); - - $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); - - // Send files to event system. - // This lets Moodle know that an assessable file was uploaded (eg for plagiarism detection). - $eventdata = new stdClass(); - $eventdata->modulename = 'assign'; - $eventdata->cmid = $this->assignment->get_course_module()->id; - $eventdata->itemid = $submission->id; - $eventdata->courseid = $this->assignment->get_course()->id; - $eventdata->userid = $USER->id; - if ($count > 1) { - $eventdata->files = $files; - } - $eventdata->file = $files; - $eventdata->pathnamehashes = array_keys($files); - events_trigger('assessable_file_uploaded', $eventdata); - - if ($filesubmission) { - $filesubmission->numfiles = $this->count_files($submission->id, - ASSIGNSUBMISSION_FILE_FILEAREA); - return $DB->update_record('assignsubmission_file', $filesubmission); - } else { - $filesubmission = new stdClass(); - $filesubmission->numfiles = $this->count_files($submission->id, - ASSIGNSUBMISSION_FILE_FILEAREA); - $filesubmission->submission = $submission->id; - $filesubmission->assignment = $this->assignment->get_instance()->id; - return $DB->insert_record('assignsubmission_file', $filesubmission) > 0; - } -``` - -The "save" function is called to save a user submission. The parameters are the submission object and the data from the submission form. This example calls `file_postupdate_standard_filemanager` to copy the files from the draft file area to the filearea for this submission, it then uses the event api to trigger an assessable_file_uploaded event for the plagiarism api. It then records the number of files in the plugin specific "assignsubmission_file" table. - -#### get_files() - -```php -public function get_files($submission) { - $result = []; - $fs = get_file_storage(); - - $files = $fs->get_area_files( - $this->assignment->get_context()->id, - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $submission->id, - 'timemodified', - false - ); - - foreach ($files as $file) { - $result[$file->get_filename()] = $file; - } - return $result; -} -``` - -If this submission plugin produces one or more files, it should implement "get_files" so that the portfolio API can export a list of all the files from all of the plugins for this assignment submission. This is also used by the offline grading feature in the assignment. - -#### view_summary() - -```php -public function view_summary(stdClass $submission, & $showviewlink) { - $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); - - // Show we show a link to view all files for this plugin. - $showviewlink = $count > ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES; - if ($count <= ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES) { - return $this->assignment->render_area_files( - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $submission->id - ); - } - - return get_string('countfiles', 'assignsubmission_file', $count); -} -``` - -The view_summary function is called to display a summary of the submission to both markers and students. It counts the number of files submitted and if it is more that a set number, it only displays a count of how many files are in the submission - otherwise it uses a helper function to write the entire list of files. This is because we want to keep the summaries really short so they can be displayed in a table. There will be a link to view the full submission on the submission status page. - -#### view() - -```php -public function view($submission) { - return $this->assignment->render_area_files( - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $submission->id - ); -} -``` - -The view function is called to display the entire submission to both markers and students. In this case it uses the helper function in the assignment class to write the list of files. - -#### can_upgrade() - -```php -public function can_upgrade($type, $version) { - $uploadsingle_type ='uploadsingle'; - $upload_type ='upload'; - - if (($type == $uploadsingle_type || $type == $upload_type) && $version >= 2011112900) { - return true; - } - return false; -} -``` - -The can_upgrade function is used to identify old "Assignment 2.2" subtypes that can be upgraded by this plugin. This plugin supports upgrades from the old "upload" and "uploadsingle" assignment subtypes. - -#### upgrade_settings() - -```php -public function upgrade_settings(context $oldcontext, stdClass $oldassignment, &$log) { - global $DB; - - if ($oldassignment->assignmenttype == 'uploadsingle') { - $this->set_config('maxfilesubmissions', 1); - $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes); - return true; - } - - if ($oldassignment->assignmenttype == 'upload') { - $this->set_config('maxfilesubmissions', $oldassignment->var1); - $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes); - - // Advanced file upload uses a different setting to do the same thing. - $DB->set_field( - 'assign', - 'submissiondrafts', - $oldassignment->var4, - ['id' => $this->assignment->get_instance()->id] - ); - - // Convert advanced file upload "hide description before due date" setting. - $alwaysshow = 0; - if (!$oldassignment->var3) { - $alwaysshow = 1; - } - $DB->set_field( - 'assign', - 'alwaysshowdescription', - $alwaysshow, - ['id' => $this->assignment->get_instance()->id] - ); - return true; - } -} -``` - -This function is called once per assignment instance to upgrade the settings from the old assignment to the new mod_assign. In this case it sets the `maxbytes`, `maxfiles` and `alwaysshowdescription` configuration settings. - -#### upgrade() - -```php -public function upgrade($oldcontext, $oldassignment, $oldsubmission, $submission, &$log) { - global $DB; - - $filesubmission = (object) [ - 'numfiles' => $oldsubmission->numfiles, - 'submission' => $submission->id, - 'assignment' => $this->assignment->get_instance()->id, - ]; - - if (!$DB->insert_record('assign_submission_file', $filesubmission) > 0) { - $log .= get_string('couldnotconvertsubmission', 'mod_assign', $submission->userid); - return false; - } - - // now copy the area files - $this->assignment->copy_area_files_for_upgrade( - $oldcontext->id, - 'mod_assignment', - 'submission', - $oldsubmission->id, - // New file area - $this->assignment->get_context()->id, - 'mod_assign', - ASSIGN_FILEAREA_SUBMISSION_FILES, - $submission->id - ); - - return true; -} -``` - -The "upgrade" function upgrades a single submission from the old assignment type to the new one. In this case it involves copying all the files from the old filearea to the new one. There is a helper function available in the assignment class for this (Note: the copy will be fast as it is just adding rows to the files table). If this function returns false, the upgrade will be aborted and rolled back. - -#### get_editor_fields() - -```php -public function () { - return [ - 'onlinetext' => get_string('pluginname', 'assignsubmission_comments'), - ]; -} -``` - -This example is from assignsubmission_onlinetext. If the plugin uses a text-editor it is ideal if the plugin implements "get_editor_fields". This allows the portfolio to retrieve the text from the plugin when exporting the list of files for a submission. This is required because the text is stored in the plugin specific table that is only known to the plugin itself. If a plugin supports multiple text areas it can return the name of each of them here. - -#### get_editor_text() - -```php -public function get_editor_text($name, $submissionid) { - if ($name == 'onlinetext') { - $onlinetextsubmission = $this->get_onlinetext_submission($submissionid); - if ($onlinetextsubmission) { - return $onlinetextsubmission->onlinetext; - } - } - - return ''; -} -``` - -This example is from assignsubmission_onlinetext. If the plugin uses a text-editor it is ideal if the plugin implements "get_editor_text". This allows the portfolio to retrieve the text from the plugin when exporting the list of files for a submission. This is required because the text is stored in the plugin specific table that is only known to the plugin itself. The name is used to distinguish between multiple text areas in the one plugin. - -#### get_editor_format() - -```php -public function get_editor_format($name, $submissionid) { - if ($name == 'onlinetext') { - $onlinetextsubmission = $this->get_onlinetext_submission($submissionid); - if ($onlinetextsubmission) { - return $onlinetextsubmission->onlineformat; - } - } - - return 0; -} -``` - -This example is from assignsubmission_onlinetext. For the same reason as the previous function, if the plugin uses a text editor, it is ideal if the plugin implements "get_editor_format". This allows the portfolio to retrieve the text from the plugin when exporting the list of files for a submission. This is required because the text is stored in the plugin specific table that is only known to the plugin itself. The name is used to distinguish between multiple text areas in the one plugin. - -#### is_empty() - -```php -public function is_empty(stdClass $submission) { - return $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA) == 0; -} -``` - -If a plugin has no submission data to show - it can return true from the is_empty function. This prevents a table row being added to the submission summary for this plugin. It is also used to check if a student has tried to save an assignment with no data. - -#### submission_is_empty() - -```php -public function submission_is_empty() { - global $USER; - $fs = get_file_storage(); - - // Get a count of all the draft files, excluding any directories. - $files = $fs->get_area_files( - context_user::instance($USER->id)->id, - 'user', - 'draft', - $data->files_filemanager, - 'id', - false - ); - - return count($files) == 0; -} -``` - -Determine if a submission is empty. This is distinct from is_empty() in that it is intended to be used to determine if a submission made before saving is empty. - -#### get_file_areas() - -```php -public function get_file_areas() { - return [ASSIGNSUBMISSION_FILE_FILEAREA=>$this->get_name()]; -} -``` - -A plugin should implement get_file_areas if it supports saving of any files to moodle - this allows the file areas to be browsed by the moodle file manager. - -#### copy_submission() - -```php -public function copy_submission(stdClass $sourcesubmission, stdClass $destsubmission) { - global $DB; - - // Copy the files across. - $contextid = $this->assignment->get_context()->id; - $fs = get_file_storage(); - $files = $fs->get_area_files( - $contextid, - 'assignsubmission_file', - ASSIGNSUBMISSION_FILE_FILEAREA, - $sourcesubmission->id, - 'id', - false - ); - foreach ($files as $file) { - $fieldupdates = ['itemid' => $destsubmission->id]; - $fs->create_file_from_storedfile($fieldupdates, $file); - } - - // Copy the assignsubmission_file record. - if ($filesubmission = $this->get_file_submission($sourcesubmission->id)) { - unset($filesubmission->id); - $filesubmission->submission = $destsubmission->id; - $DB->insert_record('assignsubmission_file', $filesubmission); - } - return true; -} -``` - -Since Moodle 2.5 - a students submission can be copied to create a new submission attempt. Plugins should implement this function if they store data associated with the submission (most plugins). - -#### format_for_log() - -```php -public function format_for_log(stdClass $submission) { - // Format the information for each submission plugin add_to_log - $filecount = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); - return ' the number of file(s) : ' . $filecount . " file(s).
    "; -} -``` - -The format_for_log function lets a plugin produce a really short summary of a submission suitable for adding to a log message. - -#### delete_instance() - -```php -public function delete_instance() { - global $DB; - // Will throw exception on failure - $DB->delete_records('assignsubmission_file', [ - 'assignment'=>$this->assignment->get_instance()->id, - ]); - - return true; -} -``` - -The delete_instance function is called when a plugin is deleted. Note only database records need to be cleaned up - files belonging to fileareas for this assignment will be automatically cleaned up. - -## Useful classes - -A submission plugin has access to a number of useful classes in the assignment module. See the phpdocs (or the code) for more information on these classes. - -### assign_plugin - -This abstract class is the base class for all assignment plugins (feedback or submission plugins). - -It provides access to the assign class which represents the current assignment instance through "$this->assignment". - -### assign_submission_plugin - -This is the base class all assignment submission plugins must extend. It contains a small number of additional function that only apply to submission plugins. - -### assign - -This is the main class for interacting with the assignment module. - -It contains public functions that are useful for listing users, loading and updating submissions, loading and updating grades, displaying users etc. - -## Other features - -### Add calendar events - - - -Submission plugins can add events to the Moodle calendar without side effects. These will be hidden and deleted in line with the assignment module. For example: - -```php -// Add release date to calendar. -$calendarevent = new stdClass(); -$calendarevent->name = get_string('calendareventname', 'assignsubmission_something'); -$calendarevent->description = get_string('calendareventdesc', 'assignsubmission_something'); -$calendarevent->courseid = $courseid; -$calendarevent->groupid = 0; -$calendarevent->userid = $userid; -$calendarevent->modulename = 'assign'; -$calendarevent->instance = $instanceid; -$calendarevent->eventtype = 'something_release'; // For activity module's events, this can be used to set the alternative text of the event icon. Set it to 'pluginname' unless you have a better string. -$calendarevent->timestart = $releasedate; -$calendarevent->visible = true; -$calendarevent->timeduration = 0; - -calendar_event::create($calendarevent); -``` - -This code should be placed in the `save_settings()` method of your assign_submission_plugin class. diff --git a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.md b/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.md deleted file mode 100644 index e2b7e9c1b6..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.md +++ /dev/null @@ -1,4 +0,0 @@ - -The plugin must implement a YUI module that will be included by the editor when the page loads. - -That YUI module **must** be named `button` and must create a namespaced class in `Y.M.[plugin name]`. diff --git a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.tsx b/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.tsx deleted file mode 100644 index 011667eb0c..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/button.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) Moodle Pty Ltd. - * - * 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 . - */ -import React from 'react'; -import { ComponentFileSummary } from '../../../../_utils'; -import type { Props } from '../../../../_utils'; - -const defaultExample = `Y.namespace('M.atto_media').Button = Y.Base.create( - 'button', - Y.M.editor_atto.EditorPlugin, - [], - { - initializer: function() { - this.addButton({ - callback: this._toggleMedia, - icon: 'e/media', - inlineFormat: true, - - // Key code for the keyboard shortcut which triggers this button: - keys: '66', - - // Watch the following tags and add/remove highlighting as appropriate: - tags: 'media' - }); - }, - - _toggleMedia: function() { - // Handle the button click here. - // You can fetch any passed in parameters here as follows: - var langs = this.get('langs'); - } - }, { - ATTRS: { - // If any parameters were defined in the 'params_for_js' function, - // they should be defined here for proper access. - langs: { - value: ['Default', 'Value'] - } - } - } -); -`; -import ButtonDescription from './button.md'; - -export default (initialProps: Props): ComponentFileSummary => ( - -); diff --git a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.md b/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.md deleted file mode 100644 index b303cf986e..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.md +++ /dev/null @@ -1,7 +0,0 @@ - -An optional file which can be used to implement optional component callbacks. - -The available callbacks are: - -- `atto_[pluginname]_strings_for_js` - To add strings required by the YUI code -- `atto_[pluginname]_params_for_js` - To get the parameters required to instantiate the plugin diff --git a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.php b/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.php deleted file mode 100644 index ef29ea076f..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/atto/_examples/lib.php +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Initialise the js strings required for this plugin. - */ -function atto_media_strings_for_js(): void { - global $PAGE; - - $PAGE->requires->strings_for_js([ - 'add', - 'width', - ], 'atto_media'); -} - -/** - * Sends the parameters to the JS module. - * - * @return array - */ -function atto_media_params_for_js(): array { - global $OUTPUT, $PAGE; - $currentlang = current_language(); - $langsinstalled = get_string_manager()->get_list_of_translations(true); - $params = [ - 'langs' => [ - 'installed' => [], - ], - ]; - - foreach ($langsinstalled as $code => $name) { - $params['langs']['installed'][] = [ - 'lang' => $name, - 'code' => $code, - 'default' => $currentlang == $code, - ]; - } - - return $params; -} diff --git a/versioned_docs/version-4.2/apis/plugintypes/atto/index.md b/versioned_docs/version-4.2/apis/plugintypes/atto/index.md deleted file mode 100644 index 0a7e3e2d74..0000000000 --- a/versioned_docs/version-4.2/apis/plugintypes/atto/index.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Atto -tags: [] ---- - - - -Atto is a JavaScript text editor built specifically for Moodle. It is the default text editor in Moodle from 2.7 onwards, and is implemented as a standard Moodle [text editor plugin](https://docs.moodle.org/dev/Editors). Most of the code is written in JavaScript using YUI modules. - -All of the buttons in Atto are implemented as Moodle subplugins. This means that the subplugins can do anything a subplugin can do including, using language strings, database tables, other JavaScript, and more. - -:::caution Sunset of Atto - -A new Editor was created for Moodle 4.1 and later using the latest version of TinyMCE. - -It is likely that Atto will be removed in Moodle 4.6. - -::: - -## File structure - -import { - Lang, - Lib, - VersionPHP, -} from '../../_files'; -import Button from './_examples/button'; - -Atto plugins are located in the `/lib/editor/atto/plugins` directory. - -Each plugin is in a separate subdirectory and consists of a number of _mandatory files_ and any other files the developer is going to use. - -
    - View an example directory layout for the `atto_media` plugin. - -```console - lib/editor/atto/plugins/media - |-- db - | └-- upgrade.php - |-- lang - | └-- en - | └-- atto_media.php - |-- yui - | └-- src - | └-- button - | └-- atto_media.php - | ├── build.json - | ├── js - | │   └── button.js - | └── meta - | └── button.json - |-- settings.php - └-- version.php -``` - -
    - -Some of the important files for the Atto plugintype are described below. See the [common plugin files](../commonfiles) documentation for details of other files which may be useful in your plugin. - -### version.php - - - -### lib.php - -import LibExample from '!!raw-loader!./_examples/lib.php'; -import LibDescription from './_examples/lib.md'; - - - -### yui/src/button/* - - - -